xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 0a00bdaf0b57198c150e70c3831cac2a60504d0d)
176668754SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
2a5205992SAndrew Boyer  * Copyright 2018-2022 Advanced Micro Devices, Inc.
3669c8de6SAlfredo Cardigliano  */
4669c8de6SAlfredo Cardigliano 
5669c8de6SAlfredo Cardigliano #include <rte_malloc.h>
6df96fd0dSBruce Richardson #include <ethdev_driver.h>
7669c8de6SAlfredo Cardigliano 
8669c8de6SAlfredo Cardigliano #include "ionic.h"
9669c8de6SAlfredo Cardigliano #include "ionic_logs.h"
10669c8de6SAlfredo Cardigliano #include "ionic_lif.h"
11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h"
1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h"
13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h"
14669c8de6SAlfredo Cardigliano 
15c5d15850SAndrew Boyer /* queuetype support level */
16c5d15850SAndrew Boyer static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = {
17c5d15850SAndrew Boyer 	[IONIC_QTYPE_ADMINQ]  = 0,   /* 0 = Base version with CQ support */
18c5d15850SAndrew Boyer 	[IONIC_QTYPE_NOTIFYQ] = 0,   /* 0 = Base version */
19c5d15850SAndrew Boyer 	[IONIC_QTYPE_RXQ]     = 2,   /* 0 = Base version with CQ+SG support
20c5d15850SAndrew Boyer 				      * 1 =       ... with EQ
21c5d15850SAndrew Boyer 				      * 2 =       ... with CMB
22c5d15850SAndrew Boyer 				      */
23c5d15850SAndrew Boyer 	[IONIC_QTYPE_TXQ]     = 3,   /* 0 = Base version with CQ+SG support
24c5d15850SAndrew Boyer 				      * 1 =   ... with Tx SG version 1
25c5d15850SAndrew Boyer 				      * 2 =       ... with EQ
26c5d15850SAndrew Boyer 				      * 3 =       ... with CMB
27c5d15850SAndrew Boyer 				      */
28c5d15850SAndrew Boyer };
29c5d15850SAndrew Boyer 
30598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
31598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
32598f6726SAlfredo Cardigliano 
3301a6c311SAlfredo Cardigliano int
3401a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq)
3501a6c311SAlfredo Cardigliano {
3601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
374ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
3801a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
3901a6c311SAlfredo Cardigliano 		.pending_work = true,
4001a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4101a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4201a6c311SAlfredo Cardigliano 			.type = q->type,
4309f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4401a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
4501a6c311SAlfredo Cardigliano 		},
4601a6c311SAlfredo Cardigliano 	};
4701a6c311SAlfredo Cardigliano 
4801a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4901a6c311SAlfredo Cardigliano }
5001a6c311SAlfredo Cardigliano 
5101a6c311SAlfredo Cardigliano int
5201a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
5301a6c311SAlfredo Cardigliano {
5401a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
554ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
5601a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
5701a6c311SAlfredo Cardigliano 		.pending_work = true,
5801a6c311SAlfredo Cardigliano 		.cmd.q_control = {
5901a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
6001a6c311SAlfredo Cardigliano 			.type = q->type,
6109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
6201a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
6301a6c311SAlfredo Cardigliano 		},
6401a6c311SAlfredo Cardigliano 	};
6501a6c311SAlfredo Cardigliano 
6601a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6701a6c311SAlfredo Cardigliano }
6801a6c311SAlfredo Cardigliano 
69be63459eSAndrew Boyer void
70be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
71598f6726SAlfredo Cardigliano {
72a0a99f21SAndrew Boyer 	uint32_t i;
73a0a99f21SAndrew Boyer 
74be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
75598f6726SAlfredo Cardigliano 
76be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
77a0a99f21SAndrew Boyer 
78a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
79be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
80a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
81a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
82a0a99f21SAndrew Boyer 	}
83a0a99f21SAndrew Boyer 
84a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
85be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
86a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
87a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
88a0a99f21SAndrew Boyer 	}
89598f6726SAlfredo Cardigliano }
90598f6726SAlfredo Cardigliano 
91598f6726SAlfredo Cardigliano void
92598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
93598f6726SAlfredo Cardigliano {
94598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
9575f96902SAndrew Boyer 	int err;
96598f6726SAlfredo Cardigliano 
97598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
98598f6726SAlfredo Cardigliano 
9900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
10075f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
10175f96902SAndrew Boyer 	if (err)
1024ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
103598f6726SAlfredo Cardigliano }
104598f6726SAlfredo Cardigliano 
1053cdfd905SAlfredo Cardigliano static void
1063cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
1073cdfd905SAlfredo Cardigliano {
1083cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
1093cdfd905SAlfredo Cardigliano 	uint32_t i;
1103cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
1113cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1123cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
1133cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1143cdfd905SAlfredo Cardigliano 
1153cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1163cdfd905SAlfredo Cardigliano 
1173cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1183cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1193cdfd905SAlfredo Cardigliano 			lif->port_id);
1203cdfd905SAlfredo Cardigliano 		return;
1213cdfd905SAlfredo Cardigliano 	}
1223cdfd905SAlfredo Cardigliano 
1233cdfd905SAlfredo Cardigliano 	/* RX */
1243cdfd905SAlfredo Cardigliano 
1253cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1263cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1273cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1283cdfd905SAlfredo Cardigliano 
1293cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1303cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1313cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1323cdfd905SAlfredo Cardigliano 
1333cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
134be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
13526cc5dc2SAndrew Boyer 		stats->ierrors +=
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 
14726cc5dc2SAndrew Boyer 	stats->ierrors +=
1483cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1493cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1503cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1513cdfd905SAlfredo Cardigliano 
1523cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
153be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1543cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1553cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1563cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1573cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1583cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1593cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1603cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1613cdfd905SAlfredo Cardigliano 	}
1623cdfd905SAlfredo Cardigliano 
1633cdfd905SAlfredo Cardigliano 	/* TX */
1643cdfd905SAlfredo Cardigliano 
1653cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1663cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1673cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1683cdfd905SAlfredo Cardigliano 
1693cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1703cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1713cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1723cdfd905SAlfredo Cardigliano 
1733cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
174be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1753cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1763cdfd905SAlfredo Cardigliano 	}
1773cdfd905SAlfredo Cardigliano 
1783cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1793cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1803cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1813cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1823cdfd905SAlfredo Cardigliano 
1833cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1843cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1853cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1863cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1873cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1883cdfd905SAlfredo Cardigliano 
1893cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
190be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1913cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1923cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1933cdfd905SAlfredo Cardigliano 	}
1943cdfd905SAlfredo Cardigliano }
1953cdfd905SAlfredo Cardigliano 
1963cdfd905SAlfredo Cardigliano void
1973cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1983cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1993cdfd905SAlfredo Cardigliano {
2003cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
2013cdfd905SAlfredo Cardigliano 
2023cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
2033cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
2043cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
2053cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
2063cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
2073cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
2083cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
2093cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
2103cdfd905SAlfredo Cardigliano }
2113cdfd905SAlfredo Cardigliano 
2123cdfd905SAlfredo Cardigliano void
2133cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2143cdfd905SAlfredo Cardigliano {
2153cdfd905SAlfredo Cardigliano 	uint32_t i;
2163cdfd905SAlfredo Cardigliano 
2173cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
218be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
2193cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
220be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
2213cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2223cdfd905SAlfredo Cardigliano 	}
2233cdfd905SAlfredo Cardigliano 
2243cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2253cdfd905SAlfredo Cardigliano }
2263cdfd905SAlfredo Cardigliano 
2273cdfd905SAlfredo Cardigliano void
2283cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2293cdfd905SAlfredo Cardigliano {
2303cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2313cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2323cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2333cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2343cdfd905SAlfredo Cardigliano 
2353cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2363cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2373cdfd905SAlfredo Cardigliano }
2383cdfd905SAlfredo Cardigliano 
2393cdfd905SAlfredo Cardigliano void
2403cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2413cdfd905SAlfredo Cardigliano {
2423cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2433cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2443cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2453cdfd905SAlfredo Cardigliano 
2463cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2473cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2483cdfd905SAlfredo Cardigliano }
2493cdfd905SAlfredo Cardigliano 
250598f6726SAlfredo Cardigliano static int
25154fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
252598f6726SAlfredo Cardigliano {
25354fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25454fe083fSAlfredo Cardigliano 		.pending_work = true,
25554fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
25654fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
25709f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
25854fe083fSAlfredo Cardigliano 		},
25954fe083fSAlfredo Cardigliano 	};
26054fe083fSAlfredo Cardigliano 	int err;
26154fe083fSAlfredo Cardigliano 
26254fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
26554fe083fSAlfredo Cardigliano 	if (err)
26654fe083fSAlfredo Cardigliano 		return err;
26754fe083fSAlfredo Cardigliano 
26854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
26909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
27054fe083fSAlfredo Cardigliano 
27154fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
27254fe083fSAlfredo Cardigliano }
27354fe083fSAlfredo Cardigliano 
27454fe083fSAlfredo Cardigliano static int
27554fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
27654fe083fSAlfredo Cardigliano {
27754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
27854fe083fSAlfredo Cardigliano 		.pending_work = true,
27954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
28054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
28154fe083fSAlfredo Cardigliano 		},
28254fe083fSAlfredo Cardigliano 	};
28354fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
28454fe083fSAlfredo Cardigliano 	int err;
28554fe083fSAlfredo Cardigliano 
28654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
28754fe083fSAlfredo Cardigliano 
28854fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
28954fe083fSAlfredo Cardigliano 
29054fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
29154fe083fSAlfredo Cardigliano 	if (!f) {
29254fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
29354fe083fSAlfredo Cardigliano 		return -ENOENT;
29454fe083fSAlfredo Cardigliano 	}
29554fe083fSAlfredo Cardigliano 
29609f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
29754fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
29854fe083fSAlfredo Cardigliano 
29954fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
30054fe083fSAlfredo Cardigliano 
30154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
30254fe083fSAlfredo Cardigliano 	if (err)
30354fe083fSAlfredo Cardigliano 		return err;
30454fe083fSAlfredo Cardigliano 
30554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
30609f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
307598f6726SAlfredo Cardigliano 
308598f6726SAlfredo Cardigliano 	return 0;
309598f6726SAlfredo Cardigliano }
310598f6726SAlfredo Cardigliano 
31154fe083fSAlfredo Cardigliano int
31254fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
31354fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
31454fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
315598f6726SAlfredo Cardigliano {
31654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31754fe083fSAlfredo Cardigliano 
31854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31954fe083fSAlfredo Cardigliano 
32054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
32154fe083fSAlfredo Cardigliano }
32254fe083fSAlfredo Cardigliano 
32354fe083fSAlfredo Cardigliano void
32475f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
32554fe083fSAlfredo Cardigliano {
32654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32754fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
32875f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
32954fe083fSAlfredo Cardigliano 
33054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
33354fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
33454fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
33554fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
33654fe083fSAlfredo Cardigliano 		return;
33754fe083fSAlfredo Cardigliano 	}
33854fe083fSAlfredo Cardigliano 
33975f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
34075f96902SAndrew Boyer 
34175f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
34254fe083fSAlfredo Cardigliano 		return;
34354fe083fSAlfredo Cardigliano 
34475f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
34554fe083fSAlfredo Cardigliano }
34654fe083fSAlfredo Cardigliano 
34754fe083fSAlfredo Cardigliano int
34854fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
34954fe083fSAlfredo Cardigliano {
35054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
35154fe083fSAlfredo Cardigliano 
35254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
35354fe083fSAlfredo Cardigliano 
35454fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
35554fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
35654fe083fSAlfredo Cardigliano 		return -1;
35754fe083fSAlfredo Cardigliano 	}
35854fe083fSAlfredo Cardigliano 
35954fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
36054fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
36154fe083fSAlfredo Cardigliano 			lif->mac_addr);
36254fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
36354fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
36454fe083fSAlfredo Cardigliano 	}
36554fe083fSAlfredo Cardigliano 
36654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
36954fe083fSAlfredo Cardigliano 
37054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
37154fe083fSAlfredo Cardigliano }
37254fe083fSAlfredo Cardigliano 
37354fe083fSAlfredo Cardigliano static int
37454fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
37554fe083fSAlfredo Cardigliano {
37654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37754fe083fSAlfredo Cardigliano 		.pending_work = true,
37854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
37954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
38009f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
38109f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
38254fe083fSAlfredo Cardigliano 		},
38354fe083fSAlfredo Cardigliano 	};
38454fe083fSAlfredo Cardigliano 	int err;
38554fe083fSAlfredo Cardigliano 
38654fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
38754fe083fSAlfredo Cardigliano 	if (err)
38854fe083fSAlfredo Cardigliano 		return err;
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
39109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
39254fe083fSAlfredo Cardigliano 
39354fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
39454fe083fSAlfredo Cardigliano }
39554fe083fSAlfredo Cardigliano 
39654fe083fSAlfredo Cardigliano static int
39754fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
39854fe083fSAlfredo Cardigliano {
39954fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
40054fe083fSAlfredo Cardigliano 		.pending_work = true,
40154fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
40254fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
40354fe083fSAlfredo Cardigliano 		},
40454fe083fSAlfredo Cardigliano 	};
40554fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
40654fe083fSAlfredo Cardigliano 	int err;
40754fe083fSAlfredo Cardigliano 
40854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
40954fe083fSAlfredo Cardigliano 
41054fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
41154fe083fSAlfredo Cardigliano 
41254fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
41354fe083fSAlfredo Cardigliano 	if (!f) {
41454fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
41554fe083fSAlfredo Cardigliano 		return -ENOENT;
41654fe083fSAlfredo Cardigliano 	}
41754fe083fSAlfredo Cardigliano 
41809f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
41954fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
42054fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
42154fe083fSAlfredo Cardigliano 
42254fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
42354fe083fSAlfredo Cardigliano 	if (err)
42454fe083fSAlfredo Cardigliano 		return err;
42554fe083fSAlfredo Cardigliano 
42654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
42709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
428598f6726SAlfredo Cardigliano 
429598f6726SAlfredo Cardigliano 	return 0;
430598f6726SAlfredo Cardigliano }
431598f6726SAlfredo Cardigliano 
43254fe083fSAlfredo Cardigliano int
43354fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
43454fe083fSAlfredo Cardigliano 		int on)
43554fe083fSAlfredo Cardigliano {
43654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
43754fe083fSAlfredo Cardigliano 	int err;
43854fe083fSAlfredo Cardigliano 
43954fe083fSAlfredo Cardigliano 	if (on)
44054fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
44154fe083fSAlfredo Cardigliano 	else
44254fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
44354fe083fSAlfredo Cardigliano 
44454fe083fSAlfredo Cardigliano 	return err;
44554fe083fSAlfredo Cardigliano }
44654fe083fSAlfredo Cardigliano 
447598f6726SAlfredo Cardigliano static void
448598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
449598f6726SAlfredo Cardigliano {
450598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
451598f6726SAlfredo Cardigliano 		.pending_work = true,
452598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
453598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
45409f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
455598f6726SAlfredo Cardigliano 		},
456598f6726SAlfredo Cardigliano 	};
457598f6726SAlfredo Cardigliano 	int err;
458598f6726SAlfredo Cardigliano 
459598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
460598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
461598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
462598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
463598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
464598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
465598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
466598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
467598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
468598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
469598f6726SAlfredo Cardigliano 
470598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
471598f6726SAlfredo Cardigliano 	if (err)
472598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
473598f6726SAlfredo Cardigliano }
474598f6726SAlfredo Cardigliano 
475598f6726SAlfredo Cardigliano static void
476598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
477598f6726SAlfredo Cardigliano {
478598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
479598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
480598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
481598f6726SAlfredo Cardigliano 	}
482598f6726SAlfredo Cardigliano }
483598f6726SAlfredo Cardigliano 
48454fe083fSAlfredo Cardigliano int
48554fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
48654fe083fSAlfredo Cardigliano {
48754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
49354fe083fSAlfredo Cardigliano 
49454fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	return 0;
49754fe083fSAlfredo Cardigliano }
49854fe083fSAlfredo Cardigliano 
49954fe083fSAlfredo Cardigliano int
50054fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
50154fe083fSAlfredo Cardigliano {
50254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50354fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
50654fe083fSAlfredo Cardigliano 
50754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	return 0;
51054fe083fSAlfredo Cardigliano }
51154fe083fSAlfredo Cardigliano 
51254fe083fSAlfredo Cardigliano int
51354fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
51454fe083fSAlfredo Cardigliano {
51554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
51954fe083fSAlfredo Cardigliano 
52054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52154fe083fSAlfredo Cardigliano 
52254fe083fSAlfredo Cardigliano 	return 0;
52354fe083fSAlfredo Cardigliano }
52454fe083fSAlfredo Cardigliano 
52554fe083fSAlfredo Cardigliano int
52654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
52754fe083fSAlfredo Cardigliano {
52854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
52954fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
53054fe083fSAlfredo Cardigliano 
53154fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
53254fe083fSAlfredo Cardigliano 
53354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
53454fe083fSAlfredo Cardigliano 
53554fe083fSAlfredo Cardigliano 	return 0;
53654fe083fSAlfredo Cardigliano }
537598f6726SAlfredo Cardigliano 
538598f6726SAlfredo Cardigliano int
539b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
540598f6726SAlfredo Cardigliano {
541598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
542598f6726SAlfredo Cardigliano 		.pending_work = true,
543598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
544598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
545598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
54609f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
547598f6726SAlfredo Cardigliano 		},
548598f6726SAlfredo Cardigliano 	};
549598f6726SAlfredo Cardigliano 
550b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
551598f6726SAlfredo Cardigliano }
552598f6726SAlfredo Cardigliano 
553598f6726SAlfredo Cardigliano int
55401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
55501a6c311SAlfredo Cardigliano {
55601a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
55701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
55801a6c311SAlfredo Cardigliano 	unsigned long index;
55901a6c311SAlfredo Cardigliano 
56001a6c311SAlfredo Cardigliano 	/*
56101a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
56201a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5634ae96cb8SAndrew Boyer 	 * which has index = 0)
56401a6c311SAlfredo Cardigliano 	 */
56501a6c311SAlfredo Cardigliano 
56601a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
56701a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
56801a6c311SAlfredo Cardigliano 			break;
56901a6c311SAlfredo Cardigliano 
57001a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
57101a6c311SAlfredo Cardigliano 		return -ENOSPC;
57201a6c311SAlfredo Cardigliano 
57301a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
57401a6c311SAlfredo Cardigliano 
57501a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
57601a6c311SAlfredo Cardigliano 
57701a6c311SAlfredo Cardigliano 	return 0;
57801a6c311SAlfredo Cardigliano }
57901a6c311SAlfredo Cardigliano 
58001a6c311SAlfredo Cardigliano static int
5814ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5824ad56b7aSAndrew Boyer 		uint8_t type,
583be39f75cSAndrew Boyer 		size_t struct_size,
5848ec5ad7fSAndrew Boyer 		uint32_t socket_id,
58501a6c311SAlfredo Cardigliano 		uint32_t index,
5864ad56b7aSAndrew Boyer 		const char *type_name,
5874ad56b7aSAndrew Boyer 		uint16_t flags,
5884ad56b7aSAndrew Boyer 		uint16_t num_descs,
5894ad56b7aSAndrew Boyer 		uint16_t desc_size,
5904ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5914ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5921abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
59301a6c311SAlfredo Cardigliano {
59401a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
59501a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59601a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
59701a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59801a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59901a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
60001a6c311SAlfredo Cardigliano 	int err;
60101a6c311SAlfredo Cardigliano 
60201a6c311SAlfredo Cardigliano 	*qcq = NULL;
60301a6c311SAlfredo Cardigliano 
60401a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60501a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60601a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60701a6c311SAlfredo Cardigliano 
608924e6b76SThomas Monjalon 	total_size = RTE_ALIGN(q_size, rte_mem_page_size()) +
609924e6b76SThomas Monjalon 			RTE_ALIGN(cq_size, rte_mem_page_size());
61001a6c311SAlfredo Cardigliano 	/*
61101a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61201a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
613924e6b76SThomas Monjalon 	 * Adding rte_mem_page_size().
61401a6c311SAlfredo Cardigliano 	 */
615924e6b76SThomas Monjalon 	total_size += rte_mem_page_size();
61601a6c311SAlfredo Cardigliano 
61701a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
618924e6b76SThomas Monjalon 		total_size += RTE_ALIGN(sg_size, rte_mem_page_size());
619924e6b76SThomas Monjalon 		total_size += rte_mem_page_size();
62001a6c311SAlfredo Cardigliano 	}
62101a6c311SAlfredo Cardigliano 
622be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
62301a6c311SAlfredo Cardigliano 	if (!new) {
62401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62501a6c311SAlfredo Cardigliano 		return -ENOMEM;
62601a6c311SAlfredo Cardigliano 	}
62701a6c311SAlfredo Cardigliano 
62801a6c311SAlfredo Cardigliano 	new->lif = lif;
62901a6c311SAlfredo Cardigliano 
630be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
631be39f75cSAndrew Boyer 				num_descs, sizeof(void *),
632924e6b76SThomas Monjalon 				rte_mem_page_size(), socket_id);
63301a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6354c8f8d57SAndrew Boyer 		err = -ENOMEM;
6364c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
63701a6c311SAlfredo Cardigliano 	}
63801a6c311SAlfredo Cardigliano 
63901a6c311SAlfredo Cardigliano 	new->q.type = type;
64001a6c311SAlfredo Cardigliano 
6414ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64201a6c311SAlfredo Cardigliano 	if (err) {
64301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6444c8f8d57SAndrew Boyer 		goto err_out_free_info;
64501a6c311SAlfredo Cardigliano 	}
64601a6c311SAlfredo Cardigliano 
6472aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
64801a6c311SAlfredo Cardigliano 	if (err) {
64901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6504c8f8d57SAndrew Boyer 		goto err_out_free_info;
65101a6c311SAlfredo Cardigliano 	}
65201a6c311SAlfredo Cardigliano 
65301a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6544ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
65501a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
65601a6c311SAlfredo Cardigliano 
65701a6c311SAlfredo Cardigliano 	if (!new->base_z) {
65801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
65901a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6604c8f8d57SAndrew Boyer 		goto err_out_free_info;
66101a6c311SAlfredo Cardigliano 	}
66201a6c311SAlfredo Cardigliano 
66301a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66401a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
66501a6c311SAlfredo Cardigliano 
66601a6c311SAlfredo Cardigliano 	q_base = new->base;
66701a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
66801a6c311SAlfredo Cardigliano 
669924e6b76SThomas Monjalon 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size,
670924e6b76SThomas Monjalon 			rte_mem_page_size());
671924e6b76SThomas Monjalon 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size,
672924e6b76SThomas Monjalon 			rte_mem_page_size());
67301a6c311SAlfredo Cardigliano 
67401a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
67501a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
676924e6b76SThomas Monjalon 				rte_mem_page_size());
677924e6b76SThomas Monjalon 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size,
678924e6b76SThomas Monjalon 				rte_mem_page_size());
67901a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68001a6c311SAlfredo Cardigliano 	}
68101a6c311SAlfredo Cardigliano 
6824ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6834ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68401a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68501a6c311SAlfredo Cardigliano 
68601a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
68701a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
68801a6c311SAlfredo Cardigliano 
68901a6c311SAlfredo Cardigliano 	*qcq = new;
69001a6c311SAlfredo Cardigliano 
69101a6c311SAlfredo Cardigliano 	return 0;
69201a6c311SAlfredo Cardigliano 
6934c8f8d57SAndrew Boyer err_out_free_info:
6944c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6954c8f8d57SAndrew Boyer err_out_free_qcq:
6964c8f8d57SAndrew Boyer 	rte_free(new);
69701a6c311SAlfredo Cardigliano 
69801a6c311SAlfredo Cardigliano 	return err;
69901a6c311SAlfredo Cardigliano }
70001a6c311SAlfredo Cardigliano 
70101a6c311SAlfredo Cardigliano void
70201a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70301a6c311SAlfredo Cardigliano {
70401a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70501a6c311SAlfredo Cardigliano 		qcq->base = NULL;
70601a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
70701a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
70801a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
70901a6c311SAlfredo Cardigliano 	}
71001a6c311SAlfredo Cardigliano 
71101a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71201a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71301a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71401a6c311SAlfredo Cardigliano 	}
71501a6c311SAlfredo Cardigliano 
71601a6c311SAlfredo Cardigliano 	rte_free(qcq);
71701a6c311SAlfredo Cardigliano }
71801a6c311SAlfredo Cardigliano 
719a27d9013SAlfredo Cardigliano int
7208ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
721be39f75cSAndrew Boyer 		uint16_t nrxq_descs, struct ionic_rx_qcq **rxq_out)
722a27d9013SAlfredo Cardigliano {
723be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
724be39f75cSAndrew Boyer 	uint16_t flags;
725be39f75cSAndrew Boyer 	int err;
726a27d9013SAlfredo Cardigliano 
727a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
728b671e69aSAndrew Boyer 
7294ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7304ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
731be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7328ec5ad7fSAndrew Boyer 		socket_id,
7334ad56b7aSAndrew Boyer 		index,
7344ad56b7aSAndrew Boyer 		"rx",
7354ad56b7aSAndrew Boyer 		flags,
736a27d9013SAlfredo Cardigliano 		nrxq_descs,
737a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
738a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
739a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
740be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
741a27d9013SAlfredo Cardigliano 	if (err)
742a27d9013SAlfredo Cardigliano 		return err;
743a27d9013SAlfredo Cardigliano 
744be39f75cSAndrew Boyer 	rxq->flags = flags;
745be39f75cSAndrew Boyer 
746be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
747be39f75cSAndrew Boyer 	*rxq_out = rxq;
748a27d9013SAlfredo Cardigliano 
749a27d9013SAlfredo Cardigliano 	return 0;
750a27d9013SAlfredo Cardigliano }
751a27d9013SAlfredo Cardigliano 
752a27d9013SAlfredo Cardigliano int
7538ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
754be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
755a27d9013SAlfredo Cardigliano {
756be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
757e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
758be39f75cSAndrew Boyer 	int err;
759a27d9013SAlfredo Cardigliano 
760a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
761e19eea1eSAndrew Boyer 
762e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
763e19eea1eSAndrew Boyer 
7644ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7654ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
766be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
7678ec5ad7fSAndrew Boyer 		socket_id,
7684ad56b7aSAndrew Boyer 		index,
7694ad56b7aSAndrew Boyer 		"tx",
7704ad56b7aSAndrew Boyer 		flags,
771a27d9013SAlfredo Cardigliano 		ntxq_descs,
772a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
773a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
77456117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
775be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
776a27d9013SAlfredo Cardigliano 	if (err)
777a27d9013SAlfredo Cardigliano 		return err;
778a27d9013SAlfredo Cardigliano 
779be39f75cSAndrew Boyer 	txq->flags = flags;
780e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
781be39f75cSAndrew Boyer 
782be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
783be39f75cSAndrew Boyer 	*txq_out = txq;
784a27d9013SAlfredo Cardigliano 
785a27d9013SAlfredo Cardigliano 	return 0;
786a27d9013SAlfredo Cardigliano }
787a27d9013SAlfredo Cardigliano 
78801a6c311SAlfredo Cardigliano static int
78901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
79001a6c311SAlfredo Cardigliano {
791be39f75cSAndrew Boyer 	uint16_t flags = 0;
792be39f75cSAndrew Boyer 	int err;
79301a6c311SAlfredo Cardigliano 
7944ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7954ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
796be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
7978ec5ad7fSAndrew Boyer 		rte_socket_id(),
7984ad56b7aSAndrew Boyer 		0,
7994ad56b7aSAndrew Boyer 		"admin",
8004ad56b7aSAndrew Boyer 		flags,
80101a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
80201a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
80301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
80401a6c311SAlfredo Cardigliano 		0,
805be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
80627b942c8SAlfredo Cardigliano 	if (err)
80727b942c8SAlfredo Cardigliano 		return err;
80801a6c311SAlfredo Cardigliano 
80927b942c8SAlfredo Cardigliano 	return 0;
81027b942c8SAlfredo Cardigliano }
81127b942c8SAlfredo Cardigliano 
81227b942c8SAlfredo Cardigliano static int
81327b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
81427b942c8SAlfredo Cardigliano {
815be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8164c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
817be39f75cSAndrew Boyer 	uint16_t flags = 0;
818be39f75cSAndrew Boyer 	int err;
81927b942c8SAlfredo Cardigliano 
8204ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8214ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
822be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8238ec5ad7fSAndrew Boyer 		rte_socket_id(),
8244ad56b7aSAndrew Boyer 		0,
8254ad56b7aSAndrew Boyer 		"notify",
82627b942c8SAlfredo Cardigliano 		flags,
82727b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
82827b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
82927b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
83027b942c8SAlfredo Cardigliano 		0,
831be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
83201a6c311SAlfredo Cardigliano 	if (err)
83301a6c311SAlfredo Cardigliano 		return err;
83401a6c311SAlfredo Cardigliano 
8354c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8364c8f8d57SAndrew Boyer 	if (err) {
837be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
8384c8f8d57SAndrew Boyer 		return err;
8394c8f8d57SAndrew Boyer 	}
8404c8f8d57SAndrew Boyer 
8414c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8424c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8434c8f8d57SAndrew Boyer 
8444c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8454c8f8d57SAndrew Boyer 
84601a6c311SAlfredo Cardigliano 	return 0;
84701a6c311SAlfredo Cardigliano }
84801a6c311SAlfredo Cardigliano 
849c5d15850SAndrew Boyer static void
850c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
851c5d15850SAndrew Boyer {
852c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
853c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
854c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
855c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
856c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
857c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
858c5d15850SAndrew Boyer 	int err;
859c5d15850SAndrew Boyer 
860c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
861c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
862c5d15850SAndrew Boyer 
863c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
864c5d15850SAndrew Boyer 		switch (qtype) {
865c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
866c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
867c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
868c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
869c5d15850SAndrew Boyer 			break;
870c5d15850SAndrew Boyer 		default:
871c5d15850SAndrew Boyer 			continue;
872c5d15850SAndrew Boyer 		}
873c5d15850SAndrew Boyer 
874c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
875c5d15850SAndrew Boyer 
876c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
877c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
878c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
879c5d15850SAndrew Boyer 		if (err == -EINVAL) {
880c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
881c5d15850SAndrew Boyer 			continue;
882c5d15850SAndrew Boyer 		} else if (err == -EIO) {
883c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
884c5d15850SAndrew Boyer 			return;
885c5d15850SAndrew Boyer 		} else if (err) {
886c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
887c5d15850SAndrew Boyer 				qtype, err);
888c5d15850SAndrew Boyer 			return;
889c5d15850SAndrew Boyer 		}
890c5d15850SAndrew Boyer 
891c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
892c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
893c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
894c5d15850SAndrew Boyer 
895c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
896c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
897c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
898c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
899c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
900c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
901c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
902c5d15850SAndrew Boyer 		qti->sg_desc_stride =
903c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
904c5d15850SAndrew Boyer 
905c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
906c5d15850SAndrew Boyer 			qtype, qti->version);
907c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
908c5d15850SAndrew Boyer 			qtype, qti->supported);
909c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
910c5d15850SAndrew Boyer 			qtype, qti->features);
911c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
912c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
913c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
914c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
915c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
916c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
917c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
918c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
919c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
920c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
921c5d15850SAndrew Boyer 	}
922c5d15850SAndrew Boyer }
923c5d15850SAndrew Boyer 
924669c8de6SAlfredo Cardigliano int
925669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
926669c8de6SAlfredo Cardigliano {
927c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
928669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
92901a6c311SAlfredo Cardigliano 	int err;
930669c8de6SAlfredo Cardigliano 
9314ae96cb8SAndrew Boyer 	/*
9324ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9334ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9344ae96cb8SAndrew Boyer 	 */
9354ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9364ae96cb8SAndrew Boyer 
9374ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
938669c8de6SAlfredo Cardigliano 
939c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
940c5d15850SAndrew Boyer 
94156117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
94256117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
94356117636SAndrew Boyer 		return -ENXIO;
94456117636SAndrew Boyer 	}
94556117636SAndrew Boyer 
946669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
947669c8de6SAlfredo Cardigliano 
94801a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
94901a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
95001a6c311SAlfredo Cardigliano 
95184cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
952c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
953c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
954c67719e1SAlfredo Cardigliano 		return -ENOMEM;
955c67719e1SAlfredo Cardigliano 	}
956c67719e1SAlfredo Cardigliano 
957a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
958a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
959a27d9013SAlfredo Cardigliano 
960a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
961a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
962a27d9013SAlfredo Cardigliano 		return -ENOMEM;
963a27d9013SAlfredo Cardigliano 	}
964a27d9013SAlfredo Cardigliano 
965a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
966a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
967a27d9013SAlfredo Cardigliano 
968a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
969a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
970a27d9013SAlfredo Cardigliano 		return -ENOMEM;
971a27d9013SAlfredo Cardigliano 	}
972a27d9013SAlfredo Cardigliano 
97327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
97427b942c8SAlfredo Cardigliano 
97527b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
97627b942c8SAlfredo Cardigliano 	if (err) {
97727b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
97827b942c8SAlfredo Cardigliano 		return err;
97927b942c8SAlfredo Cardigliano 	}
98027b942c8SAlfredo Cardigliano 
98127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
98227b942c8SAlfredo Cardigliano 
98301a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
98401a6c311SAlfredo Cardigliano 	if (err) {
98501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
98601a6c311SAlfredo Cardigliano 		return err;
98701a6c311SAlfredo Cardigliano 	}
98801a6c311SAlfredo Cardigliano 
98901a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
99001a6c311SAlfredo Cardigliano 
991924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
992669c8de6SAlfredo Cardigliano 
993669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
994669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
995669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
996669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
997669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
998669c8de6SAlfredo Cardigliano 		return -ENOMEM;
999669c8de6SAlfredo Cardigliano 	}
1000669c8de6SAlfredo Cardigliano 
1001669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1002669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1003669c8de6SAlfredo Cardigliano 
1004669c8de6SAlfredo Cardigliano 	return 0;
1005669c8de6SAlfredo Cardigliano }
1006669c8de6SAlfredo Cardigliano 
1007669c8de6SAlfredo Cardigliano void
1008669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1009669c8de6SAlfredo Cardigliano {
101027b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1011be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
101227b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
101327b942c8SAlfredo Cardigliano 	}
101427b942c8SAlfredo Cardigliano 
101501a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1016be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
101701a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
101801a6c311SAlfredo Cardigliano 	}
101901a6c311SAlfredo Cardigliano 
1020a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1021a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1022a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1023a27d9013SAlfredo Cardigliano 	}
1024a27d9013SAlfredo Cardigliano 
1025a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1026a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1027a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1028a27d9013SAlfredo Cardigliano 	}
1029a27d9013SAlfredo Cardigliano 
1030669c8de6SAlfredo Cardigliano 	if (lif->info) {
1031669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1032669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1033669c8de6SAlfredo Cardigliano 	}
1034669c8de6SAlfredo Cardigliano }
1035669c8de6SAlfredo Cardigliano 
1036175e4e7eSAndrew Boyer void
1037175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1038175e4e7eSAndrew Boyer {
1039175e4e7eSAndrew Boyer 	uint32_t i;
1040175e4e7eSAndrew Boyer 
1041175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
10427483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1043175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1044175e4e7eSAndrew Boyer 	}
1045175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
10467483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1047175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1048175e4e7eSAndrew Boyer 	}
1049175e4e7eSAndrew Boyer }
1050175e4e7eSAndrew Boyer 
105122e7171bSAlfredo Cardigliano int
105222e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
105322e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
105422e7171bSAlfredo Cardigliano {
105509f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
105622e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
105722e7171bSAlfredo Cardigliano 		.pending_work = true,
105822e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
105922e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
106022e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
106109f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
106209f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
106322e7171bSAlfredo Cardigliano 		},
106422e7171bSAlfredo Cardigliano 	};
106522e7171bSAlfredo Cardigliano 	unsigned int i;
106609f806e9SAndrew Boyer 	uint16_t tbl_sz =
106709f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
106822e7171bSAlfredo Cardigliano 
106922e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
107022e7171bSAlfredo Cardigliano 
107122e7171bSAlfredo Cardigliano 	lif->rss_types = types;
107222e7171bSAlfredo Cardigliano 
107322e7171bSAlfredo Cardigliano 	if (key)
107422e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
107522e7171bSAlfredo Cardigliano 
107622e7171bSAlfredo Cardigliano 	if (indir)
107709f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
107822e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
107922e7171bSAlfredo Cardigliano 
108022e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
108122e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
108222e7171bSAlfredo Cardigliano 
108322e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
108422e7171bSAlfredo Cardigliano }
108522e7171bSAlfredo Cardigliano 
108622e7171bSAlfredo Cardigliano static int
108722e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
108822e7171bSAlfredo Cardigliano {
108909f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
109022e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
109122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
109622e7171bSAlfredo Cardigliano 	};
109722e7171bSAlfredo Cardigliano 	uint32_t i;
109809f806e9SAndrew Boyer 	uint16_t tbl_sz =
109909f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
110022e7171bSAlfredo Cardigliano 
110122e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
110222e7171bSAlfredo Cardigliano 
11033d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
110422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11053d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11063d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11073d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
110822e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
110922e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
111022e7171bSAlfredo Cardigliano 			return -ENOMEM;
111122e7171bSAlfredo Cardigliano 		}
111222e7171bSAlfredo Cardigliano 
111322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
111422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11153d845eddSAndrew Boyer 	}
11163d845eddSAndrew Boyer 
11173d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11183d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
111922e7171bSAlfredo Cardigliano 
112022e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11213d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
112222e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11233d845eddSAndrew Boyer 	}
112422e7171bSAlfredo Cardigliano 
11253d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
112622e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
112722e7171bSAlfredo Cardigliano }
112822e7171bSAlfredo Cardigliano 
112922e7171bSAlfredo Cardigliano static void
113022e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
113122e7171bSAlfredo Cardigliano {
113222e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
113322e7171bSAlfredo Cardigliano 		return;
113422e7171bSAlfredo Cardigliano 
113522e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
113622e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
113722e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
113822e7171bSAlfredo Cardigliano 
113922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
114022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
114122e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
114222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
114322e7171bSAlfredo Cardigliano 	}
114422e7171bSAlfredo Cardigliano }
114522e7171bSAlfredo Cardigliano 
1146be39f75cSAndrew Boyer void
1147be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1148be39f75cSAndrew Boyer {
1149be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1150be39f75cSAndrew Boyer }
1151be39f75cSAndrew Boyer 
1152be39f75cSAndrew Boyer void
1153be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1154be39f75cSAndrew Boyer {
1155be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1156be39f75cSAndrew Boyer }
1157be39f75cSAndrew Boyer 
115801a6c311SAlfredo Cardigliano static void
1159be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
116001a6c311SAlfredo Cardigliano {
1161be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
11624c8f8d57SAndrew Boyer }
11634c8f8d57SAndrew Boyer 
11644c8f8d57SAndrew Boyer static void
11654c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
11664c8f8d57SAndrew Boyer {
1167be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
11684c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
11694c8f8d57SAndrew Boyer 
11704c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
11714c8f8d57SAndrew Boyer 		return;
11724c8f8d57SAndrew Boyer 
11734c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
11744c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
11754c8f8d57SAndrew Boyer 
11764c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1177a27d9013SAlfredo Cardigliano }
1178a27d9013SAlfredo Cardigliano 
117901a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
118001a6c311SAlfredo Cardigliano int
118101a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
118201a6c311SAlfredo Cardigliano 		void *cb_arg)
118301a6c311SAlfredo Cardigliano {
118401a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
118501a6c311SAlfredo Cardigliano 	uint32_t work_done;
118601a6c311SAlfredo Cardigliano 
118701a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
118801a6c311SAlfredo Cardigliano 
118901a6c311SAlfredo Cardigliano 	return work_done;
119001a6c311SAlfredo Cardigliano }
119101a6c311SAlfredo Cardigliano 
119227b942c8SAlfredo Cardigliano static void
119327b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
119427b942c8SAlfredo Cardigliano {
119527b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
119627b942c8SAlfredo Cardigliano 	bool link_up;
119727b942c8SAlfredo Cardigliano 
119827b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
119927b942c8SAlfredo Cardigliano 
120027b942c8SAlfredo Cardigliano 	if (!lif->info)
120127b942c8SAlfredo Cardigliano 		return;
120227b942c8SAlfredo Cardigliano 
120327b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
120427b942c8SAlfredo Cardigliano 
120527b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
120627b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
120727b942c8SAlfredo Cardigliano 		return;
120827b942c8SAlfredo Cardigliano 
120927b942c8SAlfredo Cardigliano 	if (link_up) {
121009f806e9SAndrew Boyer 		adapter->link_speed =
121109f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1212be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1213be63459eSAndrew Boyer 			adapter->link_speed);
121427b942c8SAlfredo Cardigliano 	} else {
121527b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
121627b942c8SAlfredo Cardigliano 	}
121727b942c8SAlfredo Cardigliano 
121827b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1219be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1220be63459eSAndrew Boyer }
1221be63459eSAndrew Boyer 
1222be63459eSAndrew Boyer static void
1223be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1224be63459eSAndrew Boyer {
1225be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1226be63459eSAndrew Boyer 		return;
1227be63459eSAndrew Boyer 
1228be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1229be63459eSAndrew Boyer 
1230be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1231be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1232be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1233be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1234be63459eSAndrew Boyer 	}
1235be63459eSAndrew Boyer 
1236be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
123727b942c8SAlfredo Cardigliano }
123827b942c8SAlfredo Cardigliano 
123927b942c8SAlfredo Cardigliano static bool
12404ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
124127b942c8SAlfredo Cardigliano {
124227b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
124327b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
124427b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
124527b942c8SAlfredo Cardigliano 
124627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
124727b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
124827b942c8SAlfredo Cardigliano 
124927b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
125027b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
125127b942c8SAlfredo Cardigliano 		return false;
125227b942c8SAlfredo Cardigliano 
125327b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
125427b942c8SAlfredo Cardigliano 
125527b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
125627b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
125727b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1258be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1259be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1260be63459eSAndrew Boyer 			lif->name,
126127b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
126227b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
126327b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
126427b942c8SAlfredo Cardigliano 
126527b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
126627b942c8SAlfredo Cardigliano 		break;
1267be63459eSAndrew Boyer 
1268be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1269be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1270be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1271be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1272be63459eSAndrew Boyer 			lif->name,
1273be63459eSAndrew Boyer 			cq_desc->event.eid,
1274be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1275be63459eSAndrew Boyer 			cq_desc->reset.state);
1276be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1277be63459eSAndrew Boyer 		break;
1278be63459eSAndrew Boyer 
127927b942c8SAlfredo Cardigliano 	default:
128027b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
128127b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
128227b942c8SAlfredo Cardigliano 		break;
128327b942c8SAlfredo Cardigliano 	}
128427b942c8SAlfredo Cardigliano 
128527b942c8SAlfredo Cardigliano 	return true;
128627b942c8SAlfredo Cardigliano }
128727b942c8SAlfredo Cardigliano 
128827b942c8SAlfredo Cardigliano int
128927b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
129027b942c8SAlfredo Cardigliano {
129127b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1292be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
129327b942c8SAlfredo Cardigliano 	uint32_t work_done;
129427b942c8SAlfredo Cardigliano 
1295be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
129627b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
129727b942c8SAlfredo Cardigliano 		return -1;
129827b942c8SAlfredo Cardigliano 	}
129927b942c8SAlfredo Cardigliano 
1300be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
130127b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
130227b942c8SAlfredo Cardigliano 
1303be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1304be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
130527b942c8SAlfredo Cardigliano 
130627b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
130727b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
130827b942c8SAlfredo Cardigliano 
1309be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
131027b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
131127b942c8SAlfredo Cardigliano 
1312be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
131327b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
131427b942c8SAlfredo Cardigliano 
131527b942c8SAlfredo Cardigliano 	return 0;
131627b942c8SAlfredo Cardigliano }
131727b942c8SAlfredo Cardigliano 
131801a6c311SAlfredo Cardigliano static int
131901a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
132001a6c311SAlfredo Cardigliano {
132101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1322be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1323be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
132401a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
132501a6c311SAlfredo Cardigliano 	int err;
132601a6c311SAlfredo Cardigliano 
1327be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
132801a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
132901a6c311SAlfredo Cardigliano 	if (err)
133001a6c311SAlfredo Cardigliano 		return err;
133101a6c311SAlfredo Cardigliano 
133201a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
133301a6c311SAlfredo Cardigliano 
133401a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
133509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
133601a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
133701a6c311SAlfredo Cardigliano 
133801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
133901a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
134001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
134101a6c311SAlfredo Cardigliano 
1342be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
134301a6c311SAlfredo Cardigliano 
134401a6c311SAlfredo Cardigliano 	return 0;
134501a6c311SAlfredo Cardigliano }
134601a6c311SAlfredo Cardigliano 
134727b942c8SAlfredo Cardigliano static int
134827b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
134927b942c8SAlfredo Cardigliano {
135027b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1351be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1352be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
1353*0a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
135427b942c8SAlfredo Cardigliano 	int err;
135527b942c8SAlfredo Cardigliano 
135627b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
135727b942c8SAlfredo Cardigliano 		.pending_work = true,
135827b942c8SAlfredo Cardigliano 		.cmd.q_init = {
135927b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
136027b942c8SAlfredo Cardigliano 			.type = q->type,
1361c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
136209f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1363*0a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
136427b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
136509f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
136627b942c8SAlfredo Cardigliano 		}
136727b942c8SAlfredo Cardigliano 	};
136827b942c8SAlfredo Cardigliano 
1369*0a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
1370*0a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
1371*0a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
1372*0a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
1373*0a00bdafSAndrew Boyer 	}
1374*0a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
1375*0a00bdafSAndrew Boyer 
137609f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
137709f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
137827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
137927b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13804ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
138127b942c8SAlfredo Cardigliano 
138227b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
138327b942c8SAlfredo Cardigliano 	if (err)
138427b942c8SAlfredo Cardigliano 		return err;
138527b942c8SAlfredo Cardigliano 
138627b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
138709f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
138827b942c8SAlfredo Cardigliano 	q->db = NULL;
138927b942c8SAlfredo Cardigliano 
139027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
139127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
139227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
139327b942c8SAlfredo Cardigliano 
1394be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
139527b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
139627b942c8SAlfredo Cardigliano 
1397be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
139827b942c8SAlfredo Cardigliano 
139927b942c8SAlfredo Cardigliano 	return 0;
140027b942c8SAlfredo Cardigliano }
140127b942c8SAlfredo Cardigliano 
1402669c8de6SAlfredo Cardigliano int
1403598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1404598f6726SAlfredo Cardigliano {
1405598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1406598f6726SAlfredo Cardigliano 		.pending_work = true,
1407598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1408598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1409598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
141009f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1411598f6726SAlfredo Cardigliano 		},
1412598f6726SAlfredo Cardigliano 	};
1413598f6726SAlfredo Cardigliano 	int err;
1414598f6726SAlfredo Cardigliano 
1415598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1416598f6726SAlfredo Cardigliano 	if (err)
1417598f6726SAlfredo Cardigliano 		return err;
1418598f6726SAlfredo Cardigliano 
141909f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1420598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1421598f6726SAlfredo Cardigliano 
1422598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1423598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1424598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1425598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1426598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1427598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1428598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1429598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1430598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1431598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1432598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1433598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1434598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1435598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1436598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1437598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1438598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1439598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1440598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1441598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1442598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1443598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1444598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1445598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1446598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1448598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1450598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1452598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1454598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1455598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1456598f6726SAlfredo Cardigliano 
1457598f6726SAlfredo Cardigliano 	return 0;
1458598f6726SAlfredo Cardigliano }
1459598f6726SAlfredo Cardigliano 
1460a27d9013SAlfredo Cardigliano int
1461be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1462a27d9013SAlfredo Cardigliano {
1463be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1464a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1465a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1466a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1467a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1468a27d9013SAlfredo Cardigliano 		.pending_work = true,
1469a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1470a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1471a27d9013SAlfredo Cardigliano 			.type = q->type,
1472c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
147309f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
147409f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
147509f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
147609f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1477a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
147809f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
147909f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
148009f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1481a27d9013SAlfredo Cardigliano 		},
1482a27d9013SAlfredo Cardigliano 	};
1483a27d9013SAlfredo Cardigliano 	int err;
1484a27d9013SAlfredo Cardigliano 
148509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
148609f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1487a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1488a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14894ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1490a27d9013SAlfredo Cardigliano 
1491be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1492a27d9013SAlfredo Cardigliano 	if (err)
1493a27d9013SAlfredo Cardigliano 		return err;
1494a27d9013SAlfredo Cardigliano 
1495a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
149609f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1497a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1498a27d9013SAlfredo Cardigliano 
1499a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1500a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1501a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1502a27d9013SAlfredo Cardigliano 
1503be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1504a27d9013SAlfredo Cardigliano 
1505a27d9013SAlfredo Cardigliano 	return 0;
1506a27d9013SAlfredo Cardigliano }
1507a27d9013SAlfredo Cardigliano 
1508a27d9013SAlfredo Cardigliano int
1509be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1510a27d9013SAlfredo Cardigliano {
1511be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1512a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1513a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1514a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1515a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1516a27d9013SAlfredo Cardigliano 		.pending_work = true,
1517a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1518a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1519a27d9013SAlfredo Cardigliano 			.type = q->type,
1520c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
152109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
152209f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
152309f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
152409f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1525a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
152609f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
152709f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
152809f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1529a27d9013SAlfredo Cardigliano 		},
1530a27d9013SAlfredo Cardigliano 	};
1531a27d9013SAlfredo Cardigliano 	int err;
1532a27d9013SAlfredo Cardigliano 
153309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
153409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1535a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1536a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15374ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1538a27d9013SAlfredo Cardigliano 
1539be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1540a27d9013SAlfredo Cardigliano 	if (err)
1541a27d9013SAlfredo Cardigliano 		return err;
1542a27d9013SAlfredo Cardigliano 
1543a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
154409f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1545a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1546a27d9013SAlfredo Cardigliano 
1547be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1548a27d9013SAlfredo Cardigliano 
1549a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1550a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1551a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1552a27d9013SAlfredo Cardigliano 
1553a27d9013SAlfredo Cardigliano 	return 0;
1554a27d9013SAlfredo Cardigliano }
1555a27d9013SAlfredo Cardigliano 
1556598f6726SAlfredo Cardigliano static int
1557598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1558598f6726SAlfredo Cardigliano {
1559598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1560598f6726SAlfredo Cardigliano 		.pending_work = true,
1561598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1562598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1563598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1564598f6726SAlfredo Cardigliano 		},
1565598f6726SAlfredo Cardigliano 	};
1566598f6726SAlfredo Cardigliano 	int err;
1567598f6726SAlfredo Cardigliano 
1568598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1569598f6726SAlfredo Cardigliano 
1570598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1571598f6726SAlfredo Cardigliano 	if (err)
1572598f6726SAlfredo Cardigliano 		return err;
1573598f6726SAlfredo Cardigliano 
1574598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1575598f6726SAlfredo Cardigliano 
1576598f6726SAlfredo Cardigliano 	return 0;
1577598f6726SAlfredo Cardigliano }
1578598f6726SAlfredo Cardigliano 
1579598f6726SAlfredo Cardigliano static void
1580598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1581598f6726SAlfredo Cardigliano {
1582598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1583598f6726SAlfredo Cardigliano 		.pending_work = true,
1584598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1585598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1586598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1587598f6726SAlfredo Cardigliano 		},
1588598f6726SAlfredo Cardigliano 	};
1589598f6726SAlfredo Cardigliano 
15904ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
15914ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1592598f6726SAlfredo Cardigliano 
1593598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1594598f6726SAlfredo Cardigliano }
1595598f6726SAlfredo Cardigliano 
1596598f6726SAlfredo Cardigliano int
1597669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1598669c8de6SAlfredo Cardigliano {
1599669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1600656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
1601669c8de6SAlfredo Cardigliano 	int err;
1602669c8de6SAlfredo Cardigliano 
16033cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
16043cdfd905SAlfredo Cardigliano 
160500b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1606669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1607669c8de6SAlfredo Cardigliano 	if (err)
1608669c8de6SAlfredo Cardigliano 		return err;
1609669c8de6SAlfredo Cardigliano 
1610656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1611656bfc9aSAndrew Boyer 
161209f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1613669c8de6SAlfredo Cardigliano 
161401a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
161501a6c311SAlfredo Cardigliano 	if (err)
161601a6c311SAlfredo Cardigliano 		return err;
161701a6c311SAlfredo Cardigliano 
161827b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
161927b942c8SAlfredo Cardigliano 	if (err)
162027b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
162127b942c8SAlfredo Cardigliano 
162218a44465SAndrew Boyer 	/*
162318a44465SAndrew Boyer 	 * Configure initial feature set
162418a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
162518a44465SAndrew Boyer 	 */
162618a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1627598f6726SAlfredo Cardigliano 
1628598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1629598f6726SAlfredo Cardigliano 	if (err)
1630598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1631598f6726SAlfredo Cardigliano 
163254fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1633598f6726SAlfredo Cardigliano 	if (err)
1634598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1635598f6726SAlfredo Cardigliano 
163654fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
163754fe083fSAlfredo Cardigliano 	if (err)
163854fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
163954fe083fSAlfredo Cardigliano 
1640598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1641598f6726SAlfredo Cardigliano 
1642669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1643669c8de6SAlfredo Cardigliano 
1644669c8de6SAlfredo Cardigliano 	return 0;
164527b942c8SAlfredo Cardigliano 
164654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
164754fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
164854fe083fSAlfredo Cardigliano 
1649598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
16504c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1651598f6726SAlfredo Cardigliano 
165227b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1653be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
165427b942c8SAlfredo Cardigliano 
165527b942c8SAlfredo Cardigliano 	return err;
1656669c8de6SAlfredo Cardigliano }
1657669c8de6SAlfredo Cardigliano 
1658669c8de6SAlfredo Cardigliano void
1659669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1660669c8de6SAlfredo Cardigliano {
1661669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1662669c8de6SAlfredo Cardigliano 		return;
1663669c8de6SAlfredo Cardigliano 
166454fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
166522e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
16664c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1667be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
166801a6c311SAlfredo Cardigliano 
1669669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1670669c8de6SAlfredo Cardigliano }
1671669c8de6SAlfredo Cardigliano 
167218a44465SAndrew Boyer void
167318a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
167418a44465SAndrew Boyer {
167518a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
167618a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
167718a44465SAndrew Boyer 
167818a44465SAndrew Boyer 	/*
167918a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1680295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
168118a44465SAndrew Boyer 	 */
1682295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
168318a44465SAndrew Boyer 
1684295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1685295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
168618a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
168718a44465SAndrew Boyer 		else
168818a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
168918a44465SAndrew Boyer 	}
169018a44465SAndrew Boyer }
169118a44465SAndrew Boyer 
169218a44465SAndrew Boyer void
1693598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1694598f6726SAlfredo Cardigliano {
169518a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
169618a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
169722e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
169809f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
169922e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
170009f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
170122e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
170209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
170322e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
170422e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
170522e7171bSAlfredo Cardigliano 
1706598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1707598f6726SAlfredo Cardigliano 
170822e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
170922e7171bSAlfredo Cardigliano 		lif->port_id);
171022e7171bSAlfredo Cardigliano 
171122e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
171222e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
171322e7171bSAlfredo Cardigliano 
171422e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
171522e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
171622e7171bSAlfredo Cardigliano 
171722e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
171822e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1719a27d9013SAlfredo Cardigliano 
172018a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
172118a44465SAndrew Boyer 
172218a44465SAndrew Boyer 	/*
172318a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
172418a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1725295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
172618a44465SAndrew Boyer 	 */
172718a44465SAndrew Boyer 
172818a44465SAndrew Boyer 	/* RX per-port */
172918a44465SAndrew Boyer 
1730295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1731295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1732295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
173318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
173418a44465SAndrew Boyer 	else
173518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
173618a44465SAndrew Boyer 
1737295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
173818a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
173918a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
174018a44465SAndrew Boyer 	} else {
174118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
174218a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
174318a44465SAndrew Boyer 	}
174418a44465SAndrew Boyer 
174518a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1746295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
174718a44465SAndrew Boyer 
174818a44465SAndrew Boyer 	/* TX per-port */
174918a44465SAndrew Boyer 
1750295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1751295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1752295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1753295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1754295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
175518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
175618a44465SAndrew Boyer 	else
175718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
175818a44465SAndrew Boyer 
1759295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
176018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
176118a44465SAndrew Boyer 	else
176218a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
176318a44465SAndrew Boyer 
1764295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
176518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
176618a44465SAndrew Boyer 	else
176718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
176818a44465SAndrew Boyer 
1769295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
177018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
177118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
177218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
177318a44465SAndrew Boyer 	} else {
177418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
177518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
177618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
177718a44465SAndrew Boyer 	}
1778598f6726SAlfredo Cardigliano }
1779598f6726SAlfredo Cardigliano 
1780598f6726SAlfredo Cardigliano int
1781598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1782598f6726SAlfredo Cardigliano {
17830578335aSAndrew Boyer 	uint32_t rx_mode;
1784a27d9013SAlfredo Cardigliano 	uint32_t i;
1785a27d9013SAlfredo Cardigliano 	int err;
1786598f6726SAlfredo Cardigliano 
178722e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
178822e7171bSAlfredo Cardigliano 	if (err)
178922e7171bSAlfredo Cardigliano 		return err;
179022e7171bSAlfredo Cardigliano 
17910578335aSAndrew Boyer 	if (!lif->rx_mode) {
17920578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
17930578335aSAndrew Boyer 			lif->name);
1794598f6726SAlfredo Cardigliano 
17950578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1796598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1797598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1798598f6726SAlfredo Cardigliano 
1799598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18000578335aSAndrew Boyer 	}
1801598f6726SAlfredo Cardigliano 
1802a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1803a27d9013SAlfredo Cardigliano 		"on port %u",
1804a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1805a27d9013SAlfredo Cardigliano 
1806a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1807be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
180802eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1809a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1810a27d9013SAlfredo Cardigliano 
1811a27d9013SAlfredo Cardigliano 			if (err)
1812a27d9013SAlfredo Cardigliano 				return err;
1813a27d9013SAlfredo Cardigliano 		}
1814a27d9013SAlfredo Cardigliano 	}
1815a27d9013SAlfredo Cardigliano 
1816a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1817be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
181802eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1819a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1820a27d9013SAlfredo Cardigliano 
1821a27d9013SAlfredo Cardigliano 			if (err)
1822a27d9013SAlfredo Cardigliano 				return err;
1823a27d9013SAlfredo Cardigliano 		}
1824a27d9013SAlfredo Cardigliano 	}
1825a27d9013SAlfredo Cardigliano 
1826598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1827be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1828be63459eSAndrew Boyer 
1829be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1830598f6726SAlfredo Cardigliano 
1831598f6726SAlfredo Cardigliano 	return 0;
1832598f6726SAlfredo Cardigliano }
1833598f6726SAlfredo Cardigliano 
1834598f6726SAlfredo Cardigliano int
1835669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1836669c8de6SAlfredo Cardigliano {
1837669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1838669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
183909f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
184076276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
184176276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
184276276d71SAndrew Boyer 	uint32_t i, nwords;
1843669c8de6SAlfredo Cardigliano 	int err;
1844669c8de6SAlfredo Cardigliano 
1845669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1846669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1847669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1848669c8de6SAlfredo Cardigliano 	if (err)
1849669c8de6SAlfredo Cardigliano 		return (err);
1850669c8de6SAlfredo Cardigliano 
1851669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1852669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1853669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1854669c8de6SAlfredo Cardigliano 
1855669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
185609f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1857669c8de6SAlfredo Cardigliano 
1858669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
185909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1860669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
186109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1862669c8de6SAlfredo Cardigliano 
1863669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
186409f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1865669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
186609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1867669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
186809f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1869669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
187009f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1871669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
187209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1873669c8de6SAlfredo Cardigliano 
1874669c8de6SAlfredo Cardigliano 	return 0;
1875669c8de6SAlfredo Cardigliano }
1876669c8de6SAlfredo Cardigliano 
1877669c8de6SAlfredo Cardigliano int
1878669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1879669c8de6SAlfredo Cardigliano {
1880669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
188109f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
188209f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1883669c8de6SAlfredo Cardigliano 
1884669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
188509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1886669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
188709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1888669c8de6SAlfredo Cardigliano 
188900b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1890669c8de6SAlfredo Cardigliano 
1891669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
18924ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
18934ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1894669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1895669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1896669c8de6SAlfredo Cardigliano 	}
1897669c8de6SAlfredo Cardigliano 
1898669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1899669c8de6SAlfredo Cardigliano 
1900669c8de6SAlfredo Cardigliano 	return 0;
1901669c8de6SAlfredo Cardigliano }
1902