xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision e19eea1e8ef2f2e87fef29614f09a0daeb89e955)
1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2669c8de6SAlfredo Cardigliano  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3669c8de6SAlfredo Cardigliano  */
4669c8de6SAlfredo Cardigliano 
5669c8de6SAlfredo Cardigliano #include <rte_malloc.h>
6df96fd0dSBruce Richardson #include <ethdev_driver.h>
7669c8de6SAlfredo Cardigliano 
8669c8de6SAlfredo Cardigliano #include "ionic.h"
9669c8de6SAlfredo Cardigliano #include "ionic_logs.h"
10669c8de6SAlfredo Cardigliano #include "ionic_lif.h"
11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h"
1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h"
13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h"
14669c8de6SAlfredo Cardigliano 
15c5d15850SAndrew Boyer /* queuetype support level */
16c5d15850SAndrew Boyer static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = {
17c5d15850SAndrew Boyer 	[IONIC_QTYPE_ADMINQ]  = 0,   /* 0 = Base version with CQ support */
18c5d15850SAndrew Boyer 	[IONIC_QTYPE_NOTIFYQ] = 0,   /* 0 = Base version */
19c5d15850SAndrew Boyer 	[IONIC_QTYPE_RXQ]     = 2,   /* 0 = Base version with CQ+SG support
20c5d15850SAndrew Boyer 				      * 1 =       ... with EQ
21c5d15850SAndrew Boyer 				      * 2 =       ... with CMB
22c5d15850SAndrew Boyer 				      */
23c5d15850SAndrew Boyer 	[IONIC_QTYPE_TXQ]     = 3,   /* 0 = Base version with CQ+SG support
24c5d15850SAndrew Boyer 				      * 1 =   ... with Tx SG version 1
25c5d15850SAndrew Boyer 				      * 2 =       ... with EQ
26c5d15850SAndrew Boyer 				      * 3 =       ... with CMB
27c5d15850SAndrew Boyer 				      */
28c5d15850SAndrew Boyer };
29c5d15850SAndrew Boyer 
30598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
31598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
32598f6726SAlfredo Cardigliano 
3301a6c311SAlfredo Cardigliano int
3401a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq)
3501a6c311SAlfredo Cardigliano {
3601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
374ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
3801a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
3901a6c311SAlfredo Cardigliano 		.pending_work = true,
4001a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4101a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4201a6c311SAlfredo Cardigliano 			.type = q->type,
4309f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4401a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
4501a6c311SAlfredo Cardigliano 		},
4601a6c311SAlfredo Cardigliano 	};
4701a6c311SAlfredo Cardigliano 
4801a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4901a6c311SAlfredo Cardigliano }
5001a6c311SAlfredo Cardigliano 
5101a6c311SAlfredo Cardigliano int
5201a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
5301a6c311SAlfredo Cardigliano {
5401a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
554ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
5601a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
5701a6c311SAlfredo Cardigliano 		.pending_work = true,
5801a6c311SAlfredo Cardigliano 		.cmd.q_control = {
5901a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
6001a6c311SAlfredo Cardigliano 			.type = q->type,
6109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
6201a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
6301a6c311SAlfredo Cardigliano 		},
6401a6c311SAlfredo Cardigliano 	};
6501a6c311SAlfredo Cardigliano 
6601a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6701a6c311SAlfredo Cardigliano }
6801a6c311SAlfredo Cardigliano 
69be63459eSAndrew Boyer void
70be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
71598f6726SAlfredo Cardigliano {
72a0a99f21SAndrew Boyer 	uint32_t i;
73a0a99f21SAndrew Boyer 
74be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
75598f6726SAlfredo Cardigliano 
76be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
77a0a99f21SAndrew Boyer 
78a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
79be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
80a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
81a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
82a0a99f21SAndrew Boyer 	}
83a0a99f21SAndrew Boyer 
84a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
85be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
86a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
87a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
88a0a99f21SAndrew Boyer 	}
89598f6726SAlfredo Cardigliano }
90598f6726SAlfredo Cardigliano 
91598f6726SAlfredo Cardigliano void
92598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
93598f6726SAlfredo Cardigliano {
94598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
9575f96902SAndrew Boyer 	int err;
96598f6726SAlfredo Cardigliano 
97598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
98598f6726SAlfredo Cardigliano 
9900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
10075f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
10175f96902SAndrew Boyer 	if (err)
1024ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
103598f6726SAlfredo Cardigliano }
104598f6726SAlfredo Cardigliano 
1053cdfd905SAlfredo Cardigliano static void
1063cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
1073cdfd905SAlfredo Cardigliano {
1083cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
1093cdfd905SAlfredo Cardigliano 	uint32_t i;
1103cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
1113cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1123cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
1133cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1143cdfd905SAlfredo Cardigliano 
1153cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1163cdfd905SAlfredo Cardigliano 
1173cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1183cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1193cdfd905SAlfredo Cardigliano 			lif->port_id);
1203cdfd905SAlfredo Cardigliano 		return;
1213cdfd905SAlfredo Cardigliano 	}
1223cdfd905SAlfredo Cardigliano 
1233cdfd905SAlfredo Cardigliano 	/* RX */
1243cdfd905SAlfredo Cardigliano 
1253cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1263cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1273cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1283cdfd905SAlfredo Cardigliano 
1293cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1303cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1313cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1323cdfd905SAlfredo Cardigliano 
1333cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
134be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1353cdfd905SAlfredo Cardigliano 		stats->imissed +=
1363cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1373cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1383cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1393cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1403cdfd905SAlfredo Cardigliano 	}
1413cdfd905SAlfredo Cardigliano 
1423cdfd905SAlfredo Cardigliano 	stats->imissed +=
1433cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1443cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1453cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1463cdfd905SAlfredo Cardigliano 
1473cdfd905SAlfredo Cardigliano 	stats->imissed +=
1483cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
1493cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1503cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
1513cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1523cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1533cdfd905SAlfredo Cardigliano 
1543cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
155be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1563cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1573cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1583cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1593cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1603cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1613cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1623cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1633cdfd905SAlfredo Cardigliano 	}
1643cdfd905SAlfredo Cardigliano 
1653cdfd905SAlfredo Cardigliano 	/* TX */
1663cdfd905SAlfredo Cardigliano 
1673cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1683cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1693cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1703cdfd905SAlfredo Cardigliano 
1713cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1723cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1733cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1743cdfd905SAlfredo Cardigliano 
1753cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
176be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1773cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1783cdfd905SAlfredo Cardigliano 	}
1793cdfd905SAlfredo Cardigliano 
1803cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1813cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1823cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1833cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1843cdfd905SAlfredo Cardigliano 
1853cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1863cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1873cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1883cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1893cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1903cdfd905SAlfredo Cardigliano 
1913cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
192be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1933cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1943cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1953cdfd905SAlfredo Cardigliano 	}
1963cdfd905SAlfredo Cardigliano }
1973cdfd905SAlfredo Cardigliano 
1983cdfd905SAlfredo Cardigliano void
1993cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
2003cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
2013cdfd905SAlfredo Cardigliano {
2023cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
2033cdfd905SAlfredo Cardigliano 
2043cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
2053cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
2063cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
2073cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
2083cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
2093cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
2103cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
2113cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
2123cdfd905SAlfredo Cardigliano }
2133cdfd905SAlfredo Cardigliano 
2143cdfd905SAlfredo Cardigliano void
2153cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2163cdfd905SAlfredo Cardigliano {
2173cdfd905SAlfredo Cardigliano 	uint32_t i;
2183cdfd905SAlfredo Cardigliano 
2193cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
220be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
2213cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
222be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
2233cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2243cdfd905SAlfredo Cardigliano 	}
2253cdfd905SAlfredo Cardigliano 
2263cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2273cdfd905SAlfredo Cardigliano }
2283cdfd905SAlfredo Cardigliano 
2293cdfd905SAlfredo Cardigliano void
2303cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2313cdfd905SAlfredo Cardigliano {
2323cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2333cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2343cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2353cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2363cdfd905SAlfredo Cardigliano 
2373cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2383cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2393cdfd905SAlfredo Cardigliano }
2403cdfd905SAlfredo Cardigliano 
2413cdfd905SAlfredo Cardigliano void
2423cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2433cdfd905SAlfredo Cardigliano {
2443cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2453cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2463cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2473cdfd905SAlfredo Cardigliano 
2483cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2493cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2503cdfd905SAlfredo Cardigliano }
2513cdfd905SAlfredo Cardigliano 
252598f6726SAlfredo Cardigliano static int
25354fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
254598f6726SAlfredo Cardigliano {
25554fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25654fe083fSAlfredo Cardigliano 		.pending_work = true,
25754fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
25854fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
25909f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
26054fe083fSAlfredo Cardigliano 		},
26154fe083fSAlfredo Cardigliano 	};
26254fe083fSAlfredo Cardigliano 	int err;
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
26554fe083fSAlfredo Cardigliano 
26654fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
26754fe083fSAlfredo Cardigliano 	if (err)
26854fe083fSAlfredo Cardigliano 		return err;
26954fe083fSAlfredo Cardigliano 
27054fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
27109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
27254fe083fSAlfredo Cardigliano 
27354fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
27454fe083fSAlfredo Cardigliano }
27554fe083fSAlfredo Cardigliano 
27654fe083fSAlfredo Cardigliano static int
27754fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
27854fe083fSAlfredo Cardigliano {
27954fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
28054fe083fSAlfredo Cardigliano 		.pending_work = true,
28154fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
28254fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
28354fe083fSAlfredo Cardigliano 		},
28454fe083fSAlfredo Cardigliano 	};
28554fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
28654fe083fSAlfredo Cardigliano 	int err;
28754fe083fSAlfredo Cardigliano 
28854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
28954fe083fSAlfredo Cardigliano 
29054fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
29154fe083fSAlfredo Cardigliano 
29254fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
29354fe083fSAlfredo Cardigliano 	if (!f) {
29454fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
29554fe083fSAlfredo Cardigliano 		return -ENOENT;
29654fe083fSAlfredo Cardigliano 	}
29754fe083fSAlfredo Cardigliano 
29809f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
29954fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
30054fe083fSAlfredo Cardigliano 
30154fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
30254fe083fSAlfredo Cardigliano 
30354fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
30454fe083fSAlfredo Cardigliano 	if (err)
30554fe083fSAlfredo Cardigliano 		return err;
30654fe083fSAlfredo Cardigliano 
30754fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
30809f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
309598f6726SAlfredo Cardigliano 
310598f6726SAlfredo Cardigliano 	return 0;
311598f6726SAlfredo Cardigliano }
312598f6726SAlfredo Cardigliano 
31354fe083fSAlfredo Cardigliano int
31454fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
31554fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
31654fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
317598f6726SAlfredo Cardigliano {
31854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31954fe083fSAlfredo Cardigliano 
32054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
32154fe083fSAlfredo Cardigliano 
32254fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
32354fe083fSAlfredo Cardigliano }
32454fe083fSAlfredo Cardigliano 
32554fe083fSAlfredo Cardigliano void
32675f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
32754fe083fSAlfredo Cardigliano {
32854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32954fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
33075f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33354fe083fSAlfredo Cardigliano 
33454fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
33554fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
33654fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
33754fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
33854fe083fSAlfredo Cardigliano 		return;
33954fe083fSAlfredo Cardigliano 	}
34054fe083fSAlfredo Cardigliano 
34175f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
34275f96902SAndrew Boyer 
34375f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
34454fe083fSAlfredo Cardigliano 		return;
34554fe083fSAlfredo Cardigliano 
34675f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
34754fe083fSAlfredo Cardigliano }
34854fe083fSAlfredo Cardigliano 
34954fe083fSAlfredo Cardigliano int
35054fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
35154fe083fSAlfredo Cardigliano {
35254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
35354fe083fSAlfredo Cardigliano 
35454fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
35554fe083fSAlfredo Cardigliano 
35654fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
35754fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
35854fe083fSAlfredo Cardigliano 		return -1;
35954fe083fSAlfredo Cardigliano 	}
36054fe083fSAlfredo Cardigliano 
36154fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
36254fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
36354fe083fSAlfredo Cardigliano 			lif->mac_addr);
36454fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
36554fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
36654fe083fSAlfredo Cardigliano 	}
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
36954fe083fSAlfredo Cardigliano 
37054fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
37154fe083fSAlfredo Cardigliano 
37254fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
37354fe083fSAlfredo Cardigliano }
37454fe083fSAlfredo Cardigliano 
37554fe083fSAlfredo Cardigliano static int
37654fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
37754fe083fSAlfredo Cardigliano {
37854fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37954fe083fSAlfredo Cardigliano 		.pending_work = true,
38054fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
38154fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
38209f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
38309f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
38454fe083fSAlfredo Cardigliano 		},
38554fe083fSAlfredo Cardigliano 	};
38654fe083fSAlfredo Cardigliano 	int err;
38754fe083fSAlfredo Cardigliano 
38854fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
38954fe083fSAlfredo Cardigliano 	if (err)
39054fe083fSAlfredo Cardigliano 		return err;
39154fe083fSAlfredo Cardigliano 
39254fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
39309f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
39454fe083fSAlfredo Cardigliano 
39554fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
39654fe083fSAlfredo Cardigliano }
39754fe083fSAlfredo Cardigliano 
39854fe083fSAlfredo Cardigliano static int
39954fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
40054fe083fSAlfredo Cardigliano {
40154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
40254fe083fSAlfredo Cardigliano 		.pending_work = true,
40354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
40454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
40554fe083fSAlfredo Cardigliano 		},
40654fe083fSAlfredo Cardigliano 	};
40754fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
40854fe083fSAlfredo Cardigliano 	int err;
40954fe083fSAlfredo Cardigliano 
41054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
41154fe083fSAlfredo Cardigliano 
41254fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
41354fe083fSAlfredo Cardigliano 
41454fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
41554fe083fSAlfredo Cardigliano 	if (!f) {
41654fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
41754fe083fSAlfredo Cardigliano 		return -ENOENT;
41854fe083fSAlfredo Cardigliano 	}
41954fe083fSAlfredo Cardigliano 
42009f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
42154fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
42254fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
42354fe083fSAlfredo Cardigliano 
42454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
42554fe083fSAlfredo Cardigliano 	if (err)
42654fe083fSAlfredo Cardigliano 		return err;
42754fe083fSAlfredo Cardigliano 
42854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
42909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
430598f6726SAlfredo Cardigliano 
431598f6726SAlfredo Cardigliano 	return 0;
432598f6726SAlfredo Cardigliano }
433598f6726SAlfredo Cardigliano 
43454fe083fSAlfredo Cardigliano int
43554fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
43654fe083fSAlfredo Cardigliano 		int on)
43754fe083fSAlfredo Cardigliano {
43854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
43954fe083fSAlfredo Cardigliano 	int err;
44054fe083fSAlfredo Cardigliano 
44154fe083fSAlfredo Cardigliano 	if (on)
44254fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
44354fe083fSAlfredo Cardigliano 	else
44454fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
44554fe083fSAlfredo Cardigliano 
44654fe083fSAlfredo Cardigliano 	return err;
44754fe083fSAlfredo Cardigliano }
44854fe083fSAlfredo Cardigliano 
449598f6726SAlfredo Cardigliano static void
450598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
451598f6726SAlfredo Cardigliano {
452598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
453598f6726SAlfredo Cardigliano 		.pending_work = true,
454598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
455598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
45609f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
457598f6726SAlfredo Cardigliano 		},
458598f6726SAlfredo Cardigliano 	};
459598f6726SAlfredo Cardigliano 	int err;
460598f6726SAlfredo Cardigliano 
461598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
462598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
463598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
464598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
465598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
466598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
467598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
468598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
469598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
470598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
471598f6726SAlfredo Cardigliano 
472598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
473598f6726SAlfredo Cardigliano 	if (err)
474598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
475598f6726SAlfredo Cardigliano }
476598f6726SAlfredo Cardigliano 
477598f6726SAlfredo Cardigliano static void
478598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
479598f6726SAlfredo Cardigliano {
480598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
481598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
482598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
483598f6726SAlfredo Cardigliano 	}
484598f6726SAlfredo Cardigliano }
485598f6726SAlfredo Cardigliano 
48654fe083fSAlfredo Cardigliano int
48754fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
48854fe083fSAlfredo Cardigliano {
48954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49054fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
49354fe083fSAlfredo Cardigliano 
49454fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano 	return 0;
49954fe083fSAlfredo Cardigliano }
50054fe083fSAlfredo Cardigliano 
50154fe083fSAlfredo Cardigliano int
50254fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
50354fe083fSAlfredo Cardigliano {
50454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50554fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50654fe083fSAlfredo Cardigliano 
50754fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano 	return 0;
51254fe083fSAlfredo Cardigliano }
51354fe083fSAlfredo Cardigliano 
51454fe083fSAlfredo Cardigliano int
51554fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
51654fe083fSAlfredo Cardigliano {
51754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51954fe083fSAlfredo Cardigliano 
52054fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
52154fe083fSAlfredo Cardigliano 
52254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52354fe083fSAlfredo Cardigliano 
52454fe083fSAlfredo Cardigliano 	return 0;
52554fe083fSAlfredo Cardigliano }
52654fe083fSAlfredo Cardigliano 
52754fe083fSAlfredo Cardigliano int
52854fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
52954fe083fSAlfredo Cardigliano {
53054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
53154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
53254fe083fSAlfredo Cardigliano 
53354fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
53454fe083fSAlfredo Cardigliano 
53554fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
53654fe083fSAlfredo Cardigliano 
53754fe083fSAlfredo Cardigliano 	return 0;
53854fe083fSAlfredo Cardigliano }
539598f6726SAlfredo Cardigliano 
540598f6726SAlfredo Cardigliano int
541598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
542598f6726SAlfredo Cardigliano {
543598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
544598f6726SAlfredo Cardigliano 		.pending_work = true,
545598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
546598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
547598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
54809f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
549598f6726SAlfredo Cardigliano 		},
550598f6726SAlfredo Cardigliano 	};
551598f6726SAlfredo Cardigliano 	int err;
552598f6726SAlfredo Cardigliano 
553598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
554598f6726SAlfredo Cardigliano 	if (err)
555598f6726SAlfredo Cardigliano 		return err;
556598f6726SAlfredo Cardigliano 
557598f6726SAlfredo Cardigliano 	return 0;
558598f6726SAlfredo Cardigliano }
559598f6726SAlfredo Cardigliano 
560598f6726SAlfredo Cardigliano int
56101a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
56201a6c311SAlfredo Cardigliano {
56301a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
56401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
56501a6c311SAlfredo Cardigliano 	unsigned long index;
56601a6c311SAlfredo Cardigliano 
56701a6c311SAlfredo Cardigliano 	/*
56801a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
56901a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5704ae96cb8SAndrew Boyer 	 * which has index = 0)
57101a6c311SAlfredo Cardigliano 	 */
57201a6c311SAlfredo Cardigliano 
57301a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
57401a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
57501a6c311SAlfredo Cardigliano 			break;
57601a6c311SAlfredo Cardigliano 
57701a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
57801a6c311SAlfredo Cardigliano 		return -ENOSPC;
57901a6c311SAlfredo Cardigliano 
58001a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
58101a6c311SAlfredo Cardigliano 
58201a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
58301a6c311SAlfredo Cardigliano 
58401a6c311SAlfredo Cardigliano 	return 0;
58501a6c311SAlfredo Cardigliano }
58601a6c311SAlfredo Cardigliano 
58701a6c311SAlfredo Cardigliano static int
5884ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5894ad56b7aSAndrew Boyer 		uint8_t type,
590be39f75cSAndrew Boyer 		size_t struct_size,
5918ec5ad7fSAndrew Boyer 		uint32_t socket_id,
59201a6c311SAlfredo Cardigliano 		uint32_t index,
5934ad56b7aSAndrew Boyer 		const char *type_name,
5944ad56b7aSAndrew Boyer 		uint16_t flags,
5954ad56b7aSAndrew Boyer 		uint16_t num_descs,
5964ad56b7aSAndrew Boyer 		uint16_t desc_size,
5974ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5984ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5991abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
60001a6c311SAlfredo Cardigliano {
60101a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
60201a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
60301a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
60401a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
60501a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
60601a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
60701a6c311SAlfredo Cardigliano 	int err;
60801a6c311SAlfredo Cardigliano 
60901a6c311SAlfredo Cardigliano 	*qcq = NULL;
61001a6c311SAlfredo Cardigliano 
61101a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
61201a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
61301a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
61401a6c311SAlfredo Cardigliano 
61501a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
61601a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
61701a6c311SAlfredo Cardigliano 	/*
61801a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61901a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
62001a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
62101a6c311SAlfredo Cardigliano 	 */
62201a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
62301a6c311SAlfredo Cardigliano 
62401a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
62501a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
62601a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
62701a6c311SAlfredo Cardigliano 	}
62801a6c311SAlfredo Cardigliano 
629be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
63001a6c311SAlfredo Cardigliano 	if (!new) {
63101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
63201a6c311SAlfredo Cardigliano 		return -ENOMEM;
63301a6c311SAlfredo Cardigliano 	}
63401a6c311SAlfredo Cardigliano 
63501a6c311SAlfredo Cardigliano 	new->lif = lif;
63601a6c311SAlfredo Cardigliano 
637be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
638be39f75cSAndrew Boyer 				num_descs, sizeof(void *),
639be39f75cSAndrew Boyer 				PAGE_SIZE, socket_id);
64001a6c311SAlfredo Cardigliano 	if (!new->q.info) {
64101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6424c8f8d57SAndrew Boyer 		err = -ENOMEM;
6434c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
64401a6c311SAlfredo Cardigliano 	}
64501a6c311SAlfredo Cardigliano 
64601a6c311SAlfredo Cardigliano 	new->q.type = type;
64701a6c311SAlfredo Cardigliano 
6484ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64901a6c311SAlfredo Cardigliano 	if (err) {
65001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6514c8f8d57SAndrew Boyer 		goto err_out_free_info;
65201a6c311SAlfredo Cardigliano 	}
65301a6c311SAlfredo Cardigliano 
6542aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
65501a6c311SAlfredo Cardigliano 	if (err) {
65601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6574c8f8d57SAndrew Boyer 		goto err_out_free_info;
65801a6c311SAlfredo Cardigliano 	}
65901a6c311SAlfredo Cardigliano 
66001a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6614ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
66201a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66301a6c311SAlfredo Cardigliano 
66401a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66601a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6674c8f8d57SAndrew Boyer 		goto err_out_free_info;
66801a6c311SAlfredo Cardigliano 	}
66901a6c311SAlfredo Cardigliano 
67001a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
67101a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67201a6c311SAlfredo Cardigliano 
67301a6c311SAlfredo Cardigliano 	q_base = new->base;
67401a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67501a6c311SAlfredo Cardigliano 
67601a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
67701a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
67801a6c311SAlfredo Cardigliano 
67901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
68001a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
68101a6c311SAlfredo Cardigliano 			PAGE_SIZE);
68201a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
68301a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68401a6c311SAlfredo Cardigliano 	}
68501a6c311SAlfredo Cardigliano 
6864ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6874ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68801a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68901a6c311SAlfredo Cardigliano 
69001a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69101a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69201a6c311SAlfredo Cardigliano 
69301a6c311SAlfredo Cardigliano 	*qcq = new;
69401a6c311SAlfredo Cardigliano 
69501a6c311SAlfredo Cardigliano 	return 0;
69601a6c311SAlfredo Cardigliano 
6974c8f8d57SAndrew Boyer err_out_free_info:
6984c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6994c8f8d57SAndrew Boyer err_out_free_qcq:
7004c8f8d57SAndrew Boyer 	rte_free(new);
70101a6c311SAlfredo Cardigliano 
70201a6c311SAlfredo Cardigliano 	return err;
70301a6c311SAlfredo Cardigliano }
70401a6c311SAlfredo Cardigliano 
70501a6c311SAlfredo Cardigliano void
70601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70701a6c311SAlfredo Cardigliano {
70801a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70901a6c311SAlfredo Cardigliano 		qcq->base = NULL;
71001a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71101a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71201a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71301a6c311SAlfredo Cardigliano 	}
71401a6c311SAlfredo Cardigliano 
71501a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71601a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71701a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71801a6c311SAlfredo Cardigliano 	}
71901a6c311SAlfredo Cardigliano 
72001a6c311SAlfredo Cardigliano 	rte_free(qcq);
72101a6c311SAlfredo Cardigliano }
72201a6c311SAlfredo Cardigliano 
723a27d9013SAlfredo Cardigliano int
7248ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
725be39f75cSAndrew Boyer 		uint16_t nrxq_descs, struct ionic_rx_qcq **rxq_out)
726a27d9013SAlfredo Cardigliano {
727be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
728be39f75cSAndrew Boyer 	uint16_t flags;
729be39f75cSAndrew Boyer 	int err;
730a27d9013SAlfredo Cardigliano 
731a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
7324ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7334ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
734be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7358ec5ad7fSAndrew Boyer 		socket_id,
7364ad56b7aSAndrew Boyer 		index,
7374ad56b7aSAndrew Boyer 		"rx",
7384ad56b7aSAndrew Boyer 		flags,
739a27d9013SAlfredo Cardigliano 		nrxq_descs,
740a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
741a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
742a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
743be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
744a27d9013SAlfredo Cardigliano 	if (err)
745a27d9013SAlfredo Cardigliano 		return err;
746a27d9013SAlfredo Cardigliano 
747be39f75cSAndrew Boyer 	rxq->flags = flags;
748be39f75cSAndrew Boyer 
749be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
750be39f75cSAndrew Boyer 	*rxq_out = rxq;
751a27d9013SAlfredo Cardigliano 
752a27d9013SAlfredo Cardigliano 	return 0;
753a27d9013SAlfredo Cardigliano }
754a27d9013SAlfredo Cardigliano 
755a27d9013SAlfredo Cardigliano int
7568ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
757be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
758a27d9013SAlfredo Cardigliano {
759be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
760*e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
761be39f75cSAndrew Boyer 	int err;
762a27d9013SAlfredo Cardigliano 
763a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
764*e19eea1eSAndrew Boyer 
765*e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
766*e19eea1eSAndrew Boyer 
7674ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7684ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
769be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
7708ec5ad7fSAndrew Boyer 		socket_id,
7714ad56b7aSAndrew Boyer 		index,
7724ad56b7aSAndrew Boyer 		"tx",
7734ad56b7aSAndrew Boyer 		flags,
774a27d9013SAlfredo Cardigliano 		ntxq_descs,
775a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
776a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
77756117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
778be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
779a27d9013SAlfredo Cardigliano 	if (err)
780a27d9013SAlfredo Cardigliano 		return err;
781a27d9013SAlfredo Cardigliano 
782be39f75cSAndrew Boyer 	txq->flags = flags;
783*e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
784be39f75cSAndrew Boyer 
785be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
786be39f75cSAndrew Boyer 	*txq_out = txq;
787a27d9013SAlfredo Cardigliano 
788a27d9013SAlfredo Cardigliano 	return 0;
789a27d9013SAlfredo Cardigliano }
790a27d9013SAlfredo Cardigliano 
79101a6c311SAlfredo Cardigliano static int
79201a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
79301a6c311SAlfredo Cardigliano {
794be39f75cSAndrew Boyer 	uint16_t flags = 0;
795be39f75cSAndrew Boyer 	int err;
79601a6c311SAlfredo Cardigliano 
7974ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7984ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
799be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8008ec5ad7fSAndrew Boyer 		rte_socket_id(),
8014ad56b7aSAndrew Boyer 		0,
8024ad56b7aSAndrew Boyer 		"admin",
8034ad56b7aSAndrew Boyer 		flags,
80401a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
80501a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
80601a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
80701a6c311SAlfredo Cardigliano 		0,
808be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
80927b942c8SAlfredo Cardigliano 	if (err)
81027b942c8SAlfredo Cardigliano 		return err;
81101a6c311SAlfredo Cardigliano 
81227b942c8SAlfredo Cardigliano 	return 0;
81327b942c8SAlfredo Cardigliano }
81427b942c8SAlfredo Cardigliano 
81527b942c8SAlfredo Cardigliano static int
81627b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
81727b942c8SAlfredo Cardigliano {
818be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8194c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
820be39f75cSAndrew Boyer 	uint16_t flags = 0;
821be39f75cSAndrew Boyer 	int err;
82227b942c8SAlfredo Cardigliano 
8234ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8244ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
825be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8268ec5ad7fSAndrew Boyer 		rte_socket_id(),
8274ad56b7aSAndrew Boyer 		0,
8284ad56b7aSAndrew Boyer 		"notify",
82927b942c8SAlfredo Cardigliano 		flags,
83027b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
83127b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
83227b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
83327b942c8SAlfredo Cardigliano 		0,
834be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
83501a6c311SAlfredo Cardigliano 	if (err)
83601a6c311SAlfredo Cardigliano 		return err;
83701a6c311SAlfredo Cardigliano 
8384c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8394c8f8d57SAndrew Boyer 	if (err) {
840be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
8414c8f8d57SAndrew Boyer 		return err;
8424c8f8d57SAndrew Boyer 	}
8434c8f8d57SAndrew Boyer 
8444c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8454c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8464c8f8d57SAndrew Boyer 
8474c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8484c8f8d57SAndrew Boyer 
84901a6c311SAlfredo Cardigliano 	return 0;
85001a6c311SAlfredo Cardigliano }
85101a6c311SAlfredo Cardigliano 
852c67719e1SAlfredo Cardigliano static void *
853c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
854c67719e1SAlfredo Cardigliano {
855c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
856c67719e1SAlfredo Cardigliano 
857c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
858c67719e1SAlfredo Cardigliano 		return NULL;
859c67719e1SAlfredo Cardigliano 
860c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
861c67719e1SAlfredo Cardigliano }
862c67719e1SAlfredo Cardigliano 
863c5d15850SAndrew Boyer static void
864c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
865c5d15850SAndrew Boyer {
866c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
867c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
868c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
869c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
870c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
871c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
872c5d15850SAndrew Boyer 	int err;
873c5d15850SAndrew Boyer 
874c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
875c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
876c5d15850SAndrew Boyer 
877c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
878c5d15850SAndrew Boyer 		switch (qtype) {
879c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
880c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
881c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
882c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
883c5d15850SAndrew Boyer 			break;
884c5d15850SAndrew Boyer 		default:
885c5d15850SAndrew Boyer 			continue;
886c5d15850SAndrew Boyer 		}
887c5d15850SAndrew Boyer 
888c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
889c5d15850SAndrew Boyer 
890c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
891c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
892c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
893c5d15850SAndrew Boyer 		if (err == -EINVAL) {
894c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
895c5d15850SAndrew Boyer 			continue;
896c5d15850SAndrew Boyer 		} else if (err == -EIO) {
897c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
898c5d15850SAndrew Boyer 			return;
899c5d15850SAndrew Boyer 		} else if (err) {
900c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
901c5d15850SAndrew Boyer 				qtype, err);
902c5d15850SAndrew Boyer 			return;
903c5d15850SAndrew Boyer 		}
904c5d15850SAndrew Boyer 
905c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
906c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
907c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
908c5d15850SAndrew Boyer 
909c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
910c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
911c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
912c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
913c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
914c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
915c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
916c5d15850SAndrew Boyer 		qti->sg_desc_stride =
917c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
918c5d15850SAndrew Boyer 
919c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
920c5d15850SAndrew Boyer 			qtype, qti->version);
921c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
922c5d15850SAndrew Boyer 			qtype, qti->supported);
923c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
924c5d15850SAndrew Boyer 			qtype, qti->features);
925c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
926c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
927c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
928c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
929c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
930c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
931c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
932c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
933c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
934c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
935c5d15850SAndrew Boyer 	}
936c5d15850SAndrew Boyer }
937c5d15850SAndrew Boyer 
938669c8de6SAlfredo Cardigliano int
939669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
940669c8de6SAlfredo Cardigliano {
941c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
942669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
94301a6c311SAlfredo Cardigliano 	int err;
944669c8de6SAlfredo Cardigliano 
9454ae96cb8SAndrew Boyer 	/*
9464ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9474ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9484ae96cb8SAndrew Boyer 	 */
9494ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9504ae96cb8SAndrew Boyer 
9514ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
952669c8de6SAlfredo Cardigliano 
953c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
954c5d15850SAndrew Boyer 
95556117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
95656117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
95756117636SAndrew Boyer 		return -ENXIO;
95856117636SAndrew Boyer 	}
95956117636SAndrew Boyer 
960669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
961669c8de6SAlfredo Cardigliano 
96201a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
96301a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
96401a6c311SAlfredo Cardigliano 
96500b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
966c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
967c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
968c67719e1SAlfredo Cardigliano 		return -ENOMEM;
969c67719e1SAlfredo Cardigliano 	}
970c67719e1SAlfredo Cardigliano 
971a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
972a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
973a27d9013SAlfredo Cardigliano 
974a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
975a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
976a27d9013SAlfredo Cardigliano 		return -ENOMEM;
977a27d9013SAlfredo Cardigliano 	}
978a27d9013SAlfredo Cardigliano 
979a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
980a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
981a27d9013SAlfredo Cardigliano 
982a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
983a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
984a27d9013SAlfredo Cardigliano 		return -ENOMEM;
985a27d9013SAlfredo Cardigliano 	}
986a27d9013SAlfredo Cardigliano 
98727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
98827b942c8SAlfredo Cardigliano 
98927b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
99027b942c8SAlfredo Cardigliano 	if (err) {
99127b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
99227b942c8SAlfredo Cardigliano 		return err;
99327b942c8SAlfredo Cardigliano 	}
99427b942c8SAlfredo Cardigliano 
99527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
99627b942c8SAlfredo Cardigliano 
99701a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
99801a6c311SAlfredo Cardigliano 	if (err) {
99901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
100001a6c311SAlfredo Cardigliano 		return err;
100101a6c311SAlfredo Cardigliano 	}
100201a6c311SAlfredo Cardigliano 
100301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
100401a6c311SAlfredo Cardigliano 
1005669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
1006669c8de6SAlfredo Cardigliano 
1007669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1008669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1009669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1010669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1011669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1012669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1013669c8de6SAlfredo Cardigliano 	}
1014669c8de6SAlfredo Cardigliano 
1015669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1016669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1017669c8de6SAlfredo Cardigliano 
1018669c8de6SAlfredo Cardigliano 	return 0;
1019669c8de6SAlfredo Cardigliano }
1020669c8de6SAlfredo Cardigliano 
1021669c8de6SAlfredo Cardigliano void
1022669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1023669c8de6SAlfredo Cardigliano {
102427b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1025be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
102627b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
102727b942c8SAlfredo Cardigliano 	}
102827b942c8SAlfredo Cardigliano 
102901a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1030be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
103101a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
103201a6c311SAlfredo Cardigliano 	}
103301a6c311SAlfredo Cardigliano 
1034a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1035a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1036a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1037a27d9013SAlfredo Cardigliano 	}
1038a27d9013SAlfredo Cardigliano 
1039a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1040a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1041a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1042a27d9013SAlfredo Cardigliano 	}
1043a27d9013SAlfredo Cardigliano 
1044669c8de6SAlfredo Cardigliano 	if (lif->info) {
1045669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1046669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1047669c8de6SAlfredo Cardigliano 	}
1048669c8de6SAlfredo Cardigliano }
1049669c8de6SAlfredo Cardigliano 
1050175e4e7eSAndrew Boyer void
1051175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1052175e4e7eSAndrew Boyer {
1053175e4e7eSAndrew Boyer 	uint32_t i;
1054175e4e7eSAndrew Boyer 
1055175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
1056175e4e7eSAndrew Boyer 		ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]);
1057175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1058175e4e7eSAndrew Boyer 	}
1059175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
1060175e4e7eSAndrew Boyer 		ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]);
1061175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1062175e4e7eSAndrew Boyer 	}
1063175e4e7eSAndrew Boyer }
1064175e4e7eSAndrew Boyer 
106522e7171bSAlfredo Cardigliano int
106622e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
106722e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
106822e7171bSAlfredo Cardigliano {
106909f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
107022e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
107122e7171bSAlfredo Cardigliano 		.pending_work = true,
107222e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
107322e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
107422e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
107509f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
107609f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
107722e7171bSAlfredo Cardigliano 		},
107822e7171bSAlfredo Cardigliano 	};
107922e7171bSAlfredo Cardigliano 	unsigned int i;
108009f806e9SAndrew Boyer 	uint16_t tbl_sz =
108109f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
108222e7171bSAlfredo Cardigliano 
108322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
108422e7171bSAlfredo Cardigliano 
108522e7171bSAlfredo Cardigliano 	lif->rss_types = types;
108622e7171bSAlfredo Cardigliano 
108722e7171bSAlfredo Cardigliano 	if (key)
108822e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
108922e7171bSAlfredo Cardigliano 
109022e7171bSAlfredo Cardigliano 	if (indir)
109109f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
109222e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
109322e7171bSAlfredo Cardigliano 
109422e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
109522e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
109622e7171bSAlfredo Cardigliano 
109722e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
109822e7171bSAlfredo Cardigliano }
109922e7171bSAlfredo Cardigliano 
110022e7171bSAlfredo Cardigliano static int
110122e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
110222e7171bSAlfredo Cardigliano {
110309f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
110422e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
110522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
111022e7171bSAlfredo Cardigliano 	};
111122e7171bSAlfredo Cardigliano 	uint32_t i;
111209f806e9SAndrew Boyer 	uint16_t tbl_sz =
111309f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
111422e7171bSAlfredo Cardigliano 
111522e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
111622e7171bSAlfredo Cardigliano 
11173d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
111822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11193d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11203d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11213d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
112222e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
112322e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
112422e7171bSAlfredo Cardigliano 			return -ENOMEM;
112522e7171bSAlfredo Cardigliano 		}
112622e7171bSAlfredo Cardigliano 
112722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
112822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11293d845eddSAndrew Boyer 	}
11303d845eddSAndrew Boyer 
11313d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11323d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
113322e7171bSAlfredo Cardigliano 
113422e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11353d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
113622e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11373d845eddSAndrew Boyer 	}
113822e7171bSAlfredo Cardigliano 
11393d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
114022e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
114122e7171bSAlfredo Cardigliano }
114222e7171bSAlfredo Cardigliano 
114322e7171bSAlfredo Cardigliano static void
114422e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
114522e7171bSAlfredo Cardigliano {
114622e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
114722e7171bSAlfredo Cardigliano 		return;
114822e7171bSAlfredo Cardigliano 
114922e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
115022e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
115122e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
115222e7171bSAlfredo Cardigliano 
115322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
115422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
115522e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
115622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
115722e7171bSAlfredo Cardigliano 	}
115822e7171bSAlfredo Cardigliano }
115922e7171bSAlfredo Cardigliano 
1160be39f75cSAndrew Boyer void
1161be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1162be39f75cSAndrew Boyer {
1163be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1164be39f75cSAndrew Boyer }
1165be39f75cSAndrew Boyer 
1166be39f75cSAndrew Boyer void
1167be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1168be39f75cSAndrew Boyer {
1169be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1170be39f75cSAndrew Boyer }
1171be39f75cSAndrew Boyer 
117201a6c311SAlfredo Cardigliano static void
1173be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
117401a6c311SAlfredo Cardigliano {
1175be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
11764c8f8d57SAndrew Boyer }
11774c8f8d57SAndrew Boyer 
11784c8f8d57SAndrew Boyer static void
11794c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
11804c8f8d57SAndrew Boyer {
1181be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
11824c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
11834c8f8d57SAndrew Boyer 
11844c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
11854c8f8d57SAndrew Boyer 		return;
11864c8f8d57SAndrew Boyer 
11874c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
11884c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
11894c8f8d57SAndrew Boyer 
11904c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1191a27d9013SAlfredo Cardigliano }
1192a27d9013SAlfredo Cardigliano 
119301a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
119401a6c311SAlfredo Cardigliano int
119501a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
119601a6c311SAlfredo Cardigliano 		void *cb_arg)
119701a6c311SAlfredo Cardigliano {
119801a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
119901a6c311SAlfredo Cardigliano 	uint32_t work_done;
120001a6c311SAlfredo Cardigliano 
120101a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
120201a6c311SAlfredo Cardigliano 
120301a6c311SAlfredo Cardigliano 	return work_done;
120401a6c311SAlfredo Cardigliano }
120501a6c311SAlfredo Cardigliano 
120627b942c8SAlfredo Cardigliano static void
120727b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
120827b942c8SAlfredo Cardigliano {
120927b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
121027b942c8SAlfredo Cardigliano 	bool link_up;
121127b942c8SAlfredo Cardigliano 
121227b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
121327b942c8SAlfredo Cardigliano 
121427b942c8SAlfredo Cardigliano 	if (!lif->info)
121527b942c8SAlfredo Cardigliano 		return;
121627b942c8SAlfredo Cardigliano 
121727b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
121827b942c8SAlfredo Cardigliano 
121927b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
122027b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
122127b942c8SAlfredo Cardigliano 		return;
122227b942c8SAlfredo Cardigliano 
122327b942c8SAlfredo Cardigliano 	if (link_up) {
122409f806e9SAndrew Boyer 		adapter->link_speed =
122509f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1226be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1227be63459eSAndrew Boyer 			adapter->link_speed);
122827b942c8SAlfredo Cardigliano 	} else {
122927b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
123027b942c8SAlfredo Cardigliano 	}
123127b942c8SAlfredo Cardigliano 
123227b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1233be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1234be63459eSAndrew Boyer }
1235be63459eSAndrew Boyer 
1236be63459eSAndrew Boyer static void
1237be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1238be63459eSAndrew Boyer {
1239be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1240be63459eSAndrew Boyer 		return;
1241be63459eSAndrew Boyer 
1242be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1243be63459eSAndrew Boyer 
1244be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1245be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1246be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1247be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1248be63459eSAndrew Boyer 	}
1249be63459eSAndrew Boyer 
1250be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
125127b942c8SAlfredo Cardigliano }
125227b942c8SAlfredo Cardigliano 
125327b942c8SAlfredo Cardigliano static bool
12544ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
125527b942c8SAlfredo Cardigliano {
125627b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
125727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
125827b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
125927b942c8SAlfredo Cardigliano 
126027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
126127b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
126227b942c8SAlfredo Cardigliano 
126327b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
126427b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
126527b942c8SAlfredo Cardigliano 		return false;
126627b942c8SAlfredo Cardigliano 
126727b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
126827b942c8SAlfredo Cardigliano 
126927b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
127027b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
127127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1272be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1273be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1274be63459eSAndrew Boyer 			lif->name,
127527b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
127627b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
127727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
127827b942c8SAlfredo Cardigliano 
127927b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
128027b942c8SAlfredo Cardigliano 		break;
1281be63459eSAndrew Boyer 
1282be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1283be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1284be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1285be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1286be63459eSAndrew Boyer 			lif->name,
1287be63459eSAndrew Boyer 			cq_desc->event.eid,
1288be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1289be63459eSAndrew Boyer 			cq_desc->reset.state);
1290be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1291be63459eSAndrew Boyer 		break;
1292be63459eSAndrew Boyer 
129327b942c8SAlfredo Cardigliano 	default:
129427b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
129527b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
129627b942c8SAlfredo Cardigliano 		break;
129727b942c8SAlfredo Cardigliano 	}
129827b942c8SAlfredo Cardigliano 
129927b942c8SAlfredo Cardigliano 	return true;
130027b942c8SAlfredo Cardigliano }
130127b942c8SAlfredo Cardigliano 
130227b942c8SAlfredo Cardigliano int
130327b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
130427b942c8SAlfredo Cardigliano {
130527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1306be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
130727b942c8SAlfredo Cardigliano 	uint32_t work_done;
130827b942c8SAlfredo Cardigliano 
1309be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
131027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
131127b942c8SAlfredo Cardigliano 		return -1;
131227b942c8SAlfredo Cardigliano 	}
131327b942c8SAlfredo Cardigliano 
1314be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
131527b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
131627b942c8SAlfredo Cardigliano 
1317be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1318be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
131927b942c8SAlfredo Cardigliano 
132027b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
132127b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
132227b942c8SAlfredo Cardigliano 
1323be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
132427b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
132527b942c8SAlfredo Cardigliano 
1326be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
132727b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
132827b942c8SAlfredo Cardigliano 
132927b942c8SAlfredo Cardigliano 	return 0;
133027b942c8SAlfredo Cardigliano }
133127b942c8SAlfredo Cardigliano 
133201a6c311SAlfredo Cardigliano static int
133301a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
133401a6c311SAlfredo Cardigliano {
133501a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1336be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1337be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
133801a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
133901a6c311SAlfredo Cardigliano 	int err;
134001a6c311SAlfredo Cardigliano 
1341be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
134201a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
134301a6c311SAlfredo Cardigliano 	if (err)
134401a6c311SAlfredo Cardigliano 		return err;
134501a6c311SAlfredo Cardigliano 
134601a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
134701a6c311SAlfredo Cardigliano 
134801a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
134909f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
135001a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
135101a6c311SAlfredo Cardigliano 
135201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
135301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
135401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
135501a6c311SAlfredo Cardigliano 
1356be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
135701a6c311SAlfredo Cardigliano 
135801a6c311SAlfredo Cardigliano 	return 0;
135901a6c311SAlfredo Cardigliano }
136001a6c311SAlfredo Cardigliano 
136127b942c8SAlfredo Cardigliano static int
136227b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
136327b942c8SAlfredo Cardigliano {
136427b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1365be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1366be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
136727b942c8SAlfredo Cardigliano 	int err;
136827b942c8SAlfredo Cardigliano 
136927b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
137027b942c8SAlfredo Cardigliano 		.pending_work = true,
137127b942c8SAlfredo Cardigliano 		.cmd.q_init = {
137227b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
137327b942c8SAlfredo Cardigliano 			.type = q->type,
1374c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
137509f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1376be39f75cSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(nqcq->intr.index),
137709f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ |
137809f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
137927b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
138009f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
138127b942c8SAlfredo Cardigliano 		}
138227b942c8SAlfredo Cardigliano 	};
138327b942c8SAlfredo Cardigliano 
138409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
138509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
138627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
138727b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13884ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
138927b942c8SAlfredo Cardigliano 
139027b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
139127b942c8SAlfredo Cardigliano 	if (err)
139227b942c8SAlfredo Cardigliano 		return err;
139327b942c8SAlfredo Cardigliano 
139427b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
139509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
139627b942c8SAlfredo Cardigliano 	q->db = NULL;
139727b942c8SAlfredo Cardigliano 
139827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
139927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
140027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
140127b942c8SAlfredo Cardigliano 
1402be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
140327b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
140427b942c8SAlfredo Cardigliano 
1405be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
140627b942c8SAlfredo Cardigliano 
140727b942c8SAlfredo Cardigliano 	return 0;
140827b942c8SAlfredo Cardigliano }
140927b942c8SAlfredo Cardigliano 
1410669c8de6SAlfredo Cardigliano int
1411598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1412598f6726SAlfredo Cardigliano {
1413598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1414598f6726SAlfredo Cardigliano 		.pending_work = true,
1415598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1416598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1417598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
141809f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1419598f6726SAlfredo Cardigliano 		},
1420598f6726SAlfredo Cardigliano 	};
1421598f6726SAlfredo Cardigliano 	int err;
1422598f6726SAlfredo Cardigliano 
1423598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1424598f6726SAlfredo Cardigliano 	if (err)
1425598f6726SAlfredo Cardigliano 		return err;
1426598f6726SAlfredo Cardigliano 
142709f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1428598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1429598f6726SAlfredo Cardigliano 
1430598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1431598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1432598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1433598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1434598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1435598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1436598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1437598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1438598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1439598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1440598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1441598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1442598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1443598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1444598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1445598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1446598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1448598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1450598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1452598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1454598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1455598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1456598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1457598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1458598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1459598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1460598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1461598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1462598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1463598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1464598f6726SAlfredo Cardigliano 
1465598f6726SAlfredo Cardigliano 	return 0;
1466598f6726SAlfredo Cardigliano }
1467598f6726SAlfredo Cardigliano 
1468a27d9013SAlfredo Cardigliano int
1469be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1470a27d9013SAlfredo Cardigliano {
1471be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1472a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1473a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1474a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1475a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1476a27d9013SAlfredo Cardigliano 		.pending_work = true,
1477a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1478a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1479a27d9013SAlfredo Cardigliano 			.type = q->type,
1480c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
148109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
148209f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
148309f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
148409f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1485a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
148609f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
148709f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
148809f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1489a27d9013SAlfredo Cardigliano 		},
1490a27d9013SAlfredo Cardigliano 	};
1491a27d9013SAlfredo Cardigliano 	int err;
1492a27d9013SAlfredo Cardigliano 
149309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
149409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1495a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1496a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14974ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1498a27d9013SAlfredo Cardigliano 
1499be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1500a27d9013SAlfredo Cardigliano 	if (err)
1501a27d9013SAlfredo Cardigliano 		return err;
1502a27d9013SAlfredo Cardigliano 
1503a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
150409f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1505a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1506a27d9013SAlfredo Cardigliano 
1507a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1508a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1509a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1510a27d9013SAlfredo Cardigliano 
1511be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1512a27d9013SAlfredo Cardigliano 
1513a27d9013SAlfredo Cardigliano 	return 0;
1514a27d9013SAlfredo Cardigliano }
1515a27d9013SAlfredo Cardigliano 
1516a27d9013SAlfredo Cardigliano int
1517be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1518a27d9013SAlfredo Cardigliano {
1519be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1520a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1521a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1522a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1523a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1524a27d9013SAlfredo Cardigliano 		.pending_work = true,
1525a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1526a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1527a27d9013SAlfredo Cardigliano 			.type = q->type,
1528c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
152909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
153009f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
153109f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
153209f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1533a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
153409f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
153509f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
153609f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1537a27d9013SAlfredo Cardigliano 		},
1538a27d9013SAlfredo Cardigliano 	};
1539a27d9013SAlfredo Cardigliano 	int err;
1540a27d9013SAlfredo Cardigliano 
154109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
154209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1543a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1544a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15454ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1546a27d9013SAlfredo Cardigliano 
1547be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1548a27d9013SAlfredo Cardigliano 	if (err)
1549a27d9013SAlfredo Cardigliano 		return err;
1550a27d9013SAlfredo Cardigliano 
1551a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
155209f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1553a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1554a27d9013SAlfredo Cardigliano 
1555be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1556a27d9013SAlfredo Cardigliano 
1557a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1558a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1559a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1560a27d9013SAlfredo Cardigliano 
1561a27d9013SAlfredo Cardigliano 	return 0;
1562a27d9013SAlfredo Cardigliano }
1563a27d9013SAlfredo Cardigliano 
1564598f6726SAlfredo Cardigliano static int
1565598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1566598f6726SAlfredo Cardigliano {
1567598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1568598f6726SAlfredo Cardigliano 		.pending_work = true,
1569598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1570598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1571598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1572598f6726SAlfredo Cardigliano 		},
1573598f6726SAlfredo Cardigliano 	};
1574598f6726SAlfredo Cardigliano 	int err;
1575598f6726SAlfredo Cardigliano 
1576598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1577598f6726SAlfredo Cardigliano 
1578598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1579598f6726SAlfredo Cardigliano 	if (err)
1580598f6726SAlfredo Cardigliano 		return err;
1581598f6726SAlfredo Cardigliano 
1582598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1583598f6726SAlfredo Cardigliano 
1584598f6726SAlfredo Cardigliano 	return 0;
1585598f6726SAlfredo Cardigliano }
1586598f6726SAlfredo Cardigliano 
1587598f6726SAlfredo Cardigliano static void
1588598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1589598f6726SAlfredo Cardigliano {
1590598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1591598f6726SAlfredo Cardigliano 		.pending_work = true,
1592598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1593598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1594598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1595598f6726SAlfredo Cardigliano 		},
1596598f6726SAlfredo Cardigliano 	};
1597598f6726SAlfredo Cardigliano 
15984ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
15994ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1600598f6726SAlfredo Cardigliano 
1601598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1602598f6726SAlfredo Cardigliano }
1603598f6726SAlfredo Cardigliano 
1604598f6726SAlfredo Cardigliano int
1605669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1606669c8de6SAlfredo Cardigliano {
1607669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1608669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1609669c8de6SAlfredo Cardigliano 	int err;
1610669c8de6SAlfredo Cardigliano 
16113cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
16123cdfd905SAlfredo Cardigliano 
161300b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1614669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1615669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1616669c8de6SAlfredo Cardigliano 	if (err)
1617669c8de6SAlfredo Cardigliano 		return err;
1618669c8de6SAlfredo Cardigliano 
161909f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1620669c8de6SAlfredo Cardigliano 
162101a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
162201a6c311SAlfredo Cardigliano 	if (err)
162301a6c311SAlfredo Cardigliano 		return err;
162401a6c311SAlfredo Cardigliano 
162527b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
162627b942c8SAlfredo Cardigliano 	if (err)
162727b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
162827b942c8SAlfredo Cardigliano 
162918a44465SAndrew Boyer 	/*
163018a44465SAndrew Boyer 	 * Configure initial feature set
163118a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
163218a44465SAndrew Boyer 	 */
163318a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1634598f6726SAlfredo Cardigliano 
1635598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1636598f6726SAlfredo Cardigliano 	if (err)
1637598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1638598f6726SAlfredo Cardigliano 
163954fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1640598f6726SAlfredo Cardigliano 	if (err)
1641598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1642598f6726SAlfredo Cardigliano 
164354fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
164454fe083fSAlfredo Cardigliano 	if (err)
164554fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
164654fe083fSAlfredo Cardigliano 
1647598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1648598f6726SAlfredo Cardigliano 
1649669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1650669c8de6SAlfredo Cardigliano 
1651669c8de6SAlfredo Cardigliano 	return 0;
165227b942c8SAlfredo Cardigliano 
165354fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
165454fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
165554fe083fSAlfredo Cardigliano 
1656598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
16574c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1658598f6726SAlfredo Cardigliano 
165927b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1660be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
166127b942c8SAlfredo Cardigliano 
166227b942c8SAlfredo Cardigliano 	return err;
1663669c8de6SAlfredo Cardigliano }
1664669c8de6SAlfredo Cardigliano 
1665669c8de6SAlfredo Cardigliano void
1666669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1667669c8de6SAlfredo Cardigliano {
1668669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1669669c8de6SAlfredo Cardigliano 		return;
1670669c8de6SAlfredo Cardigliano 
167154fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
167222e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
16734c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1674be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
167501a6c311SAlfredo Cardigliano 
1676669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1677669c8de6SAlfredo Cardigliano }
1678669c8de6SAlfredo Cardigliano 
167918a44465SAndrew Boyer void
168018a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
168118a44465SAndrew Boyer {
168218a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
168318a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
168418a44465SAndrew Boyer 
168518a44465SAndrew Boyer 	/*
168618a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
168718a44465SAndrew Boyer 	 * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK
168818a44465SAndrew Boyer 	 */
168918a44465SAndrew Boyer 	rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
169018a44465SAndrew Boyer 
169118a44465SAndrew Boyer 	if (mask & ETH_VLAN_STRIP_MASK) {
169218a44465SAndrew Boyer 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
169318a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
169418a44465SAndrew Boyer 		else
169518a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
169618a44465SAndrew Boyer 	}
169718a44465SAndrew Boyer }
169818a44465SAndrew Boyer 
169918a44465SAndrew Boyer void
1700598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1701598f6726SAlfredo Cardigliano {
170218a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
170318a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
170422e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
170509f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
170622e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
170709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
170822e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
170909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
171022e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
171122e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
171222e7171bSAlfredo Cardigliano 
1713598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1714598f6726SAlfredo Cardigliano 
171522e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
171622e7171bSAlfredo Cardigliano 		lif->port_id);
171722e7171bSAlfredo Cardigliano 
171822e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
171922e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
172022e7171bSAlfredo Cardigliano 
172122e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
172222e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
172322e7171bSAlfredo Cardigliano 
172422e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
172522e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1726a27d9013SAlfredo Cardigliano 
172718a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
172818a44465SAndrew Boyer 
172918a44465SAndrew Boyer 	/*
173018a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
173118a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
173218a44465SAndrew Boyer 	 * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH;
173318a44465SAndrew Boyer 	 */
173418a44465SAndrew Boyer 
173518a44465SAndrew Boyer 	/* RX per-port */
173618a44465SAndrew Boyer 
173718a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM ||
173818a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM ||
173918a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM)
174018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
174118a44465SAndrew Boyer 	else
174218a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
174318a44465SAndrew Boyer 
174418a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) {
174518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
174618a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
174718a44465SAndrew Boyer 	} else {
174818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
174918a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
175018a44465SAndrew Boyer 	}
175118a44465SAndrew Boyer 
175218a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
175318a44465SAndrew Boyer 	ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK);
175418a44465SAndrew Boyer 
175518a44465SAndrew Boyer 	/* TX per-port */
175618a44465SAndrew Boyer 
175718a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM ||
175818a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM ||
175918a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM ||
176018a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
176118a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
176218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
176318a44465SAndrew Boyer 	else
176418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
176518a44465SAndrew Boyer 
176618a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
176718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
176818a44465SAndrew Boyer 	else
176918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
177018a44465SAndrew Boyer 
177118a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
177218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
177318a44465SAndrew Boyer 	else
177418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
177518a44465SAndrew Boyer 
177618a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) {
177718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
177818a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
177918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
178018a44465SAndrew Boyer 	} else {
178118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
178218a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
178318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
178418a44465SAndrew Boyer 	}
1785598f6726SAlfredo Cardigliano }
1786598f6726SAlfredo Cardigliano 
1787598f6726SAlfredo Cardigliano int
1788598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1789598f6726SAlfredo Cardigliano {
17900578335aSAndrew Boyer 	uint32_t rx_mode;
1791a27d9013SAlfredo Cardigliano 	uint32_t i;
1792a27d9013SAlfredo Cardigliano 	int err;
1793598f6726SAlfredo Cardigliano 
179422e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
179522e7171bSAlfredo Cardigliano 	if (err)
179622e7171bSAlfredo Cardigliano 		return err;
179722e7171bSAlfredo Cardigliano 
17980578335aSAndrew Boyer 	if (!lif->rx_mode) {
17990578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
18000578335aSAndrew Boyer 			lif->name);
1801598f6726SAlfredo Cardigliano 
18020578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1803598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1804598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1805598f6726SAlfredo Cardigliano 
1806598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18070578335aSAndrew Boyer 	}
1808598f6726SAlfredo Cardigliano 
1809a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1810a27d9013SAlfredo Cardigliano 		"on port %u",
1811a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1812a27d9013SAlfredo Cardigliano 
1813a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1814be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
181502eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1816a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1817a27d9013SAlfredo Cardigliano 
1818a27d9013SAlfredo Cardigliano 			if (err)
1819a27d9013SAlfredo Cardigliano 				return err;
1820a27d9013SAlfredo Cardigliano 		}
1821a27d9013SAlfredo Cardigliano 	}
1822a27d9013SAlfredo Cardigliano 
1823a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1824be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
182502eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1826a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1827a27d9013SAlfredo Cardigliano 
1828a27d9013SAlfredo Cardigliano 			if (err)
1829a27d9013SAlfredo Cardigliano 				return err;
1830a27d9013SAlfredo Cardigliano 		}
1831a27d9013SAlfredo Cardigliano 	}
1832a27d9013SAlfredo Cardigliano 
1833598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1834be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1835be63459eSAndrew Boyer 
1836be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1837598f6726SAlfredo Cardigliano 
1838598f6726SAlfredo Cardigliano 	return 0;
1839598f6726SAlfredo Cardigliano }
1840598f6726SAlfredo Cardigliano 
1841598f6726SAlfredo Cardigliano int
1842669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1843669c8de6SAlfredo Cardigliano {
1844669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1845669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
184609f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
184776276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
184876276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
184976276d71SAndrew Boyer 	uint32_t i, nwords;
1850669c8de6SAlfredo Cardigliano 	int err;
1851669c8de6SAlfredo Cardigliano 
1852669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1853669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1854669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1855669c8de6SAlfredo Cardigliano 	if (err)
1856669c8de6SAlfredo Cardigliano 		return (err);
1857669c8de6SAlfredo Cardigliano 
1858669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1859669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1860669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1861669c8de6SAlfredo Cardigliano 
1862669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
186309f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1864669c8de6SAlfredo Cardigliano 
1865669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
186609f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1867669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
186809f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1869669c8de6SAlfredo Cardigliano 
1870669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
187109f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1872669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
187309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1874669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
187509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1876669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
187709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1878669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
187909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1880669c8de6SAlfredo Cardigliano 
1881669c8de6SAlfredo Cardigliano 	return 0;
1882669c8de6SAlfredo Cardigliano }
1883669c8de6SAlfredo Cardigliano 
1884669c8de6SAlfredo Cardigliano int
1885669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1886669c8de6SAlfredo Cardigliano {
1887669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
188809f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
188909f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1890669c8de6SAlfredo Cardigliano 
1891669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
189209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1893669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
189409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1895669c8de6SAlfredo Cardigliano 
189600b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1897669c8de6SAlfredo Cardigliano 
1898669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
18994ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
19004ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1901669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1902669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1903669c8de6SAlfredo Cardigliano 	}
1904669c8de6SAlfredo Cardigliano 
1905669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1906669c8de6SAlfredo Cardigliano 
1907669c8de6SAlfredo Cardigliano 	return 0;
1908669c8de6SAlfredo Cardigliano }
1909