xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 4ad56b7a7cb89148d554f006a66c6d74de2ba874)
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;
37*4ad56b7aSAndrew 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;
55*4ad56b7aSAndrew 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++) {
79a0a99f21SAndrew Boyer 		struct ionic_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++) {
85a0a99f21SAndrew Boyer 		struct ionic_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++) {
1343cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
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++) {
1553cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
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++) {
1763cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
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++) {
1923cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
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++) {
2203cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
2213cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
2223cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 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
588*4ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
589*4ad56b7aSAndrew Boyer 		uint8_t type,
59001a6c311SAlfredo Cardigliano 		uint32_t index,
591*4ad56b7aSAndrew Boyer 		const char *type_name,
592*4ad56b7aSAndrew Boyer 		uint16_t flags,
593*4ad56b7aSAndrew Boyer 		uint16_t num_descs,
594*4ad56b7aSAndrew Boyer 		uint16_t desc_size,
595*4ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
596*4ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5971abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
59801a6c311SAlfredo Cardigliano {
59901a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
60001a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
60101a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
60201a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
60301a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
60401a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
60501a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
60601a6c311SAlfredo Cardigliano 	int err;
60701a6c311SAlfredo Cardigliano 
60801a6c311SAlfredo Cardigliano 	*qcq = NULL;
60901a6c311SAlfredo Cardigliano 
61001a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
61101a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
61201a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
61301a6c311SAlfredo Cardigliano 
61401a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
61501a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
61601a6c311SAlfredo Cardigliano 	/*
61701a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61801a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
61901a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
62001a6c311SAlfredo Cardigliano 	 */
62101a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
62201a6c311SAlfredo Cardigliano 
62301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
62401a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
62501a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
62601a6c311SAlfredo Cardigliano 	}
62701a6c311SAlfredo Cardigliano 
62801a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
62901a6c311SAlfredo Cardigliano 	if (!new) {
63001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
63101a6c311SAlfredo Cardigliano 		return -ENOMEM;
63201a6c311SAlfredo Cardigliano 	}
63301a6c311SAlfredo Cardigliano 
63401a6c311SAlfredo Cardigliano 	new->lif = lif;
63501a6c311SAlfredo Cardigliano 	new->flags = flags;
63601a6c311SAlfredo Cardigliano 
63701a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
63801a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6404c8f8d57SAndrew Boyer 		err = -ENOMEM;
6414c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
64401a6c311SAlfredo Cardigliano 	new->q.type = type;
64501a6c311SAlfredo Cardigliano 
646*4ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64701a6c311SAlfredo Cardigliano 	if (err) {
64801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6494c8f8d57SAndrew Boyer 		goto err_out_free_info;
65001a6c311SAlfredo Cardigliano 	}
65101a6c311SAlfredo Cardigliano 
6522aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
65301a6c311SAlfredo Cardigliano 	if (err) {
65401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6554c8f8d57SAndrew Boyer 		goto err_out_free_info;
65601a6c311SAlfredo Cardigliano 	}
65701a6c311SAlfredo Cardigliano 
65801a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
659*4ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
66001a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66101a6c311SAlfredo Cardigliano 
66201a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66401a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6654c8f8d57SAndrew Boyer 		goto err_out_free_info;
66601a6c311SAlfredo Cardigliano 	}
66701a6c311SAlfredo Cardigliano 
66801a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66901a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67001a6c311SAlfredo Cardigliano 	new->total_size = total_size;
67101a6c311SAlfredo Cardigliano 
67201a6c311SAlfredo Cardigliano 	q_base = new->base;
67301a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67401a6c311SAlfredo Cardigliano 
67501a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
67601a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
67701a6c311SAlfredo Cardigliano 
67801a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
67901a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
68001a6c311SAlfredo Cardigliano 			PAGE_SIZE);
68101a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
68201a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68301a6c311SAlfredo Cardigliano 	}
68401a6c311SAlfredo Cardigliano 
6854ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6864ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68701a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68801a6c311SAlfredo Cardigliano 
68901a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69001a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69101a6c311SAlfredo Cardigliano 
69201a6c311SAlfredo Cardigliano 	*qcq = new;
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	return 0;
69501a6c311SAlfredo Cardigliano 
6964c8f8d57SAndrew Boyer err_out_free_info:
6974c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6984c8f8d57SAndrew Boyer err_out_free_qcq:
6994c8f8d57SAndrew Boyer 	rte_free(new);
70001a6c311SAlfredo Cardigliano 
70101a6c311SAlfredo Cardigliano 	return err;
70201a6c311SAlfredo Cardigliano }
70301a6c311SAlfredo Cardigliano 
70401a6c311SAlfredo Cardigliano void
70501a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70601a6c311SAlfredo Cardigliano {
70701a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70801a6c311SAlfredo Cardigliano 		qcq->base = NULL;
70901a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71001a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71101a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71201a6c311SAlfredo Cardigliano 	}
71301a6c311SAlfredo Cardigliano 
71401a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71501a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71601a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71701a6c311SAlfredo Cardigliano 	}
71801a6c311SAlfredo Cardigliano 
71901a6c311SAlfredo Cardigliano 	rte_free(qcq);
72001a6c311SAlfredo Cardigliano }
72101a6c311SAlfredo Cardigliano 
722a27d9013SAlfredo Cardigliano int
723a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
724a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
725a27d9013SAlfredo Cardigliano {
726a27d9013SAlfredo Cardigliano 	uint32_t flags;
727a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
728a27d9013SAlfredo Cardigliano 
729a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
730*4ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
731*4ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
732*4ad56b7aSAndrew Boyer 		index,
733*4ad56b7aSAndrew Boyer 		"rx",
734*4ad56b7aSAndrew Boyer 		flags,
735a27d9013SAlfredo Cardigliano 		nrxq_descs,
736a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
737a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
738a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
7391abf69fcSAndrew Boyer 		&lif->rxqcqs[index]);
740a27d9013SAlfredo Cardigliano 	if (err)
741a27d9013SAlfredo Cardigliano 		return err;
742a27d9013SAlfredo Cardigliano 
743a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
744a27d9013SAlfredo Cardigliano 
745a27d9013SAlfredo Cardigliano 	return 0;
746a27d9013SAlfredo Cardigliano }
747a27d9013SAlfredo Cardigliano 
748a27d9013SAlfredo Cardigliano int
749a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
750a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
751a27d9013SAlfredo Cardigliano {
752a27d9013SAlfredo Cardigliano 	uint32_t flags;
753a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
754a27d9013SAlfredo Cardigliano 
755a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
756*4ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
757*4ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
758*4ad56b7aSAndrew Boyer 		index,
759*4ad56b7aSAndrew Boyer 		"tx",
760*4ad56b7aSAndrew Boyer 		flags,
761a27d9013SAlfredo Cardigliano 		ntxq_descs,
762a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
763a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
76456117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
7651abf69fcSAndrew Boyer 		&lif->txqcqs[index]);
766a27d9013SAlfredo Cardigliano 	if (err)
767a27d9013SAlfredo Cardigliano 		return err;
768a27d9013SAlfredo Cardigliano 
769a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
770a27d9013SAlfredo Cardigliano 
771a27d9013SAlfredo Cardigliano 	return 0;
772a27d9013SAlfredo Cardigliano }
773a27d9013SAlfredo Cardigliano 
77401a6c311SAlfredo Cardigliano static int
77501a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
77601a6c311SAlfredo Cardigliano {
77701a6c311SAlfredo Cardigliano 	uint32_t flags;
77801a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
77901a6c311SAlfredo Cardigliano 
78001a6c311SAlfredo Cardigliano 	flags = 0;
781*4ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
782*4ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
783*4ad56b7aSAndrew Boyer 		0,
784*4ad56b7aSAndrew Boyer 		"admin",
785*4ad56b7aSAndrew Boyer 		flags,
78601a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
78701a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
78801a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
78901a6c311SAlfredo Cardigliano 		0,
7901abf69fcSAndrew Boyer 		&lif->adminqcq);
79127b942c8SAlfredo Cardigliano 	if (err)
79227b942c8SAlfredo Cardigliano 		return err;
79301a6c311SAlfredo Cardigliano 
79427b942c8SAlfredo Cardigliano 	return 0;
79527b942c8SAlfredo Cardigliano }
79627b942c8SAlfredo Cardigliano 
79727b942c8SAlfredo Cardigliano static int
79827b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
79927b942c8SAlfredo Cardigliano {
8004c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq;
8014c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
8024c8f8d57SAndrew Boyer 	uint32_t flags = 0;
80327b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
80427b942c8SAlfredo Cardigliano 
805*4ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
806*4ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
807*4ad56b7aSAndrew Boyer 		0,
808*4ad56b7aSAndrew Boyer 		"notify",
80927b942c8SAlfredo Cardigliano 		flags,
81027b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
81127b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
81227b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
81327b942c8SAlfredo Cardigliano 		0,
8144c8f8d57SAndrew Boyer 		&nqcq);
81501a6c311SAlfredo Cardigliano 	if (err)
81601a6c311SAlfredo Cardigliano 		return err;
81701a6c311SAlfredo Cardigliano 
8184c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8194c8f8d57SAndrew Boyer 	if (err) {
8204c8f8d57SAndrew Boyer 		ionic_qcq_free(nqcq);
8214c8f8d57SAndrew Boyer 		return err;
8224c8f8d57SAndrew Boyer 	}
8234c8f8d57SAndrew Boyer 
8244c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8254c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8264c8f8d57SAndrew Boyer 
8274c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8284c8f8d57SAndrew Boyer 
82901a6c311SAlfredo Cardigliano 	return 0;
83001a6c311SAlfredo Cardigliano }
83101a6c311SAlfredo Cardigliano 
832c67719e1SAlfredo Cardigliano static void *
833c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
834c67719e1SAlfredo Cardigliano {
835c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
836c67719e1SAlfredo Cardigliano 
837c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
838c67719e1SAlfredo Cardigliano 		return NULL;
839c67719e1SAlfredo Cardigliano 
840c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
841c67719e1SAlfredo Cardigliano }
842c67719e1SAlfredo Cardigliano 
843c5d15850SAndrew Boyer static void
844c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
845c5d15850SAndrew Boyer {
846c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
847c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
848c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
849c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
850c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
851c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
852c5d15850SAndrew Boyer 	int err;
853c5d15850SAndrew Boyer 
854c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
855c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
856c5d15850SAndrew Boyer 
857c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
858c5d15850SAndrew Boyer 		switch (qtype) {
859c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
860c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
861c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
862c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
863c5d15850SAndrew Boyer 			break;
864c5d15850SAndrew Boyer 		default:
865c5d15850SAndrew Boyer 			continue;
866c5d15850SAndrew Boyer 		}
867c5d15850SAndrew Boyer 
868c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
869c5d15850SAndrew Boyer 
870c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
871c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
872c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
873c5d15850SAndrew Boyer 		if (err == -EINVAL) {
874c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
875c5d15850SAndrew Boyer 			continue;
876c5d15850SAndrew Boyer 		} else if (err == -EIO) {
877c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
878c5d15850SAndrew Boyer 			return;
879c5d15850SAndrew Boyer 		} else if (err) {
880c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
881c5d15850SAndrew Boyer 				qtype, err);
882c5d15850SAndrew Boyer 			return;
883c5d15850SAndrew Boyer 		}
884c5d15850SAndrew Boyer 
885c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
886c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
887c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
888c5d15850SAndrew Boyer 
889c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
890c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
891c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
892c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
893c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
894c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
895c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
896c5d15850SAndrew Boyer 		qti->sg_desc_stride =
897c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
898c5d15850SAndrew Boyer 
899c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
900c5d15850SAndrew Boyer 			qtype, qti->version);
901c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
902c5d15850SAndrew Boyer 			qtype, qti->supported);
903c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
904c5d15850SAndrew Boyer 			qtype, qti->features);
905c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
906c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
907c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
908c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
909c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
910c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
911c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
912c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
913c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
914c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
915c5d15850SAndrew Boyer 	}
916c5d15850SAndrew Boyer }
917c5d15850SAndrew Boyer 
918669c8de6SAlfredo Cardigliano int
919669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
920669c8de6SAlfredo Cardigliano {
921c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
922669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
92301a6c311SAlfredo Cardigliano 	int err;
924669c8de6SAlfredo Cardigliano 
9254ae96cb8SAndrew Boyer 	/*
9264ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9274ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9284ae96cb8SAndrew Boyer 	 */
9294ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9304ae96cb8SAndrew Boyer 
9314ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
932669c8de6SAlfredo Cardigliano 
933c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
934c5d15850SAndrew Boyer 
93556117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
93656117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
93756117636SAndrew Boyer 		return -ENXIO;
93856117636SAndrew Boyer 	}
93956117636SAndrew Boyer 
940669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
941669c8de6SAlfredo Cardigliano 
94201a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
94301a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
94401a6c311SAlfredo Cardigliano 
94500b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
946c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
947c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
948c67719e1SAlfredo Cardigliano 		return -ENOMEM;
949c67719e1SAlfredo Cardigliano 	}
950c67719e1SAlfredo Cardigliano 
951a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
952a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
953a27d9013SAlfredo Cardigliano 
954a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
955a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
956a27d9013SAlfredo Cardigliano 		return -ENOMEM;
957a27d9013SAlfredo Cardigliano 	}
958a27d9013SAlfredo Cardigliano 
959a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
960a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
961a27d9013SAlfredo Cardigliano 
962a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
963a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
964a27d9013SAlfredo Cardigliano 		return -ENOMEM;
965a27d9013SAlfredo Cardigliano 	}
966a27d9013SAlfredo Cardigliano 
96727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
96827b942c8SAlfredo Cardigliano 
96927b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
97027b942c8SAlfredo Cardigliano 	if (err) {
97127b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
97227b942c8SAlfredo Cardigliano 		return err;
97327b942c8SAlfredo Cardigliano 	}
97427b942c8SAlfredo Cardigliano 
97527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
97627b942c8SAlfredo Cardigliano 
97701a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
97801a6c311SAlfredo Cardigliano 	if (err) {
97901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
98001a6c311SAlfredo Cardigliano 		return err;
98101a6c311SAlfredo Cardigliano 	}
98201a6c311SAlfredo Cardigliano 
98301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
98401a6c311SAlfredo Cardigliano 
985669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
986669c8de6SAlfredo Cardigliano 
987669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
988669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
989669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
990669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
991669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
992669c8de6SAlfredo Cardigliano 		return -ENOMEM;
993669c8de6SAlfredo Cardigliano 	}
994669c8de6SAlfredo Cardigliano 
995669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
996669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
997669c8de6SAlfredo Cardigliano 
998669c8de6SAlfredo Cardigliano 	return 0;
999669c8de6SAlfredo Cardigliano }
1000669c8de6SAlfredo Cardigliano 
1001669c8de6SAlfredo Cardigliano void
1002669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1003669c8de6SAlfredo Cardigliano {
100427b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
100527b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
100627b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
100727b942c8SAlfredo Cardigliano 	}
100827b942c8SAlfredo Cardigliano 
100901a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
101001a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
101101a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
101201a6c311SAlfredo Cardigliano 	}
101301a6c311SAlfredo Cardigliano 
1014a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1015a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1016a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1017a27d9013SAlfredo Cardigliano 	}
1018a27d9013SAlfredo Cardigliano 
1019a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1020a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1021a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1022a27d9013SAlfredo Cardigliano 	}
1023a27d9013SAlfredo Cardigliano 
1024669c8de6SAlfredo Cardigliano 	if (lif->info) {
1025669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1026669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1027669c8de6SAlfredo Cardigliano 	}
1028669c8de6SAlfredo Cardigliano }
1029669c8de6SAlfredo Cardigliano 
1030175e4e7eSAndrew Boyer void
1031175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1032175e4e7eSAndrew Boyer {
1033175e4e7eSAndrew Boyer 	uint32_t i;
1034175e4e7eSAndrew Boyer 
1035175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
1036175e4e7eSAndrew Boyer 		ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]);
1037175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1038175e4e7eSAndrew Boyer 	}
1039175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
1040175e4e7eSAndrew Boyer 		ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]);
1041175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1042175e4e7eSAndrew Boyer 	}
1043175e4e7eSAndrew Boyer }
1044175e4e7eSAndrew Boyer 
104522e7171bSAlfredo Cardigliano int
104622e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
104722e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
104822e7171bSAlfredo Cardigliano {
104909f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
105022e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
105122e7171bSAlfredo Cardigliano 		.pending_work = true,
105222e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
105322e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
105422e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
105509f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
105609f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
105722e7171bSAlfredo Cardigliano 		},
105822e7171bSAlfredo Cardigliano 	};
105922e7171bSAlfredo Cardigliano 	unsigned int i;
106009f806e9SAndrew Boyer 	uint16_t tbl_sz =
106109f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
106222e7171bSAlfredo Cardigliano 
106322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
106422e7171bSAlfredo Cardigliano 
106522e7171bSAlfredo Cardigliano 	lif->rss_types = types;
106622e7171bSAlfredo Cardigliano 
106722e7171bSAlfredo Cardigliano 	if (key)
106822e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
106922e7171bSAlfredo Cardigliano 
107022e7171bSAlfredo Cardigliano 	if (indir)
107109f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
107222e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
107322e7171bSAlfredo Cardigliano 
107422e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
107522e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
107622e7171bSAlfredo Cardigliano 
107722e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
107822e7171bSAlfredo Cardigliano }
107922e7171bSAlfredo Cardigliano 
108022e7171bSAlfredo Cardigliano static int
108122e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
108222e7171bSAlfredo Cardigliano {
108309f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
108422e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
108522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
108622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
108722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
108822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
108922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109022e7171bSAlfredo Cardigliano 	};
109122e7171bSAlfredo Cardigliano 	uint32_t i;
109209f806e9SAndrew Boyer 	uint16_t tbl_sz =
109309f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
109422e7171bSAlfredo Cardigliano 
109522e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
109622e7171bSAlfredo Cardigliano 
10973d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
109822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
10993d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11003d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11013d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
110222e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
110322e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
110422e7171bSAlfredo Cardigliano 			return -ENOMEM;
110522e7171bSAlfredo Cardigliano 		}
110622e7171bSAlfredo Cardigliano 
110722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
110822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11093d845eddSAndrew Boyer 	}
11103d845eddSAndrew Boyer 
11113d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11123d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
111322e7171bSAlfredo Cardigliano 
111422e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11153d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
111622e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11173d845eddSAndrew Boyer 	}
111822e7171bSAlfredo Cardigliano 
11193d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
112022e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
112122e7171bSAlfredo Cardigliano }
112222e7171bSAlfredo Cardigliano 
112322e7171bSAlfredo Cardigliano static void
112422e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
112522e7171bSAlfredo Cardigliano {
112622e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
112722e7171bSAlfredo Cardigliano 		return;
112822e7171bSAlfredo Cardigliano 
112922e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
113022e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
113122e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
113222e7171bSAlfredo Cardigliano 
113322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
113422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
113522e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
113622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
113722e7171bSAlfredo Cardigliano 	}
113822e7171bSAlfredo Cardigliano }
113922e7171bSAlfredo Cardigliano 
114001a6c311SAlfredo Cardigliano static void
11414c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq)
114201a6c311SAlfredo Cardigliano {
114301a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
114401a6c311SAlfredo Cardigliano }
114501a6c311SAlfredo Cardigliano 
1146a27d9013SAlfredo Cardigliano void
1147a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1148a27d9013SAlfredo Cardigliano {
11494c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
1150a27d9013SAlfredo Cardigliano }
1151a27d9013SAlfredo Cardigliano 
1152a27d9013SAlfredo Cardigliano void
1153a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1154a27d9013SAlfredo Cardigliano {
11554c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
11564c8f8d57SAndrew Boyer }
11574c8f8d57SAndrew Boyer 
11584c8f8d57SAndrew Boyer static void
11594c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
11604c8f8d57SAndrew Boyer {
11614c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq = lif->notifyqcq;
11624c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
11634c8f8d57SAndrew Boyer 
11644c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
11654c8f8d57SAndrew Boyer 		return;
11664c8f8d57SAndrew Boyer 
11674c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
11684c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
11694c8f8d57SAndrew Boyer 
11704c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1171a27d9013SAlfredo Cardigliano }
1172a27d9013SAlfredo Cardigliano 
117301a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
117401a6c311SAlfredo Cardigliano int
117501a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
117601a6c311SAlfredo Cardigliano 		void *cb_arg)
117701a6c311SAlfredo Cardigliano {
117801a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
117901a6c311SAlfredo Cardigliano 	uint32_t work_done;
118001a6c311SAlfredo Cardigliano 
118101a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
118201a6c311SAlfredo Cardigliano 
118301a6c311SAlfredo Cardigliano 	return work_done;
118401a6c311SAlfredo Cardigliano }
118501a6c311SAlfredo Cardigliano 
118627b942c8SAlfredo Cardigliano static void
118727b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
118827b942c8SAlfredo Cardigliano {
118927b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
119027b942c8SAlfredo Cardigliano 	bool link_up;
119127b942c8SAlfredo Cardigliano 
119227b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
119327b942c8SAlfredo Cardigliano 
119427b942c8SAlfredo Cardigliano 	if (!lif->info)
119527b942c8SAlfredo Cardigliano 		return;
119627b942c8SAlfredo Cardigliano 
119727b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
119827b942c8SAlfredo Cardigliano 
119927b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
120027b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
120127b942c8SAlfredo Cardigliano 		return;
120227b942c8SAlfredo Cardigliano 
120327b942c8SAlfredo Cardigliano 	if (link_up) {
120409f806e9SAndrew Boyer 		adapter->link_speed =
120509f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1206be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1207be63459eSAndrew Boyer 			adapter->link_speed);
120827b942c8SAlfredo Cardigliano 	} else {
120927b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
121027b942c8SAlfredo Cardigliano 	}
121127b942c8SAlfredo Cardigliano 
121227b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1213be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1214be63459eSAndrew Boyer }
1215be63459eSAndrew Boyer 
1216be63459eSAndrew Boyer static void
1217be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1218be63459eSAndrew Boyer {
1219be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1220be63459eSAndrew Boyer 		return;
1221be63459eSAndrew Boyer 
1222be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1223be63459eSAndrew Boyer 
1224be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1225be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1226be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1227be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1228be63459eSAndrew Boyer 	}
1229be63459eSAndrew Boyer 
1230be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
123127b942c8SAlfredo Cardigliano }
123227b942c8SAlfredo Cardigliano 
123327b942c8SAlfredo Cardigliano static bool
1234*4ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
123527b942c8SAlfredo Cardigliano {
123627b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
123727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
123827b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
123927b942c8SAlfredo Cardigliano 
124027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
124127b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
124227b942c8SAlfredo Cardigliano 
124327b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
124427b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
124527b942c8SAlfredo Cardigliano 		return false;
124627b942c8SAlfredo Cardigliano 
124727b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
124827b942c8SAlfredo Cardigliano 
124927b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
125027b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
125127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1252be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1253be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1254be63459eSAndrew Boyer 			lif->name,
125527b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
125627b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
125727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
125827b942c8SAlfredo Cardigliano 
125927b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
126027b942c8SAlfredo Cardigliano 		break;
1261be63459eSAndrew Boyer 
1262be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1263be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1264be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1265be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1266be63459eSAndrew Boyer 			lif->name,
1267be63459eSAndrew Boyer 			cq_desc->event.eid,
1268be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1269be63459eSAndrew Boyer 			cq_desc->reset.state);
1270be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1271be63459eSAndrew Boyer 		break;
1272be63459eSAndrew Boyer 
127327b942c8SAlfredo Cardigliano 	default:
127427b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
127527b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
127627b942c8SAlfredo Cardigliano 		break;
127727b942c8SAlfredo Cardigliano 	}
127827b942c8SAlfredo Cardigliano 
127927b942c8SAlfredo Cardigliano 	return true;
128027b942c8SAlfredo Cardigliano }
128127b942c8SAlfredo Cardigliano 
128227b942c8SAlfredo Cardigliano int
128327b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
128427b942c8SAlfredo Cardigliano {
128527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
128627b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
128727b942c8SAlfredo Cardigliano 	uint32_t work_done;
128827b942c8SAlfredo Cardigliano 
128927b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
129027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
129127b942c8SAlfredo Cardigliano 		return -1;
129227b942c8SAlfredo Cardigliano 	}
129327b942c8SAlfredo Cardigliano 
129427b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
129527b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
129627b942c8SAlfredo Cardigliano 
129727b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
129827b942c8SAlfredo Cardigliano 
129927b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
130027b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
130127b942c8SAlfredo Cardigliano 
130227b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
130327b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
130427b942c8SAlfredo Cardigliano 
130527b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
130627b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
130727b942c8SAlfredo Cardigliano 
130827b942c8SAlfredo Cardigliano 	return 0;
130927b942c8SAlfredo Cardigliano }
131027b942c8SAlfredo Cardigliano 
131101a6c311SAlfredo Cardigliano static int
131201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
131301a6c311SAlfredo Cardigliano {
131401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
131501a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
131601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
131701a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
131801a6c311SAlfredo Cardigliano 	int err;
131901a6c311SAlfredo Cardigliano 
13204c8f8d57SAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, qcq);
132101a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
132201a6c311SAlfredo Cardigliano 	if (err)
132301a6c311SAlfredo Cardigliano 		return err;
132401a6c311SAlfredo Cardigliano 
132501a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
132601a6c311SAlfredo Cardigliano 
132701a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
132809f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
132901a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
133001a6c311SAlfredo Cardigliano 
133101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
133201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
133301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
133401a6c311SAlfredo Cardigliano 
133501a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
133601a6c311SAlfredo Cardigliano 
133701a6c311SAlfredo Cardigliano 	return 0;
133801a6c311SAlfredo Cardigliano }
133901a6c311SAlfredo Cardigliano 
134027b942c8SAlfredo Cardigliano static int
134127b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
134227b942c8SAlfredo Cardigliano {
134327b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
134427b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
134527b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
134627b942c8SAlfredo Cardigliano 	int err;
134727b942c8SAlfredo Cardigliano 
134827b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
134927b942c8SAlfredo Cardigliano 		.pending_work = true,
135027b942c8SAlfredo Cardigliano 		.cmd.q_init = {
135127b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
135227b942c8SAlfredo Cardigliano 			.type = q->type,
1353c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
135409f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
135509f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(qcq->intr.index),
135609f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ |
135709f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
135827b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
135909f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
136027b942c8SAlfredo Cardigliano 		}
136127b942c8SAlfredo Cardigliano 	};
136227b942c8SAlfredo Cardigliano 
136309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
136409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
136527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
136627b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13674ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
136827b942c8SAlfredo Cardigliano 
136927b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
137027b942c8SAlfredo Cardigliano 	if (err)
137127b942c8SAlfredo Cardigliano 		return err;
137227b942c8SAlfredo Cardigliano 
137327b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
137409f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
137527b942c8SAlfredo Cardigliano 	q->db = NULL;
137627b942c8SAlfredo Cardigliano 
137727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
137827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
137927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
138027b942c8SAlfredo Cardigliano 
138127b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
138227b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
138327b942c8SAlfredo Cardigliano 
138427b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
138527b942c8SAlfredo Cardigliano 
138627b942c8SAlfredo Cardigliano 	return 0;
138727b942c8SAlfredo Cardigliano }
138827b942c8SAlfredo Cardigliano 
1389669c8de6SAlfredo Cardigliano int
1390598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1391598f6726SAlfredo Cardigliano {
1392598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1393598f6726SAlfredo Cardigliano 		.pending_work = true,
1394598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1395598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1396598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
139709f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1398598f6726SAlfredo Cardigliano 		},
1399598f6726SAlfredo Cardigliano 	};
1400598f6726SAlfredo Cardigliano 	int err;
1401598f6726SAlfredo Cardigliano 
1402598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1403598f6726SAlfredo Cardigliano 	if (err)
1404598f6726SAlfredo Cardigliano 		return err;
1405598f6726SAlfredo Cardigliano 
140609f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1407598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1408598f6726SAlfredo Cardigliano 
1409598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1410598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1411598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1412598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1413598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1414598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1415598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1416598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1417598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1418598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1419598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1420598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1421598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1422598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1423598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1424598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1425598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1426598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1427598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1428598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1429598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1430598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1431598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1432598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1433598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1434598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1435598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1436598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1437598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1438598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1439598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1440598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1441598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1442598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1443598f6726SAlfredo Cardigliano 
1444598f6726SAlfredo Cardigliano 	return 0;
1445598f6726SAlfredo Cardigliano }
1446598f6726SAlfredo Cardigliano 
1447a27d9013SAlfredo Cardigliano int
1448a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1449a27d9013SAlfredo Cardigliano {
1450a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1451a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1452a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1453a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1454a27d9013SAlfredo Cardigliano 		.pending_work = true,
1455a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1456a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1457a27d9013SAlfredo Cardigliano 			.type = q->type,
1458c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
145909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
146009f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
146109f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
146209f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1463a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
146409f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
146509f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
146609f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1467a27d9013SAlfredo Cardigliano 		},
1468a27d9013SAlfredo Cardigliano 	};
1469a27d9013SAlfredo Cardigliano 	int err;
1470a27d9013SAlfredo Cardigliano 
147109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
147209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1473a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1474a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14754ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1476a27d9013SAlfredo Cardigliano 
1477a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1478a27d9013SAlfredo Cardigliano 	if (err)
1479a27d9013SAlfredo Cardigliano 		return err;
1480a27d9013SAlfredo Cardigliano 
1481a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
148209f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1483a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1484a27d9013SAlfredo Cardigliano 
1485a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1486a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1487a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1488a27d9013SAlfredo Cardigliano 
1489a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1490a27d9013SAlfredo Cardigliano 
1491a27d9013SAlfredo Cardigliano 	return 0;
1492a27d9013SAlfredo Cardigliano }
1493a27d9013SAlfredo Cardigliano 
1494a27d9013SAlfredo Cardigliano int
1495a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1496a27d9013SAlfredo Cardigliano {
1497a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1498a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1499a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1500a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1501a27d9013SAlfredo Cardigliano 		.pending_work = true,
1502a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1503a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1504a27d9013SAlfredo Cardigliano 			.type = q->type,
1505c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
150609f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
150709f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
150809f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
150909f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1510a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
151109f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
151209f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
151309f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1514a27d9013SAlfredo Cardigliano 		},
1515a27d9013SAlfredo Cardigliano 	};
1516a27d9013SAlfredo Cardigliano 	int err;
1517a27d9013SAlfredo Cardigliano 
151809f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
151909f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1520a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1521a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15224ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1523a27d9013SAlfredo Cardigliano 
1524a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1525a27d9013SAlfredo Cardigliano 	if (err)
1526a27d9013SAlfredo Cardigliano 		return err;
1527a27d9013SAlfredo Cardigliano 
1528a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
152909f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1530a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1531a27d9013SAlfredo Cardigliano 
1532a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1533a27d9013SAlfredo Cardigliano 
1534a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1535a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1536a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1537a27d9013SAlfredo Cardigliano 
1538a27d9013SAlfredo Cardigliano 	return 0;
1539a27d9013SAlfredo Cardigliano }
1540a27d9013SAlfredo Cardigliano 
1541598f6726SAlfredo Cardigliano static int
1542598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1543598f6726SAlfredo Cardigliano {
1544598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1545598f6726SAlfredo Cardigliano 		.pending_work = true,
1546598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1547598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1548598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1549598f6726SAlfredo Cardigliano 		},
1550598f6726SAlfredo Cardigliano 	};
1551598f6726SAlfredo Cardigliano 	int err;
1552598f6726SAlfredo Cardigliano 
1553598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1554598f6726SAlfredo Cardigliano 
1555598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1556598f6726SAlfredo Cardigliano 	if (err)
1557598f6726SAlfredo Cardigliano 		return err;
1558598f6726SAlfredo Cardigliano 
1559598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1560598f6726SAlfredo Cardigliano 
1561598f6726SAlfredo Cardigliano 	return 0;
1562598f6726SAlfredo Cardigliano }
1563598f6726SAlfredo Cardigliano 
1564598f6726SAlfredo Cardigliano static void
1565598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1566598f6726SAlfredo Cardigliano {
1567598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1568598f6726SAlfredo Cardigliano 		.pending_work = true,
1569598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1570598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1571598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1572598f6726SAlfredo Cardigliano 		},
1573598f6726SAlfredo Cardigliano 	};
1574598f6726SAlfredo Cardigliano 
15754ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
15764ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1577598f6726SAlfredo Cardigliano 
1578598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1579598f6726SAlfredo Cardigliano }
1580598f6726SAlfredo Cardigliano 
1581598f6726SAlfredo Cardigliano int
1582669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1583669c8de6SAlfredo Cardigliano {
1584669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1585669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1586669c8de6SAlfredo Cardigliano 	int err;
1587669c8de6SAlfredo Cardigliano 
15883cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
15893cdfd905SAlfredo Cardigliano 
159000b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1591669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1592669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1593669c8de6SAlfredo Cardigliano 	if (err)
1594669c8de6SAlfredo Cardigliano 		return err;
1595669c8de6SAlfredo Cardigliano 
159609f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1597669c8de6SAlfredo Cardigliano 
159801a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
159901a6c311SAlfredo Cardigliano 	if (err)
160001a6c311SAlfredo Cardigliano 		return err;
160101a6c311SAlfredo Cardigliano 
160227b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
160327b942c8SAlfredo Cardigliano 	if (err)
160427b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
160527b942c8SAlfredo Cardigliano 
160618a44465SAndrew Boyer 	/*
160718a44465SAndrew Boyer 	 * Configure initial feature set
160818a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
160918a44465SAndrew Boyer 	 */
161018a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1611598f6726SAlfredo Cardigliano 
1612598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1613598f6726SAlfredo Cardigliano 	if (err)
1614598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1615598f6726SAlfredo Cardigliano 
161654fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1617598f6726SAlfredo Cardigliano 	if (err)
1618598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1619598f6726SAlfredo Cardigliano 
162054fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
162154fe083fSAlfredo Cardigliano 	if (err)
162254fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
162354fe083fSAlfredo Cardigliano 
1624598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1625598f6726SAlfredo Cardigliano 
1626669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1627669c8de6SAlfredo Cardigliano 
1628669c8de6SAlfredo Cardigliano 	return 0;
162927b942c8SAlfredo Cardigliano 
163054fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
163154fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
163254fe083fSAlfredo Cardigliano 
1633598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
16344c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1635598f6726SAlfredo Cardigliano 
163627b942c8SAlfredo Cardigliano err_out_adminq_deinit:
16374c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
163827b942c8SAlfredo Cardigliano 
163927b942c8SAlfredo Cardigliano 	return err;
1640669c8de6SAlfredo Cardigliano }
1641669c8de6SAlfredo Cardigliano 
1642669c8de6SAlfredo Cardigliano void
1643669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1644669c8de6SAlfredo Cardigliano {
1645669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1646669c8de6SAlfredo Cardigliano 		return;
1647669c8de6SAlfredo Cardigliano 
164854fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
164922e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
16504c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
16514c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
165201a6c311SAlfredo Cardigliano 
1653669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1654669c8de6SAlfredo Cardigliano }
1655669c8de6SAlfredo Cardigliano 
165618a44465SAndrew Boyer void
165718a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
165818a44465SAndrew Boyer {
165918a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
166018a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
166118a44465SAndrew Boyer 
166218a44465SAndrew Boyer 	/*
166318a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
166418a44465SAndrew Boyer 	 * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK
166518a44465SAndrew Boyer 	 */
166618a44465SAndrew Boyer 	rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
166718a44465SAndrew Boyer 
166818a44465SAndrew Boyer 	if (mask & ETH_VLAN_STRIP_MASK) {
166918a44465SAndrew Boyer 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
167018a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
167118a44465SAndrew Boyer 		else
167218a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
167318a44465SAndrew Boyer 	}
167418a44465SAndrew Boyer }
167518a44465SAndrew Boyer 
167618a44465SAndrew Boyer void
1677598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1678598f6726SAlfredo Cardigliano {
167918a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
168018a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
168122e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
168209f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
168322e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
168409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
168522e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
168609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
168722e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
168822e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
168922e7171bSAlfredo Cardigliano 
1690598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1691598f6726SAlfredo Cardigliano 
169222e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
169322e7171bSAlfredo Cardigliano 		lif->port_id);
169422e7171bSAlfredo Cardigliano 
169522e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
169622e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
169722e7171bSAlfredo Cardigliano 
169822e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
169922e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
170022e7171bSAlfredo Cardigliano 
170122e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
170222e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1703a27d9013SAlfredo Cardigliano 
170418a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
170518a44465SAndrew Boyer 
170618a44465SAndrew Boyer 	/*
170718a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
170818a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
170918a44465SAndrew Boyer 	 * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH;
171018a44465SAndrew Boyer 	 */
171118a44465SAndrew Boyer 
171218a44465SAndrew Boyer 	/* RX per-port */
171318a44465SAndrew Boyer 
171418a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM ||
171518a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM ||
171618a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM)
171718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
171818a44465SAndrew Boyer 	else
171918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
172018a44465SAndrew Boyer 
172118a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) {
172218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
172318a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
172418a44465SAndrew Boyer 	} else {
172518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
172618a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
172718a44465SAndrew Boyer 	}
172818a44465SAndrew Boyer 
172918a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
173018a44465SAndrew Boyer 	ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK);
173118a44465SAndrew Boyer 
173218a44465SAndrew Boyer 	/* TX per-port */
173318a44465SAndrew Boyer 
173418a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM ||
173518a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM ||
173618a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM ||
173718a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
173818a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
173918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
174018a44465SAndrew Boyer 	else
174118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
174218a44465SAndrew Boyer 
174318a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
174418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
174518a44465SAndrew Boyer 	else
174618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
174718a44465SAndrew Boyer 
174818a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
174918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
175018a44465SAndrew Boyer 	else
175118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
175218a44465SAndrew Boyer 
175318a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) {
175418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
175518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
175618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
175718a44465SAndrew Boyer 	} else {
175818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
175918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
176018a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
176118a44465SAndrew Boyer 	}
1762598f6726SAlfredo Cardigliano }
1763598f6726SAlfredo Cardigliano 
1764598f6726SAlfredo Cardigliano int
1765598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1766598f6726SAlfredo Cardigliano {
17670578335aSAndrew Boyer 	uint32_t rx_mode;
1768a27d9013SAlfredo Cardigliano 	uint32_t i;
1769a27d9013SAlfredo Cardigliano 	int err;
1770598f6726SAlfredo Cardigliano 
177122e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
177222e7171bSAlfredo Cardigliano 	if (err)
177322e7171bSAlfredo Cardigliano 		return err;
177422e7171bSAlfredo Cardigliano 
17750578335aSAndrew Boyer 	if (!lif->rx_mode) {
17760578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
17770578335aSAndrew Boyer 			lif->name);
1778598f6726SAlfredo Cardigliano 
17790578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1780598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1781598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1782598f6726SAlfredo Cardigliano 
1783598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
17840578335aSAndrew Boyer 	}
1785598f6726SAlfredo Cardigliano 
1786a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1787a27d9013SAlfredo Cardigliano 		"on port %u",
1788a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1789a27d9013SAlfredo Cardigliano 
1790a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1791a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
179202eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1793a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1794a27d9013SAlfredo Cardigliano 
1795a27d9013SAlfredo Cardigliano 			if (err)
1796a27d9013SAlfredo Cardigliano 				return err;
1797a27d9013SAlfredo Cardigliano 		}
1798a27d9013SAlfredo Cardigliano 	}
1799a27d9013SAlfredo Cardigliano 
1800a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1801a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
180202eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1803a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1804a27d9013SAlfredo Cardigliano 
1805a27d9013SAlfredo Cardigliano 			if (err)
1806a27d9013SAlfredo Cardigliano 				return err;
1807a27d9013SAlfredo Cardigliano 		}
1808a27d9013SAlfredo Cardigliano 	}
1809a27d9013SAlfredo Cardigliano 
1810598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1811be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1812be63459eSAndrew Boyer 
1813be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1814598f6726SAlfredo Cardigliano 
1815598f6726SAlfredo Cardigliano 	return 0;
1816598f6726SAlfredo Cardigliano }
1817598f6726SAlfredo Cardigliano 
1818598f6726SAlfredo Cardigliano int
1819669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1820669c8de6SAlfredo Cardigliano {
1821669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1822669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
182309f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
182476276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
182576276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
182676276d71SAndrew Boyer 	uint32_t i, nwords;
1827669c8de6SAlfredo Cardigliano 	int err;
1828669c8de6SAlfredo Cardigliano 
1829669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1830669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1831669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1832669c8de6SAlfredo Cardigliano 	if (err)
1833669c8de6SAlfredo Cardigliano 		return (err);
1834669c8de6SAlfredo Cardigliano 
1835669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1836669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1837669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1838669c8de6SAlfredo Cardigliano 
1839669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
184009f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1841669c8de6SAlfredo Cardigliano 
1842669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
184309f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1844669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
184509f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1846669c8de6SAlfredo Cardigliano 
1847669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
184809f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1849669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
185009f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1851669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
185209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1853669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
185409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1855669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
185609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1857669c8de6SAlfredo Cardigliano 
1858669c8de6SAlfredo Cardigliano 	return 0;
1859669c8de6SAlfredo Cardigliano }
1860669c8de6SAlfredo Cardigliano 
1861669c8de6SAlfredo Cardigliano int
1862669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1863669c8de6SAlfredo Cardigliano {
1864669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
186509f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
186609f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1867669c8de6SAlfredo Cardigliano 
1868669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
186909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1870669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
187109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1872669c8de6SAlfredo Cardigliano 
187300b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1874669c8de6SAlfredo Cardigliano 
1875669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
18764ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
18774ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1878669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1879669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1880669c8de6SAlfredo Cardigliano 	}
1881669c8de6SAlfredo Cardigliano 
1882669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1883669c8de6SAlfredo Cardigliano 
1884669c8de6SAlfredo Cardigliano 	return 0;
1885669c8de6SAlfredo Cardigliano }
1886