xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 0033e92f4697add2772a6e459dcb55a1962ee80c)
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 
33e7222f94SAndrew Boyer static int
347bb08900SAndrew Boyer ionic_qcq_disable_nowait(struct ionic_qcq *qcq,
357bb08900SAndrew Boyer 		struct ionic_admin_ctx *ctx)
3601a6c311SAlfredo Cardigliano {
377bb08900SAndrew Boyer 	int err;
387bb08900SAndrew Boyer 
3901a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
404ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
417bb08900SAndrew Boyer 
427bb08900SAndrew Boyer 	*ctx = (struct ionic_admin_ctx) {
4301a6c311SAlfredo Cardigliano 		.pending_work = true,
4401a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4501a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4601a6c311SAlfredo Cardigliano 			.type = q->type,
4709f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4801a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
4901a6c311SAlfredo Cardigliano 		},
5001a6c311SAlfredo Cardigliano 	};
5101a6c311SAlfredo Cardigliano 
527bb08900SAndrew Boyer 	/* Does not wait for command completion */
537bb08900SAndrew Boyer 	err = ionic_adminq_post(lif, ctx);
547bb08900SAndrew Boyer 	if (err)
557bb08900SAndrew Boyer 		ctx->pending_work = false;
567bb08900SAndrew Boyer 	return err;
5701a6c311SAlfredo Cardigliano }
5801a6c311SAlfredo Cardigliano 
59be63459eSAndrew Boyer void
60be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
61598f6726SAlfredo Cardigliano {
627bb08900SAndrew Boyer 	struct rte_eth_dev *dev = lif->eth_dev;
637bb08900SAndrew Boyer 	uint32_t i, j, chunk;
64a0a99f21SAndrew Boyer 
65be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
66598f6726SAlfredo Cardigliano 
67be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
68a0a99f21SAndrew Boyer 
697bb08900SAndrew Boyer 	chunk = ionic_adminq_space_avail(lif);
707bb08900SAndrew Boyer 
717bb08900SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i += chunk) {
727bb08900SAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++)
737bb08900SAndrew Boyer 			ionic_dev_rx_queue_stop_firsthalf(dev, i + j);
747bb08900SAndrew Boyer 
757bb08900SAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++)
767bb08900SAndrew Boyer 			ionic_dev_rx_queue_stop_secondhalf(dev, i + j);
77a0a99f21SAndrew Boyer 	}
78a0a99f21SAndrew Boyer 
797bb08900SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i += chunk) {
807bb08900SAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++)
817bb08900SAndrew Boyer 			ionic_dev_tx_queue_stop_firsthalf(dev, i + j);
827bb08900SAndrew Boyer 
837bb08900SAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++)
847bb08900SAndrew Boyer 			ionic_dev_tx_queue_stop_secondhalf(dev, i + j);
85a0a99f21SAndrew Boyer 	}
86598f6726SAlfredo Cardigliano }
87598f6726SAlfredo Cardigliano 
88598f6726SAlfredo Cardigliano void
89598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
90598f6726SAlfredo Cardigliano {
91598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
9275f96902SAndrew Boyer 	int err;
93598f6726SAlfredo Cardigliano 
94598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
95598f6726SAlfredo Cardigliano 
9600b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
9775f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
9875f96902SAndrew Boyer 	if (err)
994ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
100598f6726SAlfredo Cardigliano }
101598f6726SAlfredo Cardigliano 
1023cdfd905SAlfredo Cardigliano static void
1033cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
1043cdfd905SAlfredo Cardigliano {
1053cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
1063cdfd905SAlfredo Cardigliano 	uint32_t i;
1073cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
1083cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1093cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
1103cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1113cdfd905SAlfredo Cardigliano 
1123cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1133cdfd905SAlfredo Cardigliano 
1143cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1153cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1163cdfd905SAlfredo Cardigliano 			lif->port_id);
1173cdfd905SAlfredo Cardigliano 		return;
1183cdfd905SAlfredo Cardigliano 	}
1193cdfd905SAlfredo Cardigliano 
1203cdfd905SAlfredo Cardigliano 	/* RX */
1213cdfd905SAlfredo Cardigliano 
1223cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1233cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1243cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1253cdfd905SAlfredo Cardigliano 
1263cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1273cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1283cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1293cdfd905SAlfredo Cardigliano 
1303cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
131be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
13226cc5dc2SAndrew Boyer 		stats->ierrors +=
1333cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1343cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1353cdfd905SAlfredo Cardigliano 	}
1363cdfd905SAlfredo Cardigliano 
1373cdfd905SAlfredo Cardigliano 	stats->imissed +=
1383cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1393cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1403cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1413cdfd905SAlfredo Cardigliano 
14226cc5dc2SAndrew Boyer 	stats->ierrors +=
1433cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1443cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1453cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1463cdfd905SAlfredo Cardigliano 
1473cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
148be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1493cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1503cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1513cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1523cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1533cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1543cdfd905SAlfredo Cardigliano 	}
1553cdfd905SAlfredo Cardigliano 
1563cdfd905SAlfredo Cardigliano 	/* TX */
1573cdfd905SAlfredo Cardigliano 
1583cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1593cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1603cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1613cdfd905SAlfredo Cardigliano 
1623cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1633cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1643cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1653cdfd905SAlfredo Cardigliano 
1663cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
167be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1683cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1693cdfd905SAlfredo Cardigliano 	}
1703cdfd905SAlfredo Cardigliano 
1713cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1723cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1733cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1743cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1753cdfd905SAlfredo Cardigliano 
1763cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1773cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1783cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1793cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1803cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1813cdfd905SAlfredo Cardigliano 
1823cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
183be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1843cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1853cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1863cdfd905SAlfredo Cardigliano 	}
1873cdfd905SAlfredo Cardigliano }
1883cdfd905SAlfredo Cardigliano 
1893cdfd905SAlfredo Cardigliano void
1903cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1913cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1923cdfd905SAlfredo Cardigliano {
1933cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1943cdfd905SAlfredo Cardigliano 
1953cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1963cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1973cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1983cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1993cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
2003cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
2013cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
2023cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
2033cdfd905SAlfredo Cardigliano }
2043cdfd905SAlfredo Cardigliano 
2053cdfd905SAlfredo Cardigliano void
2063cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2073cdfd905SAlfredo Cardigliano {
2083cdfd905SAlfredo Cardigliano 	uint32_t i;
2093cdfd905SAlfredo Cardigliano 
2103cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
211be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
2123cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
213be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
2143cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2153cdfd905SAlfredo Cardigliano 	}
2163cdfd905SAlfredo Cardigliano 
2173cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2183cdfd905SAlfredo Cardigliano }
2193cdfd905SAlfredo Cardigliano 
2203cdfd905SAlfredo Cardigliano void
2213cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2223cdfd905SAlfredo Cardigliano {
2233cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2243cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2253cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2263cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2273cdfd905SAlfredo Cardigliano 
2283cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2293cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2303cdfd905SAlfredo Cardigliano }
2313cdfd905SAlfredo Cardigliano 
2323cdfd905SAlfredo Cardigliano void
2333cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2343cdfd905SAlfredo Cardigliano {
2353cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2363cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2373cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2383cdfd905SAlfredo Cardigliano 
2393cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2403cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2413cdfd905SAlfredo Cardigliano }
2423cdfd905SAlfredo Cardigliano 
243598f6726SAlfredo Cardigliano static int
24454fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
245598f6726SAlfredo Cardigliano {
24654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
24754fe083fSAlfredo Cardigliano 		.pending_work = true,
24854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
24954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
25009f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
25154fe083fSAlfredo Cardigliano 		},
25254fe083fSAlfredo Cardigliano 	};
25354fe083fSAlfredo Cardigliano 	int err;
25454fe083fSAlfredo Cardigliano 
25554fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
25654fe083fSAlfredo Cardigliano 
25754fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
25854fe083fSAlfredo Cardigliano 	if (err)
25954fe083fSAlfredo Cardigliano 		return err;
26054fe083fSAlfredo Cardigliano 
26154fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
26209f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
26554fe083fSAlfredo Cardigliano }
26654fe083fSAlfredo Cardigliano 
26754fe083fSAlfredo Cardigliano static int
26854fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
26954fe083fSAlfredo Cardigliano {
27054fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
27154fe083fSAlfredo Cardigliano 		.pending_work = true,
27254fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
27354fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
27454fe083fSAlfredo Cardigliano 		},
27554fe083fSAlfredo Cardigliano 	};
27654fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
27754fe083fSAlfredo Cardigliano 	int err;
27854fe083fSAlfredo Cardigliano 
27954fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
28054fe083fSAlfredo Cardigliano 
28154fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
28254fe083fSAlfredo Cardigliano 
28354fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
28454fe083fSAlfredo Cardigliano 	if (!f) {
28554fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
28654fe083fSAlfredo Cardigliano 		return -ENOENT;
28754fe083fSAlfredo Cardigliano 	}
28854fe083fSAlfredo Cardigliano 
28909f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
29054fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
29154fe083fSAlfredo Cardigliano 
29254fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
29354fe083fSAlfredo Cardigliano 
29454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
29554fe083fSAlfredo Cardigliano 	if (err)
29654fe083fSAlfredo Cardigliano 		return err;
29754fe083fSAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
29909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
300598f6726SAlfredo Cardigliano 
301598f6726SAlfredo Cardigliano 	return 0;
302598f6726SAlfredo Cardigliano }
303598f6726SAlfredo Cardigliano 
30454fe083fSAlfredo Cardigliano int
30554fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
30654fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
30754fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
308598f6726SAlfredo Cardigliano {
30954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31054fe083fSAlfredo Cardigliano 
31154fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31254fe083fSAlfredo Cardigliano 
31354fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
31454fe083fSAlfredo Cardigliano }
31554fe083fSAlfredo Cardigliano 
31654fe083fSAlfredo Cardigliano void
31775f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
31854fe083fSAlfredo Cardigliano {
31954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32054fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
32175f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
32254fe083fSAlfredo Cardigliano 
32354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
32454fe083fSAlfredo Cardigliano 
32554fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
32654fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
32754fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
32854fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
32954fe083fSAlfredo Cardigliano 		return;
33054fe083fSAlfredo Cardigliano 	}
33154fe083fSAlfredo Cardigliano 
33275f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
33375f96902SAndrew Boyer 
33475f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
33554fe083fSAlfredo Cardigliano 		return;
33654fe083fSAlfredo Cardigliano 
33775f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
33854fe083fSAlfredo Cardigliano }
33954fe083fSAlfredo Cardigliano 
34054fe083fSAlfredo Cardigliano int
34154fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
34254fe083fSAlfredo Cardigliano {
34354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
34454fe083fSAlfredo Cardigliano 
34554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
34654fe083fSAlfredo Cardigliano 
34754fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
34854fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
34954fe083fSAlfredo Cardigliano 		return -1;
35054fe083fSAlfredo Cardigliano 	}
35154fe083fSAlfredo Cardigliano 
35254fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
35354fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
35454fe083fSAlfredo Cardigliano 			lif->mac_addr);
35554fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
35654fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
35754fe083fSAlfredo Cardigliano 	}
35854fe083fSAlfredo Cardigliano 
35954fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
36054fe083fSAlfredo Cardigliano 
36154fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
36254fe083fSAlfredo Cardigliano 
36354fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
36454fe083fSAlfredo Cardigliano }
36554fe083fSAlfredo Cardigliano 
36654fe083fSAlfredo Cardigliano static int
36754fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
36854fe083fSAlfredo Cardigliano {
36954fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37054fe083fSAlfredo Cardigliano 		.pending_work = true,
37154fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
37254fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
37309f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
37409f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
37554fe083fSAlfredo Cardigliano 		},
37654fe083fSAlfredo Cardigliano 	};
37754fe083fSAlfredo Cardigliano 	int err;
37854fe083fSAlfredo Cardigliano 
37954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
38054fe083fSAlfredo Cardigliano 	if (err)
38154fe083fSAlfredo Cardigliano 		return err;
38254fe083fSAlfredo Cardigliano 
38354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
38409f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
38554fe083fSAlfredo Cardigliano 
38654fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
38754fe083fSAlfredo Cardigliano }
38854fe083fSAlfredo Cardigliano 
38954fe083fSAlfredo Cardigliano static int
39054fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
39154fe083fSAlfredo Cardigliano {
39254fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
39354fe083fSAlfredo Cardigliano 		.pending_work = true,
39454fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
39554fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
39654fe083fSAlfredo Cardigliano 		},
39754fe083fSAlfredo Cardigliano 	};
39854fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
39954fe083fSAlfredo Cardigliano 	int err;
40054fe083fSAlfredo Cardigliano 
40154fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
40254fe083fSAlfredo Cardigliano 
40354fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
40454fe083fSAlfredo Cardigliano 
40554fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
40654fe083fSAlfredo Cardigliano 	if (!f) {
40754fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
40854fe083fSAlfredo Cardigliano 		return -ENOENT;
40954fe083fSAlfredo Cardigliano 	}
41054fe083fSAlfredo Cardigliano 
41109f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
41254fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
41354fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
41454fe083fSAlfredo Cardigliano 
41554fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
41654fe083fSAlfredo Cardigliano 	if (err)
41754fe083fSAlfredo Cardigliano 		return err;
41854fe083fSAlfredo Cardigliano 
41954fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
42009f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
421598f6726SAlfredo Cardigliano 
422598f6726SAlfredo Cardigliano 	return 0;
423598f6726SAlfredo Cardigliano }
424598f6726SAlfredo Cardigliano 
42554fe083fSAlfredo Cardigliano int
42654fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
42754fe083fSAlfredo Cardigliano 		int on)
42854fe083fSAlfredo Cardigliano {
42954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
43054fe083fSAlfredo Cardigliano 	int err;
43154fe083fSAlfredo Cardigliano 
43254fe083fSAlfredo Cardigliano 	if (on)
43354fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
43454fe083fSAlfredo Cardigliano 	else
43554fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
43654fe083fSAlfredo Cardigliano 
43754fe083fSAlfredo Cardigliano 	return err;
43854fe083fSAlfredo Cardigliano }
43954fe083fSAlfredo Cardigliano 
440598f6726SAlfredo Cardigliano static void
441598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
442598f6726SAlfredo Cardigliano {
443598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
444598f6726SAlfredo Cardigliano 		.pending_work = true,
445598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
446598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
44709f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
448598f6726SAlfredo Cardigliano 		},
449598f6726SAlfredo Cardigliano 	};
450598f6726SAlfredo Cardigliano 	int err;
451598f6726SAlfredo Cardigliano 
452598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
454598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
455598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
456598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
457598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
458598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
459598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
460598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
461598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
462598f6726SAlfredo Cardigliano 
463598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
464598f6726SAlfredo Cardigliano 	if (err)
465598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
466598f6726SAlfredo Cardigliano }
467598f6726SAlfredo Cardigliano 
468598f6726SAlfredo Cardigliano static void
469598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
470598f6726SAlfredo Cardigliano {
471598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
472598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
473598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
474598f6726SAlfredo Cardigliano 	}
475598f6726SAlfredo Cardigliano }
476598f6726SAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano int
47854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
47954fe083fSAlfredo Cardigliano {
48054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48254fe083fSAlfredo Cardigliano 
48354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
48454fe083fSAlfredo Cardigliano 
48554fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
48654fe083fSAlfredo Cardigliano 
48754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48854fe083fSAlfredo Cardigliano 
48954fe083fSAlfredo Cardigliano 	return 0;
49054fe083fSAlfredo Cardigliano }
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano int
49354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
49454fe083fSAlfredo Cardigliano {
49554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
49954fe083fSAlfredo Cardigliano 
50054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50154fe083fSAlfredo Cardigliano 
50254fe083fSAlfredo Cardigliano 	return 0;
50354fe083fSAlfredo Cardigliano }
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano int
50654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
50754fe083fSAlfredo Cardigliano {
50854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50954fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
51254fe083fSAlfredo Cardigliano 
51354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51454fe083fSAlfredo Cardigliano 
51554fe083fSAlfredo Cardigliano 	return 0;
51654fe083fSAlfredo Cardigliano }
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano int
51954fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
52054fe083fSAlfredo Cardigliano {
52154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
52254fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
52354fe083fSAlfredo Cardigliano 
52454fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
52554fe083fSAlfredo Cardigliano 
52654fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52754fe083fSAlfredo Cardigliano 
52854fe083fSAlfredo Cardigliano 	return 0;
52954fe083fSAlfredo Cardigliano }
530598f6726SAlfredo Cardigliano 
531598f6726SAlfredo Cardigliano int
532b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
533598f6726SAlfredo Cardigliano {
534598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
535598f6726SAlfredo Cardigliano 		.pending_work = true,
536598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
537598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
538598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
53909f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
540598f6726SAlfredo Cardigliano 		},
541598f6726SAlfredo Cardigliano 	};
542598f6726SAlfredo Cardigliano 
543b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
544598f6726SAlfredo Cardigliano }
545598f6726SAlfredo Cardigliano 
546598f6726SAlfredo Cardigliano int
54701a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
54801a6c311SAlfredo Cardigliano {
54901a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
55001a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
55101a6c311SAlfredo Cardigliano 	unsigned long index;
55201a6c311SAlfredo Cardigliano 
55301a6c311SAlfredo Cardigliano 	/*
55401a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55501a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5564ae96cb8SAndrew Boyer 	 * which has index = 0)
55701a6c311SAlfredo Cardigliano 	 */
55801a6c311SAlfredo Cardigliano 
55901a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
56001a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
56101a6c311SAlfredo Cardigliano 			break;
56201a6c311SAlfredo Cardigliano 
56301a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56401a6c311SAlfredo Cardigliano 		return -ENOSPC;
56501a6c311SAlfredo Cardigliano 
56601a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
56701a6c311SAlfredo Cardigliano 
56801a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
56901a6c311SAlfredo Cardigliano 
57001a6c311SAlfredo Cardigliano 	return 0;
57101a6c311SAlfredo Cardigliano }
57201a6c311SAlfredo Cardigliano 
57301a6c311SAlfredo Cardigliano static int
5744ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5754ad56b7aSAndrew Boyer 		uint8_t type,
576be39f75cSAndrew Boyer 		size_t struct_size,
5778ec5ad7fSAndrew Boyer 		uint32_t socket_id,
57801a6c311SAlfredo Cardigliano 		uint32_t index,
5794ad56b7aSAndrew Boyer 		const char *type_name,
5804ad56b7aSAndrew Boyer 		uint16_t flags,
5814ad56b7aSAndrew Boyer 		uint16_t num_descs,
582d5850081SAndrew Boyer 		uint16_t num_segs,
5834ad56b7aSAndrew Boyer 		uint16_t desc_size,
5844ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5854ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5861abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
58701a6c311SAlfredo Cardigliano {
58801a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
58901a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59090fa040aSNeel Patel 	void *q_base, *cmb_q_base, *cq_base, *sg_base;
59101a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59201a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59301a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59490fa040aSNeel Patel 	rte_iova_t cmb_q_base_pa = 0;
59515770e98SAndrew Boyer 	size_t page_size = rte_mem_page_size();
59601a6c311SAlfredo Cardigliano 	int err;
59701a6c311SAlfredo Cardigliano 
59801a6c311SAlfredo Cardigliano 	*qcq = NULL;
59901a6c311SAlfredo Cardigliano 
60001a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60101a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60201a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60301a6c311SAlfredo Cardigliano 
60415770e98SAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
60515770e98SAndrew Boyer 			RTE_ALIGN(cq_size, page_size);
60601a6c311SAlfredo Cardigliano 	/*
60701a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
60801a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
60915770e98SAndrew Boyer 	 * Adding page_size.
61001a6c311SAlfredo Cardigliano 	 */
61115770e98SAndrew Boyer 	total_size += page_size;
61201a6c311SAlfredo Cardigliano 
61301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61415770e98SAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size);
61515770e98SAndrew Boyer 		total_size += page_size;
61601a6c311SAlfredo Cardigliano 	}
61701a6c311SAlfredo Cardigliano 
618c5d0bb79SAndrew Boyer 	new = rte_zmalloc_socket("ionic", struct_size,
619c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
62001a6c311SAlfredo Cardigliano 	if (!new) {
62101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62201a6c311SAlfredo Cardigliano 		return -ENOMEM;
62301a6c311SAlfredo Cardigliano 	}
62401a6c311SAlfredo Cardigliano 
62501a6c311SAlfredo Cardigliano 	new->lif = lif;
62601a6c311SAlfredo Cardigliano 
6277b20fc2fSAndrew Boyer 	/* Most queue types will store 1 ptr per descriptor */
628be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
6294b53e980SAndrew Boyer 				(uint64_t)num_descs * num_segs,
6304b53e980SAndrew Boyer 				sizeof(void *), page_size, socket_id);
63101a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6334c8f8d57SAndrew Boyer 		err = -ENOMEM;
6344c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
63501a6c311SAlfredo Cardigliano 	}
63601a6c311SAlfredo Cardigliano 
637d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
63801a6c311SAlfredo Cardigliano 	new->q.type = type;
63901a6c311SAlfredo Cardigliano 
6404ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64101a6c311SAlfredo Cardigliano 	if (err) {
64201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6434c8f8d57SAndrew Boyer 		goto err_out_free_info;
64401a6c311SAlfredo Cardigliano 	}
64501a6c311SAlfredo Cardigliano 
6462aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
64701a6c311SAlfredo Cardigliano 	if (err) {
64801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6494c8f8d57SAndrew Boyer 		goto err_out_free_info;
65001a6c311SAlfredo Cardigliano 	}
65101a6c311SAlfredo Cardigliano 
65201a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6534ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
65401a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
65501a6c311SAlfredo Cardigliano 
65601a6c311SAlfredo Cardigliano 	if (!new->base_z) {
65701a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
65801a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6594c8f8d57SAndrew Boyer 		goto err_out_free_info;
66001a6c311SAlfredo Cardigliano 	}
66101a6c311SAlfredo Cardigliano 
66201a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66301a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
66401a6c311SAlfredo Cardigliano 
66501a6c311SAlfredo Cardigliano 	q_base = new->base;
66601a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
66701a6c311SAlfredo Cardigliano 
66815770e98SAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
66915770e98SAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
67001a6c311SAlfredo Cardigliano 
67101a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
67201a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
67315770e98SAndrew Boyer 				page_size);
67415770e98SAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
67501a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
67601a6c311SAlfredo Cardigliano 	}
67701a6c311SAlfredo Cardigliano 
6789de21005SAndrew Boyer 	if (flags & IONIC_QCQ_F_CMB) {
6799de21005SAndrew Boyer 		/* alloc descriptor ring from nic memory */
6809de21005SAndrew Boyer 		if (lif->adapter->cmb_offset + q_size >
6819de21005SAndrew Boyer 				lif->adapter->bars.bar[2].len) {
6829de21005SAndrew Boyer 			IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem");
6839de21005SAndrew Boyer 			return -ENOMEM;
6849de21005SAndrew Boyer 		}
68590fa040aSNeel Patel 		cmb_q_base = (void *)
6869de21005SAndrew Boyer 			((uintptr_t)lif->adapter->bars.bar[2].vaddr +
6879de21005SAndrew Boyer 			 (uintptr_t)lif->adapter->cmb_offset);
6889de21005SAndrew Boyer 		/* CMB PA is a relative address */
68990fa040aSNeel Patel 		cmb_q_base_pa = lif->adapter->cmb_offset;
6909de21005SAndrew Boyer 		lif->adapter->cmb_offset += q_size;
69190fa040aSNeel Patel 	} else {
69290fa040aSNeel Patel 		cmb_q_base = NULL;
69390fa040aSNeel Patel 		cmb_q_base_pa = 0;
6949de21005SAndrew Boyer 	}
6959de21005SAndrew Boyer 
6964ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6974ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
69801a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
69901a6c311SAlfredo Cardigliano 
70090fa040aSNeel Patel 	ionic_q_map(&new->q, q_base, q_base_pa, cmb_q_base, cmb_q_base_pa);
70101a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
70201a6c311SAlfredo Cardigliano 
70301a6c311SAlfredo Cardigliano 	*qcq = new;
70401a6c311SAlfredo Cardigliano 
70501a6c311SAlfredo Cardigliano 	return 0;
70601a6c311SAlfredo Cardigliano 
7074c8f8d57SAndrew Boyer err_out_free_info:
7084c8f8d57SAndrew Boyer 	rte_free(new->q.info);
7094c8f8d57SAndrew Boyer err_out_free_qcq:
7104c8f8d57SAndrew Boyer 	rte_free(new);
71101a6c311SAlfredo Cardigliano 
71201a6c311SAlfredo Cardigliano 	return err;
71301a6c311SAlfredo Cardigliano }
71401a6c311SAlfredo Cardigliano 
71501a6c311SAlfredo Cardigliano void
71601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
71701a6c311SAlfredo Cardigliano {
71801a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
71901a6c311SAlfredo Cardigliano 		qcq->base = NULL;
72001a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
72101a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
72201a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
72301a6c311SAlfredo Cardigliano 	}
72401a6c311SAlfredo Cardigliano 
72501a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
72601a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
72701a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
72801a6c311SAlfredo Cardigliano 	}
72901a6c311SAlfredo Cardigliano 
73001a6c311SAlfredo Cardigliano 	rte_free(qcq);
73101a6c311SAlfredo Cardigliano }
73201a6c311SAlfredo Cardigliano 
7337b20fc2fSAndrew Boyer static uint64_t
7347b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif)
7357b20fc2fSAndrew Boyer {
7367b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7377b20fc2fSAndrew Boyer 
7387b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7397b20fc2fSAndrew Boyer 
7407b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7417b20fc2fSAndrew Boyer 	rxm.data_off = RTE_PKTMBUF_HEADROOM;
7427b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7437b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7447b20fc2fSAndrew Boyer 
7457b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7467b20fc2fSAndrew Boyer 
7477b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7487b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7497b20fc2fSAndrew Boyer }
7507b20fc2fSAndrew Boyer 
7517b20fc2fSAndrew Boyer static uint64_t
7527b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif)
7537b20fc2fSAndrew Boyer {
7547b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7557b20fc2fSAndrew Boyer 
7567b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7577b20fc2fSAndrew Boyer 
7587b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7597b20fc2fSAndrew Boyer 	rxm.data_off = 0;  /* no headroom */
7607b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7617b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7627b20fc2fSAndrew Boyer 
7637b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7647b20fc2fSAndrew Boyer 
7657b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7667b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7677b20fc2fSAndrew Boyer }
7687b20fc2fSAndrew Boyer 
769a27d9013SAlfredo Cardigliano int
7708ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
771d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
772d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
773a27d9013SAlfredo Cardigliano {
774be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
775e86a6fccSAndrew Boyer 	uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1;
776d5850081SAndrew Boyer 	uint32_t max_mtu;
777be39f75cSAndrew Boyer 	int err;
778a27d9013SAlfredo Cardigliano 
7799de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
7809de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
781b671e69aSAndrew Boyer 
782d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
783d5850081SAndrew Boyer 
784d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
785d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
786d5850081SAndrew Boyer 
787d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
788d5850081SAndrew Boyer 
789e86a6fccSAndrew Boyer 	/* If mbufs are too small to hold received packets, enable SG */
79051de3175SAndrew Boyer 	if (max_mtu > hdr_seg_size &&
79151de3175SAndrew Boyer 	    !(lif->features & IONIC_ETH_HW_RX_SG)) {
792e86a6fccSAndrew Boyer 		IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER");
793e86a6fccSAndrew Boyer 		lif->eth_dev->data->dev_conf.rxmode.offloads |=
794e86a6fccSAndrew Boyer 			RTE_ETH_RX_OFFLOAD_SCATTER;
795e86a6fccSAndrew Boyer 		ionic_lif_configure_rx_sg_offload(lif);
796e86a6fccSAndrew Boyer 	}
797e86a6fccSAndrew Boyer 
798e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_RX_SG) {
799e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
800d5850081SAndrew Boyer 		max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
801e86a6fccSAndrew Boyer 	}
802d5850081SAndrew Boyer 
803d5850081SAndrew Boyer 	/*
804d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
8057b20fc2fSAndrew Boyer 	 * This is the worst-case number, so that there's enough room in
8067b20fc2fSAndrew Boyer 	 * the info array.
807d5850081SAndrew Boyer 	 */
808d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
809d5850081SAndrew Boyer 
8107b20fc2fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
8117b20fc2fSAndrew Boyer 		index, max_mtu, seg_size, max_segs);
812d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
813d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
814d5850081SAndrew Boyer 			max_segs, max_segs_fw);
815d5850081SAndrew Boyer 		return -EINVAL;
816d5850081SAndrew Boyer 	}
817d5850081SAndrew Boyer 
8184ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8194ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
820be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
8218ec5ad7fSAndrew Boyer 		socket_id,
8224ad56b7aSAndrew Boyer 		index,
8234ad56b7aSAndrew Boyer 		"rx",
8244ad56b7aSAndrew Boyer 		flags,
825a27d9013SAlfredo Cardigliano 		nrxq_descs,
826d5850081SAndrew Boyer 		max_segs,
827a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
828a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
829a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
830be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
831a27d9013SAlfredo Cardigliano 	if (err)
832a27d9013SAlfredo Cardigliano 		return err;
833a27d9013SAlfredo Cardigliano 
834be39f75cSAndrew Boyer 	rxq->flags = flags;
835d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
836d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
8377b20fc2fSAndrew Boyer 	rxq->rearm_data = ionic_rx_rearm_data(lif);
8387b20fc2fSAndrew Boyer 	rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
839be39f75cSAndrew Boyer 
840be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
841be39f75cSAndrew Boyer 	*rxq_out = rxq;
842a27d9013SAlfredo Cardigliano 
843a27d9013SAlfredo Cardigliano 	return 0;
844a27d9013SAlfredo Cardigliano }
845a27d9013SAlfredo Cardigliano 
846a27d9013SAlfredo Cardigliano int
8478ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
848be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
849a27d9013SAlfredo Cardigliano {
850be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
851e86a6fccSAndrew Boyer 	uint16_t flags = 0, num_segs_fw = 1;
852be39f75cSAndrew Boyer 	int err;
853a27d9013SAlfredo Cardigliano 
854e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_TX_SG) {
855e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
856e86a6fccSAndrew Boyer 		num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
857e86a6fccSAndrew Boyer 	}
8589de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
8599de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
860e19eea1eSAndrew Boyer 
861e86a6fccSAndrew Boyer 	IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw);
862e19eea1eSAndrew Boyer 
8634ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8644ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
865be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
8668ec5ad7fSAndrew Boyer 		socket_id,
8674ad56b7aSAndrew Boyer 		index,
8684ad56b7aSAndrew Boyer 		"tx",
8694ad56b7aSAndrew Boyer 		flags,
870a27d9013SAlfredo Cardigliano 		ntxq_descs,
871b4beb84aSAndrew Boyer 		num_segs_fw,
872a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
873a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
87456117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
875be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
876a27d9013SAlfredo Cardigliano 	if (err)
877a27d9013SAlfredo Cardigliano 		return err;
878a27d9013SAlfredo Cardigliano 
879be39f75cSAndrew Boyer 	txq->flags = flags;
880e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
881be39f75cSAndrew Boyer 
882be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
883be39f75cSAndrew Boyer 	*txq_out = txq;
884a27d9013SAlfredo Cardigliano 
885a27d9013SAlfredo Cardigliano 	return 0;
886a27d9013SAlfredo Cardigliano }
887a27d9013SAlfredo Cardigliano 
88801a6c311SAlfredo Cardigliano static int
88901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
89001a6c311SAlfredo Cardigliano {
891be39f75cSAndrew Boyer 	uint16_t flags = 0;
892be39f75cSAndrew Boyer 	int err;
89301a6c311SAlfredo Cardigliano 
8944ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8954ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
896be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8978ec5ad7fSAndrew Boyer 		rte_socket_id(),
8984ad56b7aSAndrew Boyer 		0,
8994ad56b7aSAndrew Boyer 		"admin",
9004ad56b7aSAndrew Boyer 		flags,
90101a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
902d5850081SAndrew Boyer 		1,
90301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
90401a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
90501a6c311SAlfredo Cardigliano 		0,
906be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
90727b942c8SAlfredo Cardigliano 	if (err)
90827b942c8SAlfredo Cardigliano 		return err;
90901a6c311SAlfredo Cardigliano 
91027b942c8SAlfredo Cardigliano 	return 0;
91127b942c8SAlfredo Cardigliano }
91227b942c8SAlfredo Cardigliano 
91327b942c8SAlfredo Cardigliano static int
91427b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
91527b942c8SAlfredo Cardigliano {
916be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
9174c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
918be39f75cSAndrew Boyer 	uint16_t flags = 0;
919be39f75cSAndrew Boyer 	int err;
92027b942c8SAlfredo Cardigliano 
9214ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
9224ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
923be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
9248ec5ad7fSAndrew Boyer 		rte_socket_id(),
9254ad56b7aSAndrew Boyer 		0,
9264ad56b7aSAndrew Boyer 		"notify",
92727b942c8SAlfredo Cardigliano 		flags,
92827b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
929d5850081SAndrew Boyer 		1,
93027b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
93127b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
93227b942c8SAlfredo Cardigliano 		0,
933be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
93401a6c311SAlfredo Cardigliano 	if (err)
93501a6c311SAlfredo Cardigliano 		return err;
93601a6c311SAlfredo Cardigliano 
9374c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
9384c8f8d57SAndrew Boyer 	if (err) {
939be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
9404c8f8d57SAndrew Boyer 		return err;
9414c8f8d57SAndrew Boyer 	}
9424c8f8d57SAndrew Boyer 
9434c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
9444c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
9454c8f8d57SAndrew Boyer 
9464c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
9474c8f8d57SAndrew Boyer 
94801a6c311SAlfredo Cardigliano 	return 0;
94901a6c311SAlfredo Cardigliano }
95001a6c311SAlfredo Cardigliano 
951c5d15850SAndrew Boyer static void
952c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
953c5d15850SAndrew Boyer {
954c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
955c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
956c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
957c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
958c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
959c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
960c5d15850SAndrew Boyer 	int err;
961c5d15850SAndrew Boyer 
962c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
963c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
964c5d15850SAndrew Boyer 
965c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
966c5d15850SAndrew Boyer 		switch (qtype) {
967c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
968c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
969c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
970c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
971c5d15850SAndrew Boyer 			break;
972c5d15850SAndrew Boyer 		default:
973c5d15850SAndrew Boyer 			continue;
974c5d15850SAndrew Boyer 		}
975c5d15850SAndrew Boyer 
976c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
977c5d15850SAndrew Boyer 
978c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
979c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
980c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
981c5d15850SAndrew Boyer 		if (err == -EINVAL) {
982c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
983c5d15850SAndrew Boyer 			continue;
984c5d15850SAndrew Boyer 		} else if (err == -EIO) {
985c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
986c5d15850SAndrew Boyer 			return;
987c5d15850SAndrew Boyer 		} else if (err) {
988c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
989c5d15850SAndrew Boyer 				qtype, err);
990c5d15850SAndrew Boyer 			return;
991c5d15850SAndrew Boyer 		}
992c5d15850SAndrew Boyer 
993c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
994c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
995c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
996c5d15850SAndrew Boyer 
997c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
998c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
999c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
1000c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
1001c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
1002c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
1003c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
1004c5d15850SAndrew Boyer 		qti->sg_desc_stride =
1005c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
1006c5d15850SAndrew Boyer 
1007c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
1008c5d15850SAndrew Boyer 			qtype, qti->version);
1009c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
1010c5d15850SAndrew Boyer 			qtype, qti->supported);
1011c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
1012c5d15850SAndrew Boyer 			qtype, qti->features);
1013c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
1014c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
1015c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
1016c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
1017c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
1018c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
1019c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
1020c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
1021c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
1022c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
1023c5d15850SAndrew Boyer 	}
1024c5d15850SAndrew Boyer }
1025c5d15850SAndrew Boyer 
1026669c8de6SAlfredo Cardigliano int
1027669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
1028669c8de6SAlfredo Cardigliano {
1029c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
1030669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
103101a6c311SAlfredo Cardigliano 	int err;
1032669c8de6SAlfredo Cardigliano 
10334ae96cb8SAndrew Boyer 	/*
10344ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
10354ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
10364ae96cb8SAndrew Boyer 	 */
10374ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
10384ae96cb8SAndrew Boyer 
10394ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
1040669c8de6SAlfredo Cardigliano 
1041c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
1042c5d15850SAndrew Boyer 
104356117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
104456117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
104556117636SAndrew Boyer 		return -ENXIO;
104656117636SAndrew Boyer 	}
104756117636SAndrew Boyer 
10489de21005SAndrew Boyer 	if (adapter->q_in_cmb) {
10499de21005SAndrew Boyer 		if (adapter->bars.num_bars >= 3 &&
10509de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 &&
10519de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) {
10529de21005SAndrew Boyer 			IONIC_PRINT(INFO, "%s enabled on %s",
10539de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10549de21005SAndrew Boyer 			lif->state |= IONIC_LIF_F_Q_IN_CMB;
10559de21005SAndrew Boyer 		} else {
10569de21005SAndrew Boyer 			IONIC_PRINT(ERR, "%s not supported on %s, disabled",
10579de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10589de21005SAndrew Boyer 		}
10599de21005SAndrew Boyer 	}
10609de21005SAndrew Boyer 
1061669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
1062669c8de6SAlfredo Cardigliano 
106301a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
106401a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
106501a6c311SAlfredo Cardigliano 
106684cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
1067c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
1068c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1069c67719e1SAlfredo Cardigliano 		return -ENOMEM;
1070c67719e1SAlfredo Cardigliano 	}
1071c67719e1SAlfredo Cardigliano 
1072c5d0bb79SAndrew Boyer 	lif->txqcqs = rte_calloc_socket("ionic",
1073c663c7ecSAndrew Boyer 				adapter->max_ntxqs_per_lif,
1074c5d0bb79SAndrew Boyer 				sizeof(*lif->txqcqs),
1075c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1076a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
1077a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1078a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1079a27d9013SAlfredo Cardigliano 	}
1080a27d9013SAlfredo Cardigliano 
1081c5d0bb79SAndrew Boyer 	lif->rxqcqs = rte_calloc_socket("ionic",
1082c663c7ecSAndrew Boyer 				adapter->max_nrxqs_per_lif,
1083c5d0bb79SAndrew Boyer 				sizeof(*lif->rxqcqs),
1084c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1085a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
1086a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1087a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1088a27d9013SAlfredo Cardigliano 	}
1089a27d9013SAlfredo Cardigliano 
109027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
109127b942c8SAlfredo Cardigliano 
109227b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
109327b942c8SAlfredo Cardigliano 	if (err) {
109427b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
109527b942c8SAlfredo Cardigliano 		return err;
109627b942c8SAlfredo Cardigliano 	}
109727b942c8SAlfredo Cardigliano 
109827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
109927b942c8SAlfredo Cardigliano 
110001a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
110101a6c311SAlfredo Cardigliano 	if (err) {
110201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
110301a6c311SAlfredo Cardigliano 		return err;
110401a6c311SAlfredo Cardigliano 	}
110501a6c311SAlfredo Cardigliano 
110601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
110701a6c311SAlfredo Cardigliano 
1108924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1109669c8de6SAlfredo Cardigliano 
1110669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1111669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1112669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1113669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1114669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1115669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1116669c8de6SAlfredo Cardigliano 	}
1117669c8de6SAlfredo Cardigliano 
1118669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1119669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1120669c8de6SAlfredo Cardigliano 
1121669c8de6SAlfredo Cardigliano 	return 0;
1122669c8de6SAlfredo Cardigliano }
1123669c8de6SAlfredo Cardigliano 
1124669c8de6SAlfredo Cardigliano void
1125669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1126669c8de6SAlfredo Cardigliano {
112727b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1128be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
112927b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
113027b942c8SAlfredo Cardigliano 	}
113127b942c8SAlfredo Cardigliano 
113201a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1133be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
113401a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
113501a6c311SAlfredo Cardigliano 	}
113601a6c311SAlfredo Cardigliano 
1137a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1138a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1139a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1140a27d9013SAlfredo Cardigliano 	}
1141a27d9013SAlfredo Cardigliano 
1142a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1143a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1144a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1145a27d9013SAlfredo Cardigliano 	}
1146a27d9013SAlfredo Cardigliano 
1147669c8de6SAlfredo Cardigliano 	if (lif->info) {
1148669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1149669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1150669c8de6SAlfredo Cardigliano 	}
1151669c8de6SAlfredo Cardigliano }
1152669c8de6SAlfredo Cardigliano 
1153175e4e7eSAndrew Boyer void
1154175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1155175e4e7eSAndrew Boyer {
1156175e4e7eSAndrew Boyer 	uint32_t i;
1157175e4e7eSAndrew Boyer 
1158175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
11597483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1160175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1161175e4e7eSAndrew Boyer 	}
1162175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
11637483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1164175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1165175e4e7eSAndrew Boyer 	}
1166175e4e7eSAndrew Boyer }
1167175e4e7eSAndrew Boyer 
116822e7171bSAlfredo Cardigliano int
116922e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
117022e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
117122e7171bSAlfredo Cardigliano {
117209f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
117322e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
117422e7171bSAlfredo Cardigliano 		.pending_work = true,
117522e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
117622e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
117722e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
117809f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
117909f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
118022e7171bSAlfredo Cardigliano 		},
118122e7171bSAlfredo Cardigliano 	};
118222e7171bSAlfredo Cardigliano 	unsigned int i;
118309f806e9SAndrew Boyer 	uint16_t tbl_sz =
118409f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
118522e7171bSAlfredo Cardigliano 
118622e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
118722e7171bSAlfredo Cardigliano 
118822e7171bSAlfredo Cardigliano 	lif->rss_types = types;
118922e7171bSAlfredo Cardigliano 
119022e7171bSAlfredo Cardigliano 	if (key)
119122e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
119222e7171bSAlfredo Cardigliano 
119322e7171bSAlfredo Cardigliano 	if (indir)
119409f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
119522e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
119622e7171bSAlfredo Cardigliano 
119722e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
119822e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
119922e7171bSAlfredo Cardigliano 
120022e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
120122e7171bSAlfredo Cardigliano }
120222e7171bSAlfredo Cardigliano 
120322e7171bSAlfredo Cardigliano static int
120422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
120522e7171bSAlfredo Cardigliano {
120609f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
120722e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
120822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
120922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
121022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
121122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
121222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
121322e7171bSAlfredo Cardigliano 	};
121422e7171bSAlfredo Cardigliano 	uint32_t i;
121509f806e9SAndrew Boyer 	uint16_t tbl_sz =
121609f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
121722e7171bSAlfredo Cardigliano 
121822e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
121922e7171bSAlfredo Cardigliano 
12203d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
122122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
12223d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
12233d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
12243d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
122522e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
122622e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
122722e7171bSAlfredo Cardigliano 			return -ENOMEM;
122822e7171bSAlfredo Cardigliano 		}
122922e7171bSAlfredo Cardigliano 
123022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
123122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
12323d845eddSAndrew Boyer 	}
12333d845eddSAndrew Boyer 
12343d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
12353d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
123622e7171bSAlfredo Cardigliano 
123722e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
12383d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
123922e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
12403d845eddSAndrew Boyer 	}
124122e7171bSAlfredo Cardigliano 
12423d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
124322e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
124422e7171bSAlfredo Cardigliano }
124522e7171bSAlfredo Cardigliano 
124622e7171bSAlfredo Cardigliano static void
124722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
124822e7171bSAlfredo Cardigliano {
12491a9afd1fSAndrew Boyer 	if (lif->rss_ind_tbl) {
125022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
125122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
125222e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
125322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
125422e7171bSAlfredo Cardigliano 	}
125522e7171bSAlfredo Cardigliano }
125622e7171bSAlfredo Cardigliano 
1257be39f75cSAndrew Boyer void
12587bb08900SAndrew Boyer ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq *txq)
1259be39f75cSAndrew Boyer {
12607bb08900SAndrew Boyer 	ionic_qcq_disable_nowait(&txq->qcq, &txq->admin_ctx);
1261e7222f94SAndrew Boyer 
1262be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1263be39f75cSAndrew Boyer }
1264be39f75cSAndrew Boyer 
1265be39f75cSAndrew Boyer void
12667bb08900SAndrew Boyer ionic_lif_txq_stats(struct ionic_tx_qcq *txq)
1267be39f75cSAndrew Boyer {
12687bb08900SAndrew Boyer 	struct ionic_tx_stats *stats = &txq->stats;
12697bb08900SAndrew Boyer 
12707bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "TX queue %u pkts %ju tso %ju",
12717bb08900SAndrew Boyer 		txq->qcq.q.index, stats->packets, stats->tso);
12727bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "TX queue %u comps %ju (%ju per)",
12737bb08900SAndrew Boyer 		txq->qcq.q.index, stats->comps,
12747bb08900SAndrew Boyer 		stats->comps ? stats->packets / stats->comps : 0);
12757bb08900SAndrew Boyer }
12767bb08900SAndrew Boyer 
12777bb08900SAndrew Boyer void
12787bb08900SAndrew Boyer ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq *rxq)
12797bb08900SAndrew Boyer {
12807bb08900SAndrew Boyer 	ionic_qcq_disable_nowait(&rxq->qcq, &rxq->admin_ctx);
1281e7222f94SAndrew Boyer 
1282be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1283be39f75cSAndrew Boyer }
1284be39f75cSAndrew Boyer 
12857bb08900SAndrew Boyer void
12867bb08900SAndrew Boyer ionic_lif_rxq_stats(struct ionic_rx_qcq *rxq)
12877bb08900SAndrew Boyer {
12887bb08900SAndrew Boyer 	struct ionic_rx_stats *stats = &rxq->stats;
12897bb08900SAndrew Boyer 
12907bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "RX queue %u pkts %ju mtod %ju",
12917bb08900SAndrew Boyer 		rxq->qcq.q.index, stats->packets, stats->mtods);
12927bb08900SAndrew Boyer }
12937bb08900SAndrew Boyer 
129401a6c311SAlfredo Cardigliano static void
1295be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
129601a6c311SAlfredo Cardigliano {
1297be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
12984c8f8d57SAndrew Boyer }
12994c8f8d57SAndrew Boyer 
13004c8f8d57SAndrew Boyer static void
13014c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
13024c8f8d57SAndrew Boyer {
1303be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
13044c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
13054c8f8d57SAndrew Boyer 
13064c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
13074c8f8d57SAndrew Boyer 		return;
13084c8f8d57SAndrew Boyer 
13094c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
13104c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
13114c8f8d57SAndrew Boyer 
13124c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1313a27d9013SAlfredo Cardigliano }
1314a27d9013SAlfredo Cardigliano 
131501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
131601a6c311SAlfredo Cardigliano int
131701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
131801a6c311SAlfredo Cardigliano 		void *cb_arg)
131901a6c311SAlfredo Cardigliano {
132001a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
132101a6c311SAlfredo Cardigliano 	uint32_t work_done;
132201a6c311SAlfredo Cardigliano 
132301a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
132401a6c311SAlfredo Cardigliano 
132501a6c311SAlfredo Cardigliano 	return work_done;
132601a6c311SAlfredo Cardigliano }
132701a6c311SAlfredo Cardigliano 
132827b942c8SAlfredo Cardigliano static void
132927b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
133027b942c8SAlfredo Cardigliano {
133127b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
133227b942c8SAlfredo Cardigliano 	bool link_up;
133327b942c8SAlfredo Cardigliano 
133427b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
133527b942c8SAlfredo Cardigliano 
133627b942c8SAlfredo Cardigliano 	if (!lif->info)
133727b942c8SAlfredo Cardigliano 		return;
133827b942c8SAlfredo Cardigliano 
133927b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
134027b942c8SAlfredo Cardigliano 
134127b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
134227b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
134327b942c8SAlfredo Cardigliano 		return;
134427b942c8SAlfredo Cardigliano 
134527b942c8SAlfredo Cardigliano 	if (link_up) {
134609f806e9SAndrew Boyer 		adapter->link_speed =
134709f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1348be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1349be63459eSAndrew Boyer 			adapter->link_speed);
135027b942c8SAlfredo Cardigliano 	} else {
135127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
135227b942c8SAlfredo Cardigliano 	}
135327b942c8SAlfredo Cardigliano 
135427b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1355be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1356be63459eSAndrew Boyer }
1357be63459eSAndrew Boyer 
1358be63459eSAndrew Boyer static void
1359be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1360be63459eSAndrew Boyer {
1361be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1362be63459eSAndrew Boyer 		return;
1363be63459eSAndrew Boyer 
1364be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1365be63459eSAndrew Boyer 
1366be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1367be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1368be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1369be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1370be63459eSAndrew Boyer 	}
1371be63459eSAndrew Boyer 
1372be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
137327b942c8SAlfredo Cardigliano }
137427b942c8SAlfredo Cardigliano 
137527b942c8SAlfredo Cardigliano static bool
13764ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
137727b942c8SAlfredo Cardigliano {
137827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
137927b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
138027b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
138127b942c8SAlfredo Cardigliano 
138227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
138327b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
138427b942c8SAlfredo Cardigliano 
138527b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
138627b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
138727b942c8SAlfredo Cardigliano 		return false;
138827b942c8SAlfredo Cardigliano 
138927b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
139027b942c8SAlfredo Cardigliano 
139127b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
139227b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
139327b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1394be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1395be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1396be63459eSAndrew Boyer 			lif->name,
139727b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
139827b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
139927b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
140027b942c8SAlfredo Cardigliano 
140127b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
140227b942c8SAlfredo Cardigliano 		break;
1403be63459eSAndrew Boyer 
1404be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1405be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1406be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1407be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1408be63459eSAndrew Boyer 			lif->name,
1409be63459eSAndrew Boyer 			cq_desc->event.eid,
1410be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1411be63459eSAndrew Boyer 			cq_desc->reset.state);
1412be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1413be63459eSAndrew Boyer 		break;
1414be63459eSAndrew Boyer 
141527b942c8SAlfredo Cardigliano 	default:
141627b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
141727b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
141827b942c8SAlfredo Cardigliano 		break;
141927b942c8SAlfredo Cardigliano 	}
142027b942c8SAlfredo Cardigliano 
142127b942c8SAlfredo Cardigliano 	return true;
142227b942c8SAlfredo Cardigliano }
142327b942c8SAlfredo Cardigliano 
142427b942c8SAlfredo Cardigliano int
142527b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
142627b942c8SAlfredo Cardigliano {
142727b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1428be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
142927b942c8SAlfredo Cardigliano 	uint32_t work_done;
143027b942c8SAlfredo Cardigliano 
1431be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
143227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
143327b942c8SAlfredo Cardigliano 		return -1;
143427b942c8SAlfredo Cardigliano 	}
143527b942c8SAlfredo Cardigliano 
1436be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
143727b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
143827b942c8SAlfredo Cardigliano 
1439be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1440be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
144127b942c8SAlfredo Cardigliano 
144227b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
144327b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
144427b942c8SAlfredo Cardigliano 
1445be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
144627b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
144727b942c8SAlfredo Cardigliano 
1448be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
144927b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
145027b942c8SAlfredo Cardigliano 
145127b942c8SAlfredo Cardigliano 	return 0;
145227b942c8SAlfredo Cardigliano }
145327b942c8SAlfredo Cardigliano 
145401a6c311SAlfredo Cardigliano static int
145501a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
145601a6c311SAlfredo Cardigliano {
145701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1458be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1459be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
146001a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
146113133a28SAndrew Boyer 	uint32_t retries = 5;
146201a6c311SAlfredo Cardigliano 	int err;
146301a6c311SAlfredo Cardigliano 
146413133a28SAndrew Boyer retry_adminq_init:
1465be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
146601a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
146713133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
146813133a28SAndrew Boyer 		retries--;
146913133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
147013133a28SAndrew Boyer 		goto retry_adminq_init;
147113133a28SAndrew Boyer 	}
147201a6c311SAlfredo Cardigliano 	if (err)
147301a6c311SAlfredo Cardigliano 		return err;
147401a6c311SAlfredo Cardigliano 
147501a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
147601a6c311SAlfredo Cardigliano 
147701a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
147809f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
147901a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
148001a6c311SAlfredo Cardigliano 
148101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
148201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
148301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
148401a6c311SAlfredo Cardigliano 
1485be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
148601a6c311SAlfredo Cardigliano 
148701a6c311SAlfredo Cardigliano 	return 0;
148801a6c311SAlfredo Cardigliano }
148901a6c311SAlfredo Cardigliano 
149027b942c8SAlfredo Cardigliano static int
149127b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
149227b942c8SAlfredo Cardigliano {
149327b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1494be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1495be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
14960a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
149727b942c8SAlfredo Cardigliano 	int err;
149827b942c8SAlfredo Cardigliano 
149927b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
150027b942c8SAlfredo Cardigliano 		.pending_work = true,
150127b942c8SAlfredo Cardigliano 		.cmd.q_init = {
150227b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
150327b942c8SAlfredo Cardigliano 			.type = q->type,
1504c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
150509f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
15060a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
150727b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
150809f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
150927b942c8SAlfredo Cardigliano 		}
151027b942c8SAlfredo Cardigliano 	};
151127b942c8SAlfredo Cardigliano 
15120a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
15130a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
15140a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
15150a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
15160a00bdafSAndrew Boyer 	}
15170a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
15180a00bdafSAndrew Boyer 
151909f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
152009f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
152127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
152227b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15234ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
152427b942c8SAlfredo Cardigliano 
152527b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
152627b942c8SAlfredo Cardigliano 	if (err)
152727b942c8SAlfredo Cardigliano 		return err;
152827b942c8SAlfredo Cardigliano 
152927b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
153009f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
153127b942c8SAlfredo Cardigliano 	q->db = NULL;
153227b942c8SAlfredo Cardigliano 
153327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
153427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
153527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
153627b942c8SAlfredo Cardigliano 
1537be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
153827b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
153927b942c8SAlfredo Cardigliano 
1540be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
154127b942c8SAlfredo Cardigliano 
154227b942c8SAlfredo Cardigliano 	return 0;
154327b942c8SAlfredo Cardigliano }
154427b942c8SAlfredo Cardigliano 
1545669c8de6SAlfredo Cardigliano int
1546598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1547598f6726SAlfredo Cardigliano {
1548598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1549598f6726SAlfredo Cardigliano 		.pending_work = true,
1550598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1551598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1552598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
155309f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1554598f6726SAlfredo Cardigliano 		},
1555598f6726SAlfredo Cardigliano 	};
1556598f6726SAlfredo Cardigliano 	int err;
1557598f6726SAlfredo Cardigliano 
1558598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1559598f6726SAlfredo Cardigliano 	if (err)
1560598f6726SAlfredo Cardigliano 		return err;
1561598f6726SAlfredo Cardigliano 
156209f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1563598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1564598f6726SAlfredo Cardigliano 
1565598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1566598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1567598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1568598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1569598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1570598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1571598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1572598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1573598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1574598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1575598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1576598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1577598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1578598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1579598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1580598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1581598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1582598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1583598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1584598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1585598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1586598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1587598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1588598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1589598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1590598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1591598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1592598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1593598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1594598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1595598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1596598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1597598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1598598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1599598f6726SAlfredo Cardigliano 
1600598f6726SAlfredo Cardigliano 	return 0;
1601598f6726SAlfredo Cardigliano }
1602598f6726SAlfredo Cardigliano 
1603a27d9013SAlfredo Cardigliano int
1604*0033e92fSAndrew Boyer ionic_lif_txq_init_nowait(struct ionic_tx_qcq *txq)
1605a27d9013SAlfredo Cardigliano {
1606be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1607a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1608a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1609a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1610*0033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &txq->admin_ctx;
1611*0033e92fSAndrew Boyer 	int err;
1612*0033e92fSAndrew Boyer 
1613*0033e92fSAndrew Boyer 	*ctx = (struct ionic_admin_ctx) {
1614a27d9013SAlfredo Cardigliano 		.pending_work = true,
1615a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1616a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1617a27d9013SAlfredo Cardigliano 			.type = q->type,
1618c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
161909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1620e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
162109f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1622a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
162309f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
162409f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1625a27d9013SAlfredo Cardigliano 		},
1626a27d9013SAlfredo Cardigliano 	};
1627a27d9013SAlfredo Cardigliano 
1628e86a6fccSAndrew Boyer 	if (txq->flags & IONIC_QCQ_F_SG)
1629*0033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
163090fa040aSNeel Patel 	if (txq->flags & IONIC_QCQ_F_CMB) {
1631*0033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1632*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa);
163390fa040aSNeel Patel 	} else {
1634*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa);
163590fa040aSNeel Patel 	}
16369de21005SAndrew Boyer 
163709f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
163809f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1639a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1640*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_size);
1641*0033e92fSAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx->cmd.q_init.ver);
1642a27d9013SAlfredo Cardigliano 
1643e7222f94SAndrew Boyer 	ionic_q_reset(q);
1644e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1645e7222f94SAndrew Boyer 
1646*0033e92fSAndrew Boyer 	/* Caller responsible for calling ionic_lif_txq_init_done() */
1647*0033e92fSAndrew Boyer 	err = ionic_adminq_post(lif, ctx);
1648a27d9013SAlfredo Cardigliano 	if (err)
1649*0033e92fSAndrew Boyer 		ctx->pending_work = false;
1650a27d9013SAlfredo Cardigliano 	return err;
1651*0033e92fSAndrew Boyer }
1652a27d9013SAlfredo Cardigliano 
1653*0033e92fSAndrew Boyer void
1654*0033e92fSAndrew Boyer ionic_lif_txq_init_done(struct ionic_tx_qcq *txq)
1655*0033e92fSAndrew Boyer {
1656*0033e92fSAndrew Boyer 	struct ionic_lif *lif = txq->qcq.lif;
1657*0033e92fSAndrew Boyer 	struct ionic_queue *q = &txq->qcq.q;
1658*0033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &txq->admin_ctx;
1659*0033e92fSAndrew Boyer 
1660*0033e92fSAndrew Boyer 	q->hw_type = ctx->comp.q_init.hw_type;
1661*0033e92fSAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx->comp.q_init.hw_index);
1662a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1663a27d9013SAlfredo Cardigliano 
1664a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1665a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1666a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1667a27d9013SAlfredo Cardigliano 
1668be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1669a27d9013SAlfredo Cardigliano }
1670a27d9013SAlfredo Cardigliano 
1671a27d9013SAlfredo Cardigliano int
1672*0033e92fSAndrew Boyer ionic_lif_rxq_init_nowait(struct ionic_rx_qcq *rxq)
1673a27d9013SAlfredo Cardigliano {
1674be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1675a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1676a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1677a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1678*0033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &rxq->admin_ctx;
1679*0033e92fSAndrew Boyer 	int err;
1680*0033e92fSAndrew Boyer 
1681*0033e92fSAndrew Boyer 	*ctx = (struct ionic_admin_ctx) {
1682a27d9013SAlfredo Cardigliano 		.pending_work = true,
1683a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1684a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1685a27d9013SAlfredo Cardigliano 			.type = q->type,
1686c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
168709f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1688e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
168909f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1690a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
169109f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
169209f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1693a27d9013SAlfredo Cardigliano 		},
1694a27d9013SAlfredo Cardigliano 	};
1695a27d9013SAlfredo Cardigliano 
1696e86a6fccSAndrew Boyer 	if (rxq->flags & IONIC_QCQ_F_SG)
1697*0033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
169890fa040aSNeel Patel 	if (rxq->flags & IONIC_QCQ_F_CMB) {
1699*0033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1700*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa);
170190fa040aSNeel Patel 	} else {
1702*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa);
170390fa040aSNeel Patel 	}
17049de21005SAndrew Boyer 
170509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
170609f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1707a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1708*0033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_size);
1709*0033e92fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx->cmd.q_init.ver);
1710a27d9013SAlfredo Cardigliano 
1711e7222f94SAndrew Boyer 	ionic_q_reset(q);
1712e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1713e7222f94SAndrew Boyer 
1714*0033e92fSAndrew Boyer 	/* Caller responsible for calling ionic_lif_rxq_init_done() */
1715*0033e92fSAndrew Boyer 	err = ionic_adminq_post(lif, ctx);
1716a27d9013SAlfredo Cardigliano 	if (err)
1717*0033e92fSAndrew Boyer 		ctx->pending_work = false;
1718a27d9013SAlfredo Cardigliano 	return err;
1719*0033e92fSAndrew Boyer }
1720a27d9013SAlfredo Cardigliano 
1721*0033e92fSAndrew Boyer void
1722*0033e92fSAndrew Boyer ionic_lif_rxq_init_done(struct ionic_rx_qcq *rxq)
1723*0033e92fSAndrew Boyer {
1724*0033e92fSAndrew Boyer 	struct ionic_lif *lif = rxq->qcq.lif;
1725*0033e92fSAndrew Boyer 	struct ionic_queue *q = &rxq->qcq.q;
1726*0033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &rxq->admin_ctx;
1727*0033e92fSAndrew Boyer 
1728*0033e92fSAndrew Boyer 	q->hw_type = ctx->comp.q_init.hw_type;
1729*0033e92fSAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx->comp.q_init.hw_index);
1730a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1731a27d9013SAlfredo Cardigliano 
1732be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1733a27d9013SAlfredo Cardigliano 
1734a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1735a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1736a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1737a27d9013SAlfredo Cardigliano }
1738a27d9013SAlfredo Cardigliano 
1739598f6726SAlfredo Cardigliano static int
1740598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1741598f6726SAlfredo Cardigliano {
1742598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1743598f6726SAlfredo Cardigliano 		.pending_work = true,
1744598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1745598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1746598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1747598f6726SAlfredo Cardigliano 		},
1748598f6726SAlfredo Cardigliano 	};
1749598f6726SAlfredo Cardigliano 	int err;
1750598f6726SAlfredo Cardigliano 
1751598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1752598f6726SAlfredo Cardigliano 
1753598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1754598f6726SAlfredo Cardigliano 	if (err)
1755598f6726SAlfredo Cardigliano 		return err;
1756598f6726SAlfredo Cardigliano 
1757598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1758598f6726SAlfredo Cardigliano 
1759598f6726SAlfredo Cardigliano 	return 0;
1760598f6726SAlfredo Cardigliano }
1761598f6726SAlfredo Cardigliano 
1762598f6726SAlfredo Cardigliano static void
1763598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1764598f6726SAlfredo Cardigliano {
1765598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1766598f6726SAlfredo Cardigliano 		.pending_work = true,
1767598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1768598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1769598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1770598f6726SAlfredo Cardigliano 		},
1771598f6726SAlfredo Cardigliano 	};
1772598f6726SAlfredo Cardigliano 
17734ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
17744ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1775598f6726SAlfredo Cardigliano 
1776598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1777598f6726SAlfredo Cardigliano }
1778598f6726SAlfredo Cardigliano 
1779598f6726SAlfredo Cardigliano int
1780669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1781669c8de6SAlfredo Cardigliano {
1782669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1783656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
178413133a28SAndrew Boyer 	uint32_t retries = 5;
1785669c8de6SAlfredo Cardigliano 	int err;
1786669c8de6SAlfredo Cardigliano 
17873cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
17883cdfd905SAlfredo Cardigliano 
178913133a28SAndrew Boyer retry_lif_init:
179000b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1791669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
179213133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
179313133a28SAndrew Boyer 		retries--;
179413133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
179513133a28SAndrew Boyer 		goto retry_lif_init;
179613133a28SAndrew Boyer 	}
1797669c8de6SAlfredo Cardigliano 	if (err)
1798669c8de6SAlfredo Cardigliano 		return err;
1799669c8de6SAlfredo Cardigliano 
1800656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1801656bfc9aSAndrew Boyer 
180209f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1803669c8de6SAlfredo Cardigliano 
180401a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
180501a6c311SAlfredo Cardigliano 	if (err)
180601a6c311SAlfredo Cardigliano 		return err;
180701a6c311SAlfredo Cardigliano 
180827b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
180927b942c8SAlfredo Cardigliano 	if (err)
181027b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
181127b942c8SAlfredo Cardigliano 
181218a44465SAndrew Boyer 	/*
181318a44465SAndrew Boyer 	 * Configure initial feature set
181418a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
181518a44465SAndrew Boyer 	 */
181618a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1817598f6726SAlfredo Cardigliano 
1818598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1819598f6726SAlfredo Cardigliano 	if (err)
1820598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1821598f6726SAlfredo Cardigliano 
182254fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1823598f6726SAlfredo Cardigliano 	if (err)
1824598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1825598f6726SAlfredo Cardigliano 
182654fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
182754fe083fSAlfredo Cardigliano 	if (err)
182854fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
182954fe083fSAlfredo Cardigliano 
1830598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1831598f6726SAlfredo Cardigliano 
1832669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1833669c8de6SAlfredo Cardigliano 
1834669c8de6SAlfredo Cardigliano 	return 0;
183527b942c8SAlfredo Cardigliano 
183654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
183754fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
183854fe083fSAlfredo Cardigliano 
1839598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
18404c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1841598f6726SAlfredo Cardigliano 
184227b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1843be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
184427b942c8SAlfredo Cardigliano 
184527b942c8SAlfredo Cardigliano 	return err;
1846669c8de6SAlfredo Cardigliano }
1847669c8de6SAlfredo Cardigliano 
1848669c8de6SAlfredo Cardigliano void
1849669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1850669c8de6SAlfredo Cardigliano {
1851669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1852669c8de6SAlfredo Cardigliano 		return;
1853669c8de6SAlfredo Cardigliano 
185454fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
185522e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
18564c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1857be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
185801a6c311SAlfredo Cardigliano 
1859669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1860669c8de6SAlfredo Cardigliano }
1861669c8de6SAlfredo Cardigliano 
186218a44465SAndrew Boyer void
186318a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
186418a44465SAndrew Boyer {
186518a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
186618a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
186718a44465SAndrew Boyer 
186818a44465SAndrew Boyer 	/*
186918a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1870295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
187118a44465SAndrew Boyer 	 */
1872295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
187318a44465SAndrew Boyer 
1874295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1875295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
187618a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
187718a44465SAndrew Boyer 		else
187818a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
187918a44465SAndrew Boyer 	}
188018a44465SAndrew Boyer }
188118a44465SAndrew Boyer 
188218a44465SAndrew Boyer void
1883e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif)
1884e86a6fccSAndrew Boyer {
1885e86a6fccSAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
1886e86a6fccSAndrew Boyer 
1887e86a6fccSAndrew Boyer 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
1888e86a6fccSAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
1889e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
1890e86a6fccSAndrew Boyer 	} else {
1891e86a6fccSAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
1892e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
1893e86a6fccSAndrew Boyer 	}
1894e86a6fccSAndrew Boyer }
1895e86a6fccSAndrew Boyer 
1896e86a6fccSAndrew Boyer void
1897598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1898598f6726SAlfredo Cardigliano {
189918a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
190018a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
190122e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
190209f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
190322e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
190409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
190522e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
190609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
190722e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
190822e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
190922e7171bSAlfredo Cardigliano 
1910598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1911598f6726SAlfredo Cardigliano 
191222e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
191322e7171bSAlfredo Cardigliano 		lif->port_id);
191422e7171bSAlfredo Cardigliano 
191522e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
191622e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
191722e7171bSAlfredo Cardigliano 
191822e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
191922e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
192022e7171bSAlfredo Cardigliano 
192122e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
192222e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1923a27d9013SAlfredo Cardigliano 
192418a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
192518a44465SAndrew Boyer 
192618a44465SAndrew Boyer 	/*
192718a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
192818a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1929295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
193018a44465SAndrew Boyer 	 */
193118a44465SAndrew Boyer 
193218a44465SAndrew Boyer 	/* RX per-port */
193318a44465SAndrew Boyer 
1934295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1935295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1936295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
193718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
193818a44465SAndrew Boyer 	else
193918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
194018a44465SAndrew Boyer 
1941e86a6fccSAndrew Boyer 	/*
1942e86a6fccSAndrew Boyer 	 * NB: RX_SG may be enabled later during rx_queue_setup() if
1943e86a6fccSAndrew Boyer 	 * required by the mbuf/mtu configuration
1944e86a6fccSAndrew Boyer 	 */
1945e86a6fccSAndrew Boyer 	ionic_lif_configure_rx_sg_offload(lif);
194618a44465SAndrew Boyer 
194718a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1948295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
194918a44465SAndrew Boyer 
195018a44465SAndrew Boyer 	/* TX per-port */
195118a44465SAndrew Boyer 
1952295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1953295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1954295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1955295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1956295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
195718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
195818a44465SAndrew Boyer 	else
195918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
196018a44465SAndrew Boyer 
1961295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
196218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
196318a44465SAndrew Boyer 	else
196418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
196518a44465SAndrew Boyer 
1966295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
196718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
196818a44465SAndrew Boyer 	else
196918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
197018a44465SAndrew Boyer 
1971295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
197218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
197318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
197418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
197518a44465SAndrew Boyer 	} else {
197618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
197718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
197818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
197918a44465SAndrew Boyer 	}
1980598f6726SAlfredo Cardigliano }
1981598f6726SAlfredo Cardigliano 
1982598f6726SAlfredo Cardigliano int
1983598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1984598f6726SAlfredo Cardigliano {
1985*0033e92fSAndrew Boyer 	struct rte_eth_dev *dev = lif->eth_dev;
19860578335aSAndrew Boyer 	uint32_t rx_mode;
1987*0033e92fSAndrew Boyer 	uint32_t i, j, chunk;
1988a27d9013SAlfredo Cardigliano 	int err;
1989*0033e92fSAndrew Boyer 	bool fatal = false;
1990598f6726SAlfredo Cardigliano 
199122e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
199222e7171bSAlfredo Cardigliano 	if (err)
199322e7171bSAlfredo Cardigliano 		return err;
199422e7171bSAlfredo Cardigliano 
19950578335aSAndrew Boyer 	if (!lif->rx_mode) {
19960578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
19970578335aSAndrew Boyer 			lif->name);
1998598f6726SAlfredo Cardigliano 
19990578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
2000598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
2001598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
2002598f6726SAlfredo Cardigliano 
2003598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
20040578335aSAndrew Boyer 	}
2005598f6726SAlfredo Cardigliano 
2006a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
2007a27d9013SAlfredo Cardigliano 		"on port %u",
2008a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
2009a27d9013SAlfredo Cardigliano 
2010*0033e92fSAndrew Boyer 	chunk = ionic_adminq_space_avail(lif);
2011a27d9013SAlfredo Cardigliano 
2012*0033e92fSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i += chunk) {
2013*0033e92fSAndrew Boyer 		if (lif->rxqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) {
2014*0033e92fSAndrew Boyer 			IONIC_PRINT(DEBUG, "Rx queue start deferred");
2015*0033e92fSAndrew Boyer 			break;
2016*0033e92fSAndrew Boyer 		}
2017*0033e92fSAndrew Boyer 
2018*0033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) {
2019*0033e92fSAndrew Boyer 			err = ionic_dev_rx_queue_start_firsthalf(dev, i + j);
2020*0033e92fSAndrew Boyer 			if (err) {
2021*0033e92fSAndrew Boyer 				fatal = true;
2022*0033e92fSAndrew Boyer 				break;
2023*0033e92fSAndrew Boyer 			}
2024*0033e92fSAndrew Boyer 		}
2025*0033e92fSAndrew Boyer 
2026*0033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) {
2027*0033e92fSAndrew Boyer 			/* Commands that failed to post return immediately */
2028*0033e92fSAndrew Boyer 			err = ionic_dev_rx_queue_start_secondhalf(dev, i + j);
2029a27d9013SAlfredo Cardigliano 			if (err)
2030*0033e92fSAndrew Boyer 				/* Don't break */
2031*0033e92fSAndrew Boyer 				fatal = true;
2032*0033e92fSAndrew Boyer 		}
2033*0033e92fSAndrew Boyer 	}
2034*0033e92fSAndrew Boyer 	if (fatal)
2035*0033e92fSAndrew Boyer 		return -EIO;
2036*0033e92fSAndrew Boyer 
2037*0033e92fSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i += chunk) {
2038*0033e92fSAndrew Boyer 		if (lif->txqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) {
2039*0033e92fSAndrew Boyer 			IONIC_PRINT(DEBUG, "Tx queue start deferred");
2040*0033e92fSAndrew Boyer 			break;
2041*0033e92fSAndrew Boyer 		}
2042*0033e92fSAndrew Boyer 
2043*0033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) {
2044*0033e92fSAndrew Boyer 			err = ionic_dev_tx_queue_start_firsthalf(dev, i + j);
2045*0033e92fSAndrew Boyer 			if (err) {
2046*0033e92fSAndrew Boyer 				fatal = true;
2047*0033e92fSAndrew Boyer 				break;
2048a27d9013SAlfredo Cardigliano 			}
2049a27d9013SAlfredo Cardigliano 		}
2050a27d9013SAlfredo Cardigliano 
2051*0033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) {
2052*0033e92fSAndrew Boyer 			/* Commands that failed to post return immediately */
2053*0033e92fSAndrew Boyer 			err = ionic_dev_tx_queue_start_secondhalf(dev, i + j);
2054a27d9013SAlfredo Cardigliano 			if (err)
2055*0033e92fSAndrew Boyer 				/* Don't break */
2056*0033e92fSAndrew Boyer 				fatal = true;
2057a27d9013SAlfredo Cardigliano 		}
2058a27d9013SAlfredo Cardigliano 	}
2059*0033e92fSAndrew Boyer 	if (fatal)
2060*0033e92fSAndrew Boyer 		return -EIO;
2061a27d9013SAlfredo Cardigliano 
2062598f6726SAlfredo Cardigliano 	/* Carrier ON here */
2063be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
2064be63459eSAndrew Boyer 
2065be63459eSAndrew Boyer 	ionic_link_status_check(lif);
2066598f6726SAlfredo Cardigliano 
2067598f6726SAlfredo Cardigliano 	return 0;
2068598f6726SAlfredo Cardigliano }
2069598f6726SAlfredo Cardigliano 
2070598f6726SAlfredo Cardigliano int
2071669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
2072669c8de6SAlfredo Cardigliano {
2073669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
2074669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
207509f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
207676276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
207776276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
207876276d71SAndrew Boyer 	uint32_t i, nwords;
2079669c8de6SAlfredo Cardigliano 	int err;
2080669c8de6SAlfredo Cardigliano 
2081669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
2082669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
2083669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
2084669c8de6SAlfredo Cardigliano 	if (err)
2085669c8de6SAlfredo Cardigliano 		return (err);
2086669c8de6SAlfredo Cardigliano 
2087669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
2088669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
2089669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
2090669c8de6SAlfredo Cardigliano 
2091669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
209209f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
2093669c8de6SAlfredo Cardigliano 
2094669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
209509f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
2096669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
209709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
2098669c8de6SAlfredo Cardigliano 
2099669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
210009f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
2101669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
210209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
2103669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
210409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
2105669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
210609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
2107669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
210809f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
2109669c8de6SAlfredo Cardigliano 
2110669c8de6SAlfredo Cardigliano 	return 0;
2111669c8de6SAlfredo Cardigliano }
2112669c8de6SAlfredo Cardigliano 
2113669c8de6SAlfredo Cardigliano int
2114669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
2115669c8de6SAlfredo Cardigliano {
2116669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
211709f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
211809f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
2119669c8de6SAlfredo Cardigliano 
2120669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
212109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
2122669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
212309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
2124669c8de6SAlfredo Cardigliano 
212500b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
2126669c8de6SAlfredo Cardigliano 
2127669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
21284ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
21294ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
2130669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
2131669c8de6SAlfredo Cardigliano 		return -ENOSPC;
2132669c8de6SAlfredo Cardigliano 	}
2133669c8de6SAlfredo Cardigliano 
2134669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
2135669c8de6SAlfredo Cardigliano 
2136669c8de6SAlfredo Cardigliano 	return 0;
2137669c8de6SAlfredo Cardigliano }
2138