xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision d026a6b02bba146b130688b4b9e3851a65035ad3)
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
ionic_qcq_disable_nowait(struct ionic_qcq * qcq,struct ionic_admin_ctx * ctx)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
ionic_lif_stop(struct ionic_lif * lif)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
ionic_lif_reset(struct ionic_lif * lif)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
ionic_lif_get_abs_stats(const struct ionic_lif * lif,struct rte_eth_stats * stats)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
ionic_lif_get_stats(const struct ionic_lif * lif,struct rte_eth_stats * stats)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
ionic_lif_reset_stats(struct ionic_lif * lif)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
ionic_lif_get_hw_stats(struct ionic_lif * lif,struct ionic_lif_stats * stats)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
ionic_lif_reset_hw_stats(struct ionic_lif * lif)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
ionic_lif_addr_add(struct ionic_lif * lif,const uint8_t * addr)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
ionic_lif_addr_del(struct ionic_lif * lif,const uint8_t * addr)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
ionic_dev_add_mac(struct rte_eth_dev * eth_dev,struct rte_ether_addr * mac_addr,uint32_t index __rte_unused,uint32_t pool __rte_unused)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
ionic_dev_remove_mac(struct rte_eth_dev * eth_dev,uint32_t index)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
ionic_dev_set_mac(struct rte_eth_dev * eth_dev,struct rte_ether_addr * mac_addr)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
ionic_vlan_rx_add_vid(struct ionic_lif * lif,uint16_t vid)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
ionic_vlan_rx_kill_vid(struct ionic_lif * lif,uint16_t vid)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
ionic_dev_vlan_filter_set(struct rte_eth_dev * eth_dev,uint16_t vlan_id,int on)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
ionic_lif_rx_mode(struct ionic_lif * lif,uint32_t rx_mode)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
ionic_set_rx_mode(struct ionic_lif * lif,uint32_t rx_mode)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
ionic_dev_promiscuous_enable(struct rte_eth_dev * eth_dev)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
ionic_dev_promiscuous_disable(struct rte_eth_dev * eth_dev)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
ionic_dev_allmulticast_enable(struct rte_eth_dev * eth_dev)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
ionic_dev_allmulticast_disable(struct rte_eth_dev * eth_dev)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
ionic_lif_change_mtu(struct ionic_lif * lif,uint32_t new_mtu)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 
543fffea1aeSAndrew Boyer 	/* Not needed for embedded applications */
544fffea1aeSAndrew Boyer 	if (ionic_is_embedded())
545fffea1aeSAndrew Boyer 		return 0;
546fffea1aeSAndrew Boyer 
547b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
548598f6726SAlfredo Cardigliano }
549598f6726SAlfredo Cardigliano 
550598f6726SAlfredo Cardigliano int
ionic_intr_alloc(struct ionic_lif * lif,struct ionic_intr_info * intr)55101a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
55201a6c311SAlfredo Cardigliano {
55301a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
55401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
55501a6c311SAlfredo Cardigliano 	unsigned long index;
55601a6c311SAlfredo Cardigliano 
55701a6c311SAlfredo Cardigliano 	/*
55801a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55901a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5604ae96cb8SAndrew Boyer 	 * which has index = 0)
56101a6c311SAlfredo Cardigliano 	 */
56201a6c311SAlfredo Cardigliano 
56301a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
56401a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
56501a6c311SAlfredo Cardigliano 			break;
56601a6c311SAlfredo Cardigliano 
56701a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56801a6c311SAlfredo Cardigliano 		return -ENOSPC;
56901a6c311SAlfredo Cardigliano 
57001a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
57101a6c311SAlfredo Cardigliano 
57201a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
57301a6c311SAlfredo Cardigliano 
57401a6c311SAlfredo Cardigliano 	return 0;
57501a6c311SAlfredo Cardigliano }
57601a6c311SAlfredo Cardigliano 
57701a6c311SAlfredo Cardigliano static int
ionic_qcq_alloc(struct ionic_lif * lif,uint8_t type,size_t struct_size,uint32_t socket_id,uint32_t index,const char * type_name,uint16_t flags,uint16_t num_descs,uint16_t num_segs,uint16_t desc_size,uint16_t cq_desc_size,uint16_t sg_desc_size,struct ionic_qcq ** qcq)5784ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5794ad56b7aSAndrew Boyer 		uint8_t type,
580be39f75cSAndrew Boyer 		size_t struct_size,
5818ec5ad7fSAndrew Boyer 		uint32_t socket_id,
58201a6c311SAlfredo Cardigliano 		uint32_t index,
5834ad56b7aSAndrew Boyer 		const char *type_name,
5844ad56b7aSAndrew Boyer 		uint16_t flags,
5854ad56b7aSAndrew Boyer 		uint16_t num_descs,
586d5850081SAndrew Boyer 		uint16_t num_segs,
5874ad56b7aSAndrew Boyer 		uint16_t desc_size,
5884ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5894ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5901abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
59101a6c311SAlfredo Cardigliano {
59201a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
59301a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59490fa040aSNeel Patel 	void *q_base, *cmb_q_base, *cq_base, *sg_base;
59501a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59601a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59701a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59890fa040aSNeel Patel 	rte_iova_t cmb_q_base_pa = 0;
59915770e98SAndrew Boyer 	size_t page_size = rte_mem_page_size();
60001a6c311SAlfredo Cardigliano 	int err;
60101a6c311SAlfredo Cardigliano 
60201a6c311SAlfredo Cardigliano 	*qcq = NULL;
60301a6c311SAlfredo Cardigliano 
60401a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60501a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60601a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60701a6c311SAlfredo Cardigliano 
60815770e98SAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
60915770e98SAndrew Boyer 			RTE_ALIGN(cq_size, page_size);
61001a6c311SAlfredo Cardigliano 	/*
61101a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61201a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
61315770e98SAndrew Boyer 	 * Adding page_size.
61401a6c311SAlfredo Cardigliano 	 */
61515770e98SAndrew Boyer 	total_size += page_size;
61601a6c311SAlfredo Cardigliano 
61701a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61815770e98SAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size);
61915770e98SAndrew Boyer 		total_size += page_size;
62001a6c311SAlfredo Cardigliano 	}
62101a6c311SAlfredo Cardigliano 
622c5d0bb79SAndrew Boyer 	new = rte_zmalloc_socket("ionic", struct_size,
623c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
62401a6c311SAlfredo Cardigliano 	if (!new) {
62501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62601a6c311SAlfredo Cardigliano 		return -ENOMEM;
62701a6c311SAlfredo Cardigliano 	}
62801a6c311SAlfredo Cardigliano 
62901a6c311SAlfredo Cardigliano 	new->lif = lif;
63001a6c311SAlfredo Cardigliano 
6317b20fc2fSAndrew Boyer 	/* Most queue types will store 1 ptr per descriptor */
632be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
6334b53e980SAndrew Boyer 				(uint64_t)num_descs * num_segs,
6344b53e980SAndrew Boyer 				sizeof(void *), page_size, socket_id);
63501a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6374c8f8d57SAndrew Boyer 		err = -ENOMEM;
6384c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
63901a6c311SAlfredo Cardigliano 	}
64001a6c311SAlfredo Cardigliano 
641d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
64201a6c311SAlfredo Cardigliano 	new->q.type = type;
64301a6c311SAlfredo Cardigliano 
6444ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64501a6c311SAlfredo Cardigliano 	if (err) {
64601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6474c8f8d57SAndrew Boyer 		goto err_out_free_info;
64801a6c311SAlfredo Cardigliano 	}
64901a6c311SAlfredo Cardigliano 
6502aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
65101a6c311SAlfredo Cardigliano 	if (err) {
65201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6534c8f8d57SAndrew Boyer 		goto err_out_free_info;
65401a6c311SAlfredo Cardigliano 	}
65501a6c311SAlfredo Cardigliano 
65601a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6574ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
65801a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
65901a6c311SAlfredo Cardigliano 
66001a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66201a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6634c8f8d57SAndrew Boyer 		goto err_out_free_info;
66401a6c311SAlfredo Cardigliano 	}
66501a6c311SAlfredo Cardigliano 
66601a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66701a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
66801a6c311SAlfredo Cardigliano 
66901a6c311SAlfredo Cardigliano 	q_base = new->base;
67001a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67101a6c311SAlfredo Cardigliano 
67215770e98SAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
67315770e98SAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
67401a6c311SAlfredo Cardigliano 
67501a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
67601a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
67715770e98SAndrew Boyer 				page_size);
67815770e98SAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
67901a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68001a6c311SAlfredo Cardigliano 	}
68101a6c311SAlfredo Cardigliano 
6829de21005SAndrew Boyer 	if (flags & IONIC_QCQ_F_CMB) {
6839de21005SAndrew Boyer 		/* alloc descriptor ring from nic memory */
6849de21005SAndrew Boyer 		if (lif->adapter->cmb_offset + q_size >
6859de21005SAndrew Boyer 				lif->adapter->bars.bar[2].len) {
6869de21005SAndrew Boyer 			IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem");
6879de21005SAndrew Boyer 			return -ENOMEM;
6889de21005SAndrew Boyer 		}
68990fa040aSNeel Patel 		cmb_q_base = (void *)
6909de21005SAndrew Boyer 			((uintptr_t)lif->adapter->bars.bar[2].vaddr +
6919de21005SAndrew Boyer 			 (uintptr_t)lif->adapter->cmb_offset);
6929de21005SAndrew Boyer 		/* CMB PA is a relative address */
69390fa040aSNeel Patel 		cmb_q_base_pa = lif->adapter->cmb_offset;
6949de21005SAndrew Boyer 		lif->adapter->cmb_offset += q_size;
69590fa040aSNeel Patel 	} else {
69690fa040aSNeel Patel 		cmb_q_base = NULL;
69790fa040aSNeel Patel 		cmb_q_base_pa = 0;
6989de21005SAndrew Boyer 	}
6999de21005SAndrew Boyer 
7004ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
7014ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
70201a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
70301a6c311SAlfredo Cardigliano 
70490fa040aSNeel Patel 	ionic_q_map(&new->q, q_base, q_base_pa, cmb_q_base, cmb_q_base_pa);
70501a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
70601a6c311SAlfredo Cardigliano 
70701a6c311SAlfredo Cardigliano 	*qcq = new;
70801a6c311SAlfredo Cardigliano 
70901a6c311SAlfredo Cardigliano 	return 0;
71001a6c311SAlfredo Cardigliano 
7114c8f8d57SAndrew Boyer err_out_free_info:
7124c8f8d57SAndrew Boyer 	rte_free(new->q.info);
7134c8f8d57SAndrew Boyer err_out_free_qcq:
7144c8f8d57SAndrew Boyer 	rte_free(new);
71501a6c311SAlfredo Cardigliano 
71601a6c311SAlfredo Cardigliano 	return err;
71701a6c311SAlfredo Cardigliano }
71801a6c311SAlfredo Cardigliano 
71901a6c311SAlfredo Cardigliano void
ionic_qcq_free(struct ionic_qcq * qcq)72001a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
72101a6c311SAlfredo Cardigliano {
72201a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
72301a6c311SAlfredo Cardigliano 		qcq->base = NULL;
72401a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
72501a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
72601a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
72701a6c311SAlfredo Cardigliano 	}
72801a6c311SAlfredo Cardigliano 
72901a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
73001a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
73101a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
73201a6c311SAlfredo Cardigliano 	}
73301a6c311SAlfredo Cardigliano 
73401a6c311SAlfredo Cardigliano 	rte_free(qcq);
73501a6c311SAlfredo Cardigliano }
73601a6c311SAlfredo Cardigliano 
7377b20fc2fSAndrew Boyer static uint64_t
ionic_rx_rearm_data(struct ionic_lif * lif)7387b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif)
7397b20fc2fSAndrew Boyer {
7407b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7417b20fc2fSAndrew Boyer 
7427b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7437b20fc2fSAndrew Boyer 
7447b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7457b20fc2fSAndrew Boyer 	rxm.data_off = RTE_PKTMBUF_HEADROOM;
7467b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7477b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7487b20fc2fSAndrew Boyer 
7497b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7507b20fc2fSAndrew Boyer 
7517b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7527b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7537b20fc2fSAndrew Boyer }
7547b20fc2fSAndrew Boyer 
7557b20fc2fSAndrew Boyer static uint64_t
ionic_rx_seg_rearm_data(struct ionic_lif * lif)7567b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif)
7577b20fc2fSAndrew Boyer {
7587b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7597b20fc2fSAndrew Boyer 
7607b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7617b20fc2fSAndrew Boyer 
7627b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7637b20fc2fSAndrew Boyer 	rxm.data_off = 0;  /* no headroom */
7647b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7657b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7667b20fc2fSAndrew Boyer 
7677b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7687b20fc2fSAndrew Boyer 
7697b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7707b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7717b20fc2fSAndrew Boyer }
7727b20fc2fSAndrew Boyer 
773a27d9013SAlfredo Cardigliano int
ionic_rx_qcq_alloc(struct ionic_lif * lif,uint32_t socket_id,uint32_t index,uint16_t nrxq_descs,struct rte_mempool * mb_pool,struct ionic_rx_qcq ** rxq_out)7748ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
775d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
776d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
777a27d9013SAlfredo Cardigliano {
778be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
779e86a6fccSAndrew Boyer 	uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1;
780d5850081SAndrew Boyer 	uint32_t max_mtu;
781be39f75cSAndrew Boyer 	int err;
782a27d9013SAlfredo Cardigliano 
7839de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
7849de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
785b671e69aSAndrew Boyer 
786d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
787d5850081SAndrew Boyer 
788d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
789d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
790d5850081SAndrew Boyer 
791d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
792d5850081SAndrew Boyer 
793e86a6fccSAndrew Boyer 	/* If mbufs are too small to hold received packets, enable SG */
79451de3175SAndrew Boyer 	if (max_mtu > hdr_seg_size &&
79551de3175SAndrew Boyer 	    !(lif->features & IONIC_ETH_HW_RX_SG)) {
796e86a6fccSAndrew Boyer 		IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER");
797e86a6fccSAndrew Boyer 		lif->eth_dev->data->dev_conf.rxmode.offloads |=
798e86a6fccSAndrew Boyer 			RTE_ETH_RX_OFFLOAD_SCATTER;
799e86a6fccSAndrew Boyer 		ionic_lif_configure_rx_sg_offload(lif);
800e86a6fccSAndrew Boyer 	}
801e86a6fccSAndrew Boyer 
802e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_RX_SG) {
803e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
804d5850081SAndrew Boyer 		max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
805e86a6fccSAndrew Boyer 	}
806d5850081SAndrew Boyer 
807d5850081SAndrew Boyer 	/*
808d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
8097b20fc2fSAndrew Boyer 	 * This is the worst-case number, so that there's enough room in
8107b20fc2fSAndrew Boyer 	 * the info array.
811d5850081SAndrew Boyer 	 */
812d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
813d5850081SAndrew Boyer 
8147b20fc2fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
8157b20fc2fSAndrew Boyer 		index, max_mtu, seg_size, max_segs);
816d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
817d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
818d5850081SAndrew Boyer 			max_segs, max_segs_fw);
819d5850081SAndrew Boyer 		return -EINVAL;
820d5850081SAndrew Boyer 	}
821d5850081SAndrew Boyer 
8224ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8234ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
824be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
8258ec5ad7fSAndrew Boyer 		socket_id,
8264ad56b7aSAndrew Boyer 		index,
8274ad56b7aSAndrew Boyer 		"rx",
8284ad56b7aSAndrew Boyer 		flags,
829a27d9013SAlfredo Cardigliano 		nrxq_descs,
830d5850081SAndrew Boyer 		max_segs,
831a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
832a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
833a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
834be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
835a27d9013SAlfredo Cardigliano 	if (err)
836a27d9013SAlfredo Cardigliano 		return err;
837a27d9013SAlfredo Cardigliano 
838be39f75cSAndrew Boyer 	rxq->flags = flags;
839d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
840d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
8417b20fc2fSAndrew Boyer 	rxq->rearm_data = ionic_rx_rearm_data(lif);
8427b20fc2fSAndrew Boyer 	rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
843be39f75cSAndrew Boyer 
844be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
845be39f75cSAndrew Boyer 	*rxq_out = rxq;
846a27d9013SAlfredo Cardigliano 
847a27d9013SAlfredo Cardigliano 	return 0;
848a27d9013SAlfredo Cardigliano }
849a27d9013SAlfredo Cardigliano 
850a27d9013SAlfredo Cardigliano int
ionic_tx_qcq_alloc(struct ionic_lif * lif,uint32_t socket_id,uint32_t index,uint16_t ntxq_descs,struct ionic_tx_qcq ** txq_out)8518ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
852be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
853a27d9013SAlfredo Cardigliano {
854be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
855e86a6fccSAndrew Boyer 	uint16_t flags = 0, num_segs_fw = 1;
856be39f75cSAndrew Boyer 	int err;
857a27d9013SAlfredo Cardigliano 
858e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_TX_SG) {
859e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
860e86a6fccSAndrew Boyer 		num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
861e86a6fccSAndrew Boyer 	}
8629de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
8639de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
864e19eea1eSAndrew Boyer 
865e86a6fccSAndrew Boyer 	IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw);
866e19eea1eSAndrew Boyer 
8674ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8684ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
869be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
8708ec5ad7fSAndrew Boyer 		socket_id,
8714ad56b7aSAndrew Boyer 		index,
8724ad56b7aSAndrew Boyer 		"tx",
8734ad56b7aSAndrew Boyer 		flags,
874a27d9013SAlfredo Cardigliano 		ntxq_descs,
875b4beb84aSAndrew Boyer 		num_segs_fw,
876a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
877a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
87856117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
879be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
880a27d9013SAlfredo Cardigliano 	if (err)
881a27d9013SAlfredo Cardigliano 		return err;
882a27d9013SAlfredo Cardigliano 
883be39f75cSAndrew Boyer 	txq->flags = flags;
884e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
885be39f75cSAndrew Boyer 
886be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
887be39f75cSAndrew Boyer 	*txq_out = txq;
888a27d9013SAlfredo Cardigliano 
889a27d9013SAlfredo Cardigliano 	return 0;
890a27d9013SAlfredo Cardigliano }
891a27d9013SAlfredo Cardigliano 
89201a6c311SAlfredo Cardigliano static int
ionic_admin_qcq_alloc(struct ionic_lif * lif)89301a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
89401a6c311SAlfredo Cardigliano {
895be39f75cSAndrew Boyer 	uint16_t flags = 0;
896be39f75cSAndrew Boyer 	int err;
89701a6c311SAlfredo Cardigliano 
8984ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8994ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
900be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
9018ec5ad7fSAndrew Boyer 		rte_socket_id(),
9024ad56b7aSAndrew Boyer 		0,
9034ad56b7aSAndrew Boyer 		"admin",
9044ad56b7aSAndrew Boyer 		flags,
90501a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
906d5850081SAndrew Boyer 		1,
90701a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
90801a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
90901a6c311SAlfredo Cardigliano 		0,
910be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
91127b942c8SAlfredo Cardigliano 	if (err)
91227b942c8SAlfredo Cardigliano 		return err;
91301a6c311SAlfredo Cardigliano 
91427b942c8SAlfredo Cardigliano 	return 0;
91527b942c8SAlfredo Cardigliano }
91627b942c8SAlfredo Cardigliano 
91727b942c8SAlfredo Cardigliano static int
ionic_notify_qcq_alloc(struct ionic_lif * lif)91827b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
91927b942c8SAlfredo Cardigliano {
920be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
9214c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
922be39f75cSAndrew Boyer 	uint16_t flags = 0;
923be39f75cSAndrew Boyer 	int err;
92427b942c8SAlfredo Cardigliano 
9254ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
9264ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
927be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
9288ec5ad7fSAndrew Boyer 		rte_socket_id(),
9294ad56b7aSAndrew Boyer 		0,
9304ad56b7aSAndrew Boyer 		"notify",
93127b942c8SAlfredo Cardigliano 		flags,
93227b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
933d5850081SAndrew Boyer 		1,
93427b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
93527b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
93627b942c8SAlfredo Cardigliano 		0,
937be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
93801a6c311SAlfredo Cardigliano 	if (err)
93901a6c311SAlfredo Cardigliano 		return err;
94001a6c311SAlfredo Cardigliano 
9414c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
9424c8f8d57SAndrew Boyer 	if (err) {
943be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
9444c8f8d57SAndrew Boyer 		return err;
9454c8f8d57SAndrew Boyer 	}
9464c8f8d57SAndrew Boyer 
9474c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
9484c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
9494c8f8d57SAndrew Boyer 
9504c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
9514c8f8d57SAndrew Boyer 
95201a6c311SAlfredo Cardigliano 	return 0;
95301a6c311SAlfredo Cardigliano }
95401a6c311SAlfredo Cardigliano 
955c5d15850SAndrew Boyer static void
ionic_lif_queue_identify(struct ionic_lif * lif)956c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
957c5d15850SAndrew Boyer {
958c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
959c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
960c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
961c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
962c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
963c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
964c5d15850SAndrew Boyer 	int err;
965c5d15850SAndrew Boyer 
966c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
967c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
968c5d15850SAndrew Boyer 
969c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
970c5d15850SAndrew Boyer 		switch (qtype) {
971c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
972c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
973c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
974c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
975c5d15850SAndrew Boyer 			break;
976c5d15850SAndrew Boyer 		default:
977c5d15850SAndrew Boyer 			continue;
978c5d15850SAndrew Boyer 		}
979c5d15850SAndrew Boyer 
980c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
981c5d15850SAndrew Boyer 
982fffea1aeSAndrew Boyer 		if (ionic_is_embedded()) {
983fffea1aeSAndrew Boyer 			/* When embedded, FW will always match the driver */
984fffea1aeSAndrew Boyer 			qti->version = ionic_qtype_vers[qtype];
985fffea1aeSAndrew Boyer 			continue;
986fffea1aeSAndrew Boyer 		}
987fffea1aeSAndrew Boyer 
988fffea1aeSAndrew Boyer 		/* On the host, query the FW for info */
989c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
990c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
991c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
992c5d15850SAndrew Boyer 		if (err == -EINVAL) {
993*d026a6b0SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported", qtype);
994c5d15850SAndrew Boyer 			continue;
995c5d15850SAndrew Boyer 		} else if (err == -EIO) {
996*d026a6b0SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW");
997c5d15850SAndrew Boyer 			return;
998c5d15850SAndrew Boyer 		} else if (err) {
999*d026a6b0SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d",
1000c5d15850SAndrew Boyer 				qtype, err);
1001c5d15850SAndrew Boyer 			return;
1002c5d15850SAndrew Boyer 		}
1003c5d15850SAndrew Boyer 
1004c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
1005c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
1006c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
1007c5d15850SAndrew Boyer 
1008c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
1009c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
1010c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
1011c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
1012c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
1013c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
1014c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
1015c5d15850SAndrew Boyer 		qti->sg_desc_stride =
1016c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
1017c5d15850SAndrew Boyer 
1018c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
1019c5d15850SAndrew Boyer 			qtype, qti->version);
1020c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
1021c5d15850SAndrew Boyer 			qtype, qti->supported);
1022c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
1023c5d15850SAndrew Boyer 			qtype, qti->features);
1024c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
1025c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
1026c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
1027c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
1028c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
1029c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
1030c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
1031c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
1032c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
1033c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
1034c5d15850SAndrew Boyer 	}
1035c5d15850SAndrew Boyer }
1036c5d15850SAndrew Boyer 
1037669c8de6SAlfredo Cardigliano int
ionic_lif_alloc(struct ionic_lif * lif)1038669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
1039669c8de6SAlfredo Cardigliano {
1040c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
1041669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
104201a6c311SAlfredo Cardigliano 	int err;
1043669c8de6SAlfredo Cardigliano 
10444ae96cb8SAndrew Boyer 	/*
10454ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
10464ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
10474ae96cb8SAndrew Boyer 	 */
10484ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
10494ae96cb8SAndrew Boyer 
10504ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
1051669c8de6SAlfredo Cardigliano 
1052c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
1053c5d15850SAndrew Boyer 
105456117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
105556117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
105656117636SAndrew Boyer 		return -ENXIO;
105756117636SAndrew Boyer 	}
105856117636SAndrew Boyer 
10599de21005SAndrew Boyer 	if (adapter->q_in_cmb) {
10609de21005SAndrew Boyer 		if (adapter->bars.num_bars >= 3 &&
10619de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 &&
10629de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) {
10639de21005SAndrew Boyer 			IONIC_PRINT(INFO, "%s enabled on %s",
10649de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10659de21005SAndrew Boyer 			lif->state |= IONIC_LIF_F_Q_IN_CMB;
10669de21005SAndrew Boyer 		} else {
10679de21005SAndrew Boyer 			IONIC_PRINT(ERR, "%s not supported on %s, disabled",
10689de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10699de21005SAndrew Boyer 		}
10709de21005SAndrew Boyer 	}
10719de21005SAndrew Boyer 
1072669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
1073669c8de6SAlfredo Cardigliano 
107401a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
107501a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
107601a6c311SAlfredo Cardigliano 
107784cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
1078c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
1079c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1080c67719e1SAlfredo Cardigliano 		return -ENOMEM;
1081c67719e1SAlfredo Cardigliano 	}
1082c67719e1SAlfredo Cardigliano 
1083c5d0bb79SAndrew Boyer 	lif->txqcqs = rte_calloc_socket("ionic",
1084c663c7ecSAndrew Boyer 				adapter->max_ntxqs_per_lif,
1085c5d0bb79SAndrew Boyer 				sizeof(*lif->txqcqs),
1086c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1087a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
1088a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1089a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1090a27d9013SAlfredo Cardigliano 	}
1091a27d9013SAlfredo Cardigliano 
1092c5d0bb79SAndrew Boyer 	lif->rxqcqs = rte_calloc_socket("ionic",
1093c663c7ecSAndrew Boyer 				adapter->max_nrxqs_per_lif,
1094c5d0bb79SAndrew Boyer 				sizeof(*lif->rxqcqs),
1095c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1096a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
1097a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1098a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1099a27d9013SAlfredo Cardigliano 	}
1100a27d9013SAlfredo Cardigliano 
110127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
110227b942c8SAlfredo Cardigliano 
110327b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
110427b942c8SAlfredo Cardigliano 	if (err) {
110527b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
110627b942c8SAlfredo Cardigliano 		return err;
110727b942c8SAlfredo Cardigliano 	}
110827b942c8SAlfredo Cardigliano 
110927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
111027b942c8SAlfredo Cardigliano 
111101a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
111201a6c311SAlfredo Cardigliano 	if (err) {
111301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
111401a6c311SAlfredo Cardigliano 		return err;
111501a6c311SAlfredo Cardigliano 	}
111601a6c311SAlfredo Cardigliano 
111701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
111801a6c311SAlfredo Cardigliano 
1119924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1120669c8de6SAlfredo Cardigliano 
1121669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1122669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1123669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1124669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1125669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1126669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1127669c8de6SAlfredo Cardigliano 	}
1128669c8de6SAlfredo Cardigliano 
1129669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1130669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1131669c8de6SAlfredo Cardigliano 
1132669c8de6SAlfredo Cardigliano 	return 0;
1133669c8de6SAlfredo Cardigliano }
1134669c8de6SAlfredo Cardigliano 
1135669c8de6SAlfredo Cardigliano void
ionic_lif_free(struct ionic_lif * lif)1136669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1137669c8de6SAlfredo Cardigliano {
113827b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1139be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
114027b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
114127b942c8SAlfredo Cardigliano 	}
114227b942c8SAlfredo Cardigliano 
114301a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1144be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
114501a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
114601a6c311SAlfredo Cardigliano 	}
114701a6c311SAlfredo Cardigliano 
1148a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1149a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1150a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1151a27d9013SAlfredo Cardigliano 	}
1152a27d9013SAlfredo Cardigliano 
1153a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1154a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1155a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1156a27d9013SAlfredo Cardigliano 	}
1157a27d9013SAlfredo Cardigliano 
1158669c8de6SAlfredo Cardigliano 	if (lif->info) {
1159669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1160669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1161669c8de6SAlfredo Cardigliano 	}
1162669c8de6SAlfredo Cardigliano }
1163669c8de6SAlfredo Cardigliano 
1164175e4e7eSAndrew Boyer void
ionic_lif_free_queues(struct ionic_lif * lif)1165175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1166175e4e7eSAndrew Boyer {
1167175e4e7eSAndrew Boyer 	uint32_t i;
1168175e4e7eSAndrew Boyer 
1169175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
11707483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1171175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1172175e4e7eSAndrew Boyer 	}
1173175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
11747483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1175175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1176175e4e7eSAndrew Boyer 	}
1177175e4e7eSAndrew Boyer }
1178175e4e7eSAndrew Boyer 
117922e7171bSAlfredo Cardigliano int
ionic_lif_rss_config(struct ionic_lif * lif,const uint16_t types,const uint8_t * key,const uint32_t * indir)118022e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
118122e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
118222e7171bSAlfredo Cardigliano {
118309f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
118422e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
118522e7171bSAlfredo Cardigliano 		.pending_work = true,
118622e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
118722e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
118822e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
118909f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
119009f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
119122e7171bSAlfredo Cardigliano 		},
119222e7171bSAlfredo Cardigliano 	};
119322e7171bSAlfredo Cardigliano 	unsigned int i;
119409f806e9SAndrew Boyer 	uint16_t tbl_sz =
119509f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
119622e7171bSAlfredo Cardigliano 
119722e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
119822e7171bSAlfredo Cardigliano 
119922e7171bSAlfredo Cardigliano 	lif->rss_types = types;
120022e7171bSAlfredo Cardigliano 
120122e7171bSAlfredo Cardigliano 	if (key)
120222e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
120322e7171bSAlfredo Cardigliano 
120422e7171bSAlfredo Cardigliano 	if (indir)
120509f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
120622e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
120722e7171bSAlfredo Cardigliano 
120822e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
120922e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
121022e7171bSAlfredo Cardigliano 
121122e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
121222e7171bSAlfredo Cardigliano }
121322e7171bSAlfredo Cardigliano 
121422e7171bSAlfredo Cardigliano static int
ionic_lif_rss_setup(struct ionic_lif * lif)121522e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
121622e7171bSAlfredo Cardigliano {
121709f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
121822e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
121922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
122022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
122122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
122222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
122322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
122422e7171bSAlfredo Cardigliano 	};
122522e7171bSAlfredo Cardigliano 	uint32_t i;
122609f806e9SAndrew Boyer 	uint16_t tbl_sz =
122709f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
122822e7171bSAlfredo Cardigliano 
122922e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
123022e7171bSAlfredo Cardigliano 
12313d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
123222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
12333d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
12343d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
12353d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
123622e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
123722e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
123822e7171bSAlfredo Cardigliano 			return -ENOMEM;
123922e7171bSAlfredo Cardigliano 		}
124022e7171bSAlfredo Cardigliano 
124122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
124222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
12433d845eddSAndrew Boyer 	}
12443d845eddSAndrew Boyer 
12453d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
12463d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
124722e7171bSAlfredo Cardigliano 
124822e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
12493d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
125022e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
12513d845eddSAndrew Boyer 	}
125222e7171bSAlfredo Cardigliano 
12533d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
125422e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
125522e7171bSAlfredo Cardigliano }
125622e7171bSAlfredo Cardigliano 
125722e7171bSAlfredo Cardigliano static void
ionic_lif_rss_teardown(struct ionic_lif * lif)125822e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
125922e7171bSAlfredo Cardigliano {
1260fffea1aeSAndrew Boyer 	/* Not needed for embedded applications */
1261fffea1aeSAndrew Boyer 	if (ionic_is_embedded())
1262fffea1aeSAndrew Boyer 		return;
1263fffea1aeSAndrew Boyer 
12641a9afd1fSAndrew Boyer 	if (lif->rss_ind_tbl) {
126522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
126622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
126722e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
126822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
126922e7171bSAlfredo Cardigliano 	}
127022e7171bSAlfredo Cardigliano }
127122e7171bSAlfredo Cardigliano 
1272be39f75cSAndrew Boyer void
ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq * txq)12737bb08900SAndrew Boyer ionic_lif_txq_deinit_nowait(struct ionic_tx_qcq *txq)
1274be39f75cSAndrew Boyer {
12757bb08900SAndrew Boyer 	ionic_qcq_disable_nowait(&txq->qcq, &txq->admin_ctx);
1276e7222f94SAndrew Boyer 
1277be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1278be39f75cSAndrew Boyer }
1279be39f75cSAndrew Boyer 
1280be39f75cSAndrew Boyer void
ionic_lif_txq_stats(struct ionic_tx_qcq * txq)12817bb08900SAndrew Boyer ionic_lif_txq_stats(struct ionic_tx_qcq *txq)
1282be39f75cSAndrew Boyer {
12837bb08900SAndrew Boyer 	struct ionic_tx_stats *stats = &txq->stats;
12847bb08900SAndrew Boyer 
12857bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "TX queue %u pkts %ju tso %ju",
12867bb08900SAndrew Boyer 		txq->qcq.q.index, stats->packets, stats->tso);
12877bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "TX queue %u comps %ju (%ju per)",
12887bb08900SAndrew Boyer 		txq->qcq.q.index, stats->comps,
12897bb08900SAndrew Boyer 		stats->comps ? stats->packets / stats->comps : 0);
12907bb08900SAndrew Boyer }
12917bb08900SAndrew Boyer 
12927bb08900SAndrew Boyer void
ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq * rxq)12937bb08900SAndrew Boyer ionic_lif_rxq_deinit_nowait(struct ionic_rx_qcq *rxq)
12947bb08900SAndrew Boyer {
12957bb08900SAndrew Boyer 	ionic_qcq_disable_nowait(&rxq->qcq, &rxq->admin_ctx);
1296e7222f94SAndrew Boyer 
1297be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1298be39f75cSAndrew Boyer }
1299be39f75cSAndrew Boyer 
13007bb08900SAndrew Boyer void
ionic_lif_rxq_stats(struct ionic_rx_qcq * rxq)13017bb08900SAndrew Boyer ionic_lif_rxq_stats(struct ionic_rx_qcq *rxq)
13027bb08900SAndrew Boyer {
13037bb08900SAndrew Boyer 	struct ionic_rx_stats *stats = &rxq->stats;
13047bb08900SAndrew Boyer 
13057bb08900SAndrew Boyer 	IONIC_PRINT(DEBUG, "RX queue %u pkts %ju mtod %ju",
13067bb08900SAndrew Boyer 		rxq->qcq.q.index, stats->packets, stats->mtods);
13077bb08900SAndrew Boyer }
13087bb08900SAndrew Boyer 
130901a6c311SAlfredo Cardigliano static void
ionic_lif_adminq_deinit(struct ionic_lif * lif)1310be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
131101a6c311SAlfredo Cardigliano {
1312be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
13134c8f8d57SAndrew Boyer }
13144c8f8d57SAndrew Boyer 
13154c8f8d57SAndrew Boyer static void
ionic_lif_notifyq_deinit(struct ionic_lif * lif)13164c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
13174c8f8d57SAndrew Boyer {
1318be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
13194c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
13204c8f8d57SAndrew Boyer 
13214c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
13224c8f8d57SAndrew Boyer 		return;
13234c8f8d57SAndrew Boyer 
13244c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
13254c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
13264c8f8d57SAndrew Boyer 
13274c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1328a27d9013SAlfredo Cardigliano }
1329a27d9013SAlfredo Cardigliano 
133001a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
133101a6c311SAlfredo Cardigliano int
ionic_qcq_service(struct ionic_qcq * qcq,int budget,ionic_cq_cb cb,void * cb_arg)133201a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
133301a6c311SAlfredo Cardigliano 		void *cb_arg)
133401a6c311SAlfredo Cardigliano {
133501a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
133601a6c311SAlfredo Cardigliano 	uint32_t work_done;
133701a6c311SAlfredo Cardigliano 
133801a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
133901a6c311SAlfredo Cardigliano 
134001a6c311SAlfredo Cardigliano 	return work_done;
134101a6c311SAlfredo Cardigliano }
134201a6c311SAlfredo Cardigliano 
134327b942c8SAlfredo Cardigliano static void
ionic_link_status_check(struct ionic_lif * lif)134427b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
134527b942c8SAlfredo Cardigliano {
134627b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
134727b942c8SAlfredo Cardigliano 	bool link_up;
134827b942c8SAlfredo Cardigliano 
134927b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
135027b942c8SAlfredo Cardigliano 
135127b942c8SAlfredo Cardigliano 	if (!lif->info)
135227b942c8SAlfredo Cardigliano 		return;
135327b942c8SAlfredo Cardigliano 
135427b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
135527b942c8SAlfredo Cardigliano 
135627b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
135727b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
135827b942c8SAlfredo Cardigliano 		return;
135927b942c8SAlfredo Cardigliano 
136027b942c8SAlfredo Cardigliano 	if (link_up) {
136109f806e9SAndrew Boyer 		adapter->link_speed =
136209f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1363be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1364be63459eSAndrew Boyer 			adapter->link_speed);
136527b942c8SAlfredo Cardigliano 	} else {
136627b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
136727b942c8SAlfredo Cardigliano 	}
136827b942c8SAlfredo Cardigliano 
136927b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1370be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1371be63459eSAndrew Boyer }
1372be63459eSAndrew Boyer 
1373be63459eSAndrew Boyer static void
ionic_lif_handle_fw_down(struct ionic_lif * lif)1374be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1375be63459eSAndrew Boyer {
1376be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1377be63459eSAndrew Boyer 		return;
1378be63459eSAndrew Boyer 
1379be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1380be63459eSAndrew Boyer 
1381be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1382be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1383*d026a6b0SAndrew Boyer 			"Surprise FW stop, stopping %s", lif->name);
1384be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1385be63459eSAndrew Boyer 	}
1386be63459eSAndrew Boyer 
1387be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
138827b942c8SAlfredo Cardigliano }
138927b942c8SAlfredo Cardigliano 
139027b942c8SAlfredo Cardigliano static bool
ionic_notifyq_cb(struct ionic_cq * cq,uint16_t cq_desc_index,void * cb_arg)13914ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
139227b942c8SAlfredo Cardigliano {
139327b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
139427b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
139527b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
139627b942c8SAlfredo Cardigliano 
139727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
139827b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
139927b942c8SAlfredo Cardigliano 
140027b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
140127b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
140227b942c8SAlfredo Cardigliano 		return false;
140327b942c8SAlfredo Cardigliano 
140427b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
140527b942c8SAlfredo Cardigliano 
140627b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
140727b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
140827b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1409be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1410be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1411be63459eSAndrew Boyer 			lif->name,
141227b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
141327b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
141427b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
141527b942c8SAlfredo Cardigliano 
141627b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
141727b942c8SAlfredo Cardigliano 		break;
1418be63459eSAndrew Boyer 
1419be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1420be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1421be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1422be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1423be63459eSAndrew Boyer 			lif->name,
1424be63459eSAndrew Boyer 			cq_desc->event.eid,
1425be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1426be63459eSAndrew Boyer 			cq_desc->reset.state);
1427be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1428be63459eSAndrew Boyer 		break;
1429be63459eSAndrew Boyer 
143027b942c8SAlfredo Cardigliano 	default:
143127b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
143227b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
143327b942c8SAlfredo Cardigliano 		break;
143427b942c8SAlfredo Cardigliano 	}
143527b942c8SAlfredo Cardigliano 
143627b942c8SAlfredo Cardigliano 	return true;
143727b942c8SAlfredo Cardigliano }
143827b942c8SAlfredo Cardigliano 
143927b942c8SAlfredo Cardigliano int
ionic_notifyq_handler(struct ionic_lif * lif,int budget)144027b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
144127b942c8SAlfredo Cardigliano {
144227b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1443be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
144427b942c8SAlfredo Cardigliano 	uint32_t work_done;
144527b942c8SAlfredo Cardigliano 
1446be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
144727b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
144827b942c8SAlfredo Cardigliano 		return -1;
144927b942c8SAlfredo Cardigliano 	}
145027b942c8SAlfredo Cardigliano 
1451be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
145227b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
145327b942c8SAlfredo Cardigliano 
1454be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1455be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
145627b942c8SAlfredo Cardigliano 
145727b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
145827b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
145927b942c8SAlfredo Cardigliano 
1460be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
146127b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
146227b942c8SAlfredo Cardigliano 
1463be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
146427b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
146527b942c8SAlfredo Cardigliano 
146627b942c8SAlfredo Cardigliano 	return 0;
146727b942c8SAlfredo Cardigliano }
146827b942c8SAlfredo Cardigliano 
146901a6c311SAlfredo Cardigliano static int
ionic_lif_adminq_init(struct ionic_lif * lif)147001a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
147101a6c311SAlfredo Cardigliano {
147201a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1473be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1474be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
147501a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
147613133a28SAndrew Boyer 	uint32_t retries = 5;
147701a6c311SAlfredo Cardigliano 	int err;
147801a6c311SAlfredo Cardigliano 
147913133a28SAndrew Boyer retry_adminq_init:
1480be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
148101a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
148213133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
148313133a28SAndrew Boyer 		retries--;
148413133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
148513133a28SAndrew Boyer 		goto retry_adminq_init;
148613133a28SAndrew Boyer 	}
148701a6c311SAlfredo Cardigliano 	if (err)
148801a6c311SAlfredo Cardigliano 		return err;
148901a6c311SAlfredo Cardigliano 
149001a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
149101a6c311SAlfredo Cardigliano 
149201a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
149309f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
149401a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
149501a6c311SAlfredo Cardigliano 
149601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
149701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
149801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
149901a6c311SAlfredo Cardigliano 
1500be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
150101a6c311SAlfredo Cardigliano 
150201a6c311SAlfredo Cardigliano 	return 0;
150301a6c311SAlfredo Cardigliano }
150401a6c311SAlfredo Cardigliano 
150527b942c8SAlfredo Cardigliano static int
ionic_lif_notifyq_init(struct ionic_lif * lif)150627b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
150727b942c8SAlfredo Cardigliano {
150827b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1509be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1510be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
15110a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
151227b942c8SAlfredo Cardigliano 	int err;
151327b942c8SAlfredo Cardigliano 
151427b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
151527b942c8SAlfredo Cardigliano 		.pending_work = true,
151627b942c8SAlfredo Cardigliano 		.cmd.q_init = {
151727b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
151827b942c8SAlfredo Cardigliano 			.type = q->type,
1519c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
152009f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
15210a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
152227b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
152309f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
152427b942c8SAlfredo Cardigliano 		}
152527b942c8SAlfredo Cardigliano 	};
152627b942c8SAlfredo Cardigliano 
15270a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
15280a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
15290a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
15300a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
15310a00bdafSAndrew Boyer 	}
15320a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
15330a00bdafSAndrew Boyer 
153409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
153509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
153627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
153727b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15384ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
153927b942c8SAlfredo Cardigliano 
154027b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
154127b942c8SAlfredo Cardigliano 	if (err)
154227b942c8SAlfredo Cardigliano 		return err;
154327b942c8SAlfredo Cardigliano 
154427b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
154509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
154627b942c8SAlfredo Cardigliano 	q->db = NULL;
154727b942c8SAlfredo Cardigliano 
154827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
154927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
155027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
155127b942c8SAlfredo Cardigliano 
1552be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
155327b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
155427b942c8SAlfredo Cardigliano 
1555be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
155627b942c8SAlfredo Cardigliano 
155727b942c8SAlfredo Cardigliano 	return 0;
155827b942c8SAlfredo Cardigliano }
155927b942c8SAlfredo Cardigliano 
1560669c8de6SAlfredo Cardigliano int
ionic_lif_set_features(struct ionic_lif * lif)1561598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1562598f6726SAlfredo Cardigliano {
1563598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1564598f6726SAlfredo Cardigliano 		.pending_work = true,
1565598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1566598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1567598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
156809f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1569598f6726SAlfredo Cardigliano 		},
1570598f6726SAlfredo Cardigliano 	};
1571598f6726SAlfredo Cardigliano 	int err;
1572598f6726SAlfredo Cardigliano 
1573598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1574598f6726SAlfredo Cardigliano 	if (err)
1575598f6726SAlfredo Cardigliano 		return err;
1576598f6726SAlfredo Cardigliano 
157709f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1578598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1579598f6726SAlfredo Cardigliano 
1580598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1581598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1582598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1583598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1584598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1585598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1586598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1587598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1588598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1589598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1590598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1591598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1592598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1593598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1594598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1595598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1596598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1597598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1598598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1599598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1600598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1601598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1602598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1603598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1604598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1605598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1606598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1607598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1608598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1609598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1610598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1611598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1612598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1613598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1614598f6726SAlfredo Cardigliano 
1615598f6726SAlfredo Cardigliano 	return 0;
1616598f6726SAlfredo Cardigliano }
1617598f6726SAlfredo Cardigliano 
1618a27d9013SAlfredo Cardigliano int
ionic_lif_txq_init_nowait(struct ionic_tx_qcq * txq)16190033e92fSAndrew Boyer ionic_lif_txq_init_nowait(struct ionic_tx_qcq *txq)
1620a27d9013SAlfredo Cardigliano {
1621be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1622a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1623a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1624a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
16250033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &txq->admin_ctx;
16260033e92fSAndrew Boyer 	int err;
16270033e92fSAndrew Boyer 
16280033e92fSAndrew Boyer 	*ctx = (struct ionic_admin_ctx) {
1629a27d9013SAlfredo Cardigliano 		.pending_work = true,
1630a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1631a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1632a27d9013SAlfredo Cardigliano 			.type = q->type,
1633c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
163409f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1635e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
163609f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1637a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
163809f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
163909f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1640a27d9013SAlfredo Cardigliano 		},
1641a27d9013SAlfredo Cardigliano 	};
1642a27d9013SAlfredo Cardigliano 
1643e86a6fccSAndrew Boyer 	if (txq->flags & IONIC_QCQ_F_SG)
16440033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
164590fa040aSNeel Patel 	if (txq->flags & IONIC_QCQ_F_CMB) {
16460033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
16470033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa);
164890fa040aSNeel Patel 	} else {
16490033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa);
165090fa040aSNeel Patel 	}
16519de21005SAndrew Boyer 
165209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
165309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1654a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
16550033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_size);
16560033e92fSAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx->cmd.q_init.ver);
1657a27d9013SAlfredo Cardigliano 
1658e7222f94SAndrew Boyer 	ionic_q_reset(q);
1659e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1660e7222f94SAndrew Boyer 
16610033e92fSAndrew Boyer 	/* Caller responsible for calling ionic_lif_txq_init_done() */
16620033e92fSAndrew Boyer 	err = ionic_adminq_post(lif, ctx);
1663a27d9013SAlfredo Cardigliano 	if (err)
16640033e92fSAndrew Boyer 		ctx->pending_work = false;
1665a27d9013SAlfredo Cardigliano 	return err;
16660033e92fSAndrew Boyer }
1667a27d9013SAlfredo Cardigliano 
16680033e92fSAndrew Boyer void
ionic_lif_txq_init_done(struct ionic_tx_qcq * txq)16690033e92fSAndrew Boyer ionic_lif_txq_init_done(struct ionic_tx_qcq *txq)
16700033e92fSAndrew Boyer {
16710033e92fSAndrew Boyer 	struct ionic_lif *lif = txq->qcq.lif;
16720033e92fSAndrew Boyer 	struct ionic_queue *q = &txq->qcq.q;
16730033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &txq->admin_ctx;
16740033e92fSAndrew Boyer 
16750033e92fSAndrew Boyer 	q->hw_type = ctx->comp.q_init.hw_type;
16760033e92fSAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx->comp.q_init.hw_index);
1677a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1678a27d9013SAlfredo Cardigliano 
1679a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1680a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1681a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1682a27d9013SAlfredo Cardigliano 
1683be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1684a27d9013SAlfredo Cardigliano }
1685a27d9013SAlfredo Cardigliano 
1686a27d9013SAlfredo Cardigliano int
ionic_lif_rxq_init_nowait(struct ionic_rx_qcq * rxq)16870033e92fSAndrew Boyer ionic_lif_rxq_init_nowait(struct ionic_rx_qcq *rxq)
1688a27d9013SAlfredo Cardigliano {
1689be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1690a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1691a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1692a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
16930033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &rxq->admin_ctx;
16940033e92fSAndrew Boyer 	int err;
16950033e92fSAndrew Boyer 
16960033e92fSAndrew Boyer 	*ctx = (struct ionic_admin_ctx) {
1697a27d9013SAlfredo Cardigliano 		.pending_work = true,
1698a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1699a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1700a27d9013SAlfredo Cardigliano 			.type = q->type,
1701c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
170209f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1703e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
170409f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1705a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
170609f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
170709f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1708a27d9013SAlfredo Cardigliano 		},
1709a27d9013SAlfredo Cardigliano 	};
1710a27d9013SAlfredo Cardigliano 
1711e86a6fccSAndrew Boyer 	if (rxq->flags & IONIC_QCQ_F_SG)
17120033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
171390fa040aSNeel Patel 	if (rxq->flags & IONIC_QCQ_F_CMB) {
17140033e92fSAndrew Boyer 		ctx->cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
17150033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->cmb_base_pa);
171690fa040aSNeel Patel 	} else {
17170033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_base = rte_cpu_to_le_64(q->base_pa);
171890fa040aSNeel Patel 	}
17199de21005SAndrew Boyer 
172009f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
172109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1722a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
17230033e92fSAndrew Boyer 		ctx->cmd.q_init.ring_size);
17240033e92fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx->cmd.q_init.ver);
1725a27d9013SAlfredo Cardigliano 
1726e7222f94SAndrew Boyer 	ionic_q_reset(q);
1727e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1728e7222f94SAndrew Boyer 
17290033e92fSAndrew Boyer 	/* Caller responsible for calling ionic_lif_rxq_init_done() */
17300033e92fSAndrew Boyer 	err = ionic_adminq_post(lif, ctx);
1731a27d9013SAlfredo Cardigliano 	if (err)
17320033e92fSAndrew Boyer 		ctx->pending_work = false;
1733a27d9013SAlfredo Cardigliano 	return err;
17340033e92fSAndrew Boyer }
1735a27d9013SAlfredo Cardigliano 
17360033e92fSAndrew Boyer void
ionic_lif_rxq_init_done(struct ionic_rx_qcq * rxq)17370033e92fSAndrew Boyer ionic_lif_rxq_init_done(struct ionic_rx_qcq *rxq)
17380033e92fSAndrew Boyer {
17390033e92fSAndrew Boyer 	struct ionic_lif *lif = rxq->qcq.lif;
17400033e92fSAndrew Boyer 	struct ionic_queue *q = &rxq->qcq.q;
17410033e92fSAndrew Boyer 	struct ionic_admin_ctx *ctx = &rxq->admin_ctx;
17420033e92fSAndrew Boyer 
17430033e92fSAndrew Boyer 	q->hw_type = ctx->comp.q_init.hw_type;
17440033e92fSAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx->comp.q_init.hw_index);
1745a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1746a27d9013SAlfredo Cardigliano 
1747be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1748a27d9013SAlfredo Cardigliano 
1749a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1750a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1751a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1752a27d9013SAlfredo Cardigliano }
1753a27d9013SAlfredo Cardigliano 
1754598f6726SAlfredo Cardigliano static int
ionic_station_set(struct ionic_lif * lif)1755598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1756598f6726SAlfredo Cardigliano {
1757598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1758598f6726SAlfredo Cardigliano 		.pending_work = true,
1759598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1760598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1761598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1762598f6726SAlfredo Cardigliano 		},
1763598f6726SAlfredo Cardigliano 	};
1764598f6726SAlfredo Cardigliano 	int err;
1765598f6726SAlfredo Cardigliano 
1766598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1767598f6726SAlfredo Cardigliano 
1768598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1769598f6726SAlfredo Cardigliano 	if (err)
1770598f6726SAlfredo Cardigliano 		return err;
1771598f6726SAlfredo Cardigliano 
1772598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1773598f6726SAlfredo Cardigliano 
1774598f6726SAlfredo Cardigliano 	return 0;
1775598f6726SAlfredo Cardigliano }
1776598f6726SAlfredo Cardigliano 
1777598f6726SAlfredo Cardigliano static void
ionic_lif_set_name(struct ionic_lif * lif)1778598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1779598f6726SAlfredo Cardigliano {
1780598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1781598f6726SAlfredo Cardigliano 		.pending_work = true,
1782598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1783598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1784598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1785598f6726SAlfredo Cardigliano 		},
1786598f6726SAlfredo Cardigliano 	};
1787598f6726SAlfredo Cardigliano 
1788fffea1aeSAndrew Boyer 	/* Not needed for embedded applications */
1789fffea1aeSAndrew Boyer 	if (ionic_is_embedded())
1790fffea1aeSAndrew Boyer 		return;
1791fffea1aeSAndrew Boyer 
17924ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
17934ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1794598f6726SAlfredo Cardigliano 
1795598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1796598f6726SAlfredo Cardigliano }
1797598f6726SAlfredo Cardigliano 
1798598f6726SAlfredo Cardigliano int
ionic_lif_init(struct ionic_lif * lif)1799669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1800669c8de6SAlfredo Cardigliano {
1801669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1802656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
180313133a28SAndrew Boyer 	uint32_t retries = 5;
1804669c8de6SAlfredo Cardigliano 	int err;
1805669c8de6SAlfredo Cardigliano 
18063cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
18073cdfd905SAlfredo Cardigliano 
180813133a28SAndrew Boyer retry_lif_init:
180900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1810669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
181113133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
181213133a28SAndrew Boyer 		retries--;
181313133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
181413133a28SAndrew Boyer 		goto retry_lif_init;
181513133a28SAndrew Boyer 	}
1816669c8de6SAlfredo Cardigliano 	if (err)
1817669c8de6SAlfredo Cardigliano 		return err;
1818669c8de6SAlfredo Cardigliano 
1819656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1820656bfc9aSAndrew Boyer 
182109f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1822669c8de6SAlfredo Cardigliano 
182301a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
182401a6c311SAlfredo Cardigliano 	if (err)
182501a6c311SAlfredo Cardigliano 		return err;
182601a6c311SAlfredo Cardigliano 
182727b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
182827b942c8SAlfredo Cardigliano 	if (err)
182927b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
183027b942c8SAlfredo Cardigliano 
183118a44465SAndrew Boyer 	/*
183218a44465SAndrew Boyer 	 * Configure initial feature set
183318a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
183418a44465SAndrew Boyer 	 */
183518a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1836598f6726SAlfredo Cardigliano 
1837598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1838598f6726SAlfredo Cardigliano 	if (err)
1839598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1840598f6726SAlfredo Cardigliano 
184154fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1842598f6726SAlfredo Cardigliano 	if (err)
1843598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1844598f6726SAlfredo Cardigliano 
184554fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
184654fe083fSAlfredo Cardigliano 	if (err)
184754fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
184854fe083fSAlfredo Cardigliano 
1849598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1850598f6726SAlfredo Cardigliano 
1851669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1852669c8de6SAlfredo Cardigliano 
1853669c8de6SAlfredo Cardigliano 	return 0;
185427b942c8SAlfredo Cardigliano 
185554fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
185654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
185754fe083fSAlfredo Cardigliano 
1858598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
18594c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1860598f6726SAlfredo Cardigliano 
186127b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1862be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
186327b942c8SAlfredo Cardigliano 
186427b942c8SAlfredo Cardigliano 	return err;
1865669c8de6SAlfredo Cardigliano }
1866669c8de6SAlfredo Cardigliano 
1867669c8de6SAlfredo Cardigliano void
ionic_lif_deinit(struct ionic_lif * lif)1868669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1869669c8de6SAlfredo Cardigliano {
1870669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1871669c8de6SAlfredo Cardigliano 		return;
1872669c8de6SAlfredo Cardigliano 
187354fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
187422e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
18754c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1876be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
187701a6c311SAlfredo Cardigliano 
1878669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1879669c8de6SAlfredo Cardigliano }
1880669c8de6SAlfredo Cardigliano 
188118a44465SAndrew Boyer void
ionic_lif_configure_vlan_offload(struct ionic_lif * lif,int mask)188218a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
188318a44465SAndrew Boyer {
188418a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
188518a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
188618a44465SAndrew Boyer 
188718a44465SAndrew Boyer 	/*
188818a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1889295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
189018a44465SAndrew Boyer 	 */
1891295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
189218a44465SAndrew Boyer 
1893295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1894295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
189518a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
189618a44465SAndrew Boyer 		else
189718a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
189818a44465SAndrew Boyer 	}
189918a44465SAndrew Boyer }
190018a44465SAndrew Boyer 
190118a44465SAndrew Boyer void
ionic_lif_configure_rx_sg_offload(struct ionic_lif * lif)1902e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif)
1903e86a6fccSAndrew Boyer {
1904e86a6fccSAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
1905e86a6fccSAndrew Boyer 
1906e86a6fccSAndrew Boyer 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
1907e86a6fccSAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
1908e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
1909e86a6fccSAndrew Boyer 	} else {
1910e86a6fccSAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
1911e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
1912e86a6fccSAndrew Boyer 	}
1913e86a6fccSAndrew Boyer }
1914e86a6fccSAndrew Boyer 
1915e86a6fccSAndrew Boyer void
ionic_lif_configure(struct ionic_lif * lif)1916598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1917598f6726SAlfredo Cardigliano {
191818a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
191918a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
192022e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
192109f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
192222e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
192309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
192422e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
192509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
192622e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
192722e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
192822e7171bSAlfredo Cardigliano 
1929598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1930598f6726SAlfredo Cardigliano 
193122e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
193222e7171bSAlfredo Cardigliano 		lif->port_id);
193322e7171bSAlfredo Cardigliano 
193422e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
193522e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
193622e7171bSAlfredo Cardigliano 
193722e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
193822e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
193922e7171bSAlfredo Cardigliano 
194022e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
194122e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1942a27d9013SAlfredo Cardigliano 
194318a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
194418a44465SAndrew Boyer 
194518a44465SAndrew Boyer 	/*
194618a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
194718a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1948295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
194918a44465SAndrew Boyer 	 */
195018a44465SAndrew Boyer 
195118a44465SAndrew Boyer 	/* RX per-port */
195218a44465SAndrew Boyer 
1953295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1954295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1955295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
195618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
195718a44465SAndrew Boyer 	else
195818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
195918a44465SAndrew Boyer 
1960e86a6fccSAndrew Boyer 	/*
1961e86a6fccSAndrew Boyer 	 * NB: RX_SG may be enabled later during rx_queue_setup() if
1962e86a6fccSAndrew Boyer 	 * required by the mbuf/mtu configuration
1963e86a6fccSAndrew Boyer 	 */
1964e86a6fccSAndrew Boyer 	ionic_lif_configure_rx_sg_offload(lif);
196518a44465SAndrew Boyer 
196618a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1967295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
196818a44465SAndrew Boyer 
196918a44465SAndrew Boyer 	/* TX per-port */
197018a44465SAndrew Boyer 
1971295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1972295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1973295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1974295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1975295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
197618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
197718a44465SAndrew Boyer 	else
197818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
197918a44465SAndrew Boyer 
1980295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
198118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
198218a44465SAndrew Boyer 	else
198318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
198418a44465SAndrew Boyer 
1985295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
198618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
198718a44465SAndrew Boyer 	else
198818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
198918a44465SAndrew Boyer 
1990295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
199118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
199218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
199318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
199418a44465SAndrew Boyer 	} else {
199518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
199618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
199718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
199818a44465SAndrew Boyer 	}
1999598f6726SAlfredo Cardigliano }
2000598f6726SAlfredo Cardigliano 
2001598f6726SAlfredo Cardigliano int
ionic_lif_start(struct ionic_lif * lif)2002598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
2003598f6726SAlfredo Cardigliano {
20040033e92fSAndrew Boyer 	struct rte_eth_dev *dev = lif->eth_dev;
20050578335aSAndrew Boyer 	uint32_t rx_mode;
20060033e92fSAndrew Boyer 	uint32_t i, j, chunk;
2007a27d9013SAlfredo Cardigliano 	int err;
20080033e92fSAndrew Boyer 	bool fatal = false;
2009598f6726SAlfredo Cardigliano 
201022e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
201122e7171bSAlfredo Cardigliano 	if (err)
201222e7171bSAlfredo Cardigliano 		return err;
201322e7171bSAlfredo Cardigliano 
20140578335aSAndrew Boyer 	if (!lif->rx_mode) {
20150578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
20160578335aSAndrew Boyer 			lif->name);
2017598f6726SAlfredo Cardigliano 
20180578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
2019598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
2020598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
2021598f6726SAlfredo Cardigliano 
2022598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
20230578335aSAndrew Boyer 	}
2024598f6726SAlfredo Cardigliano 
2025a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
2026a27d9013SAlfredo Cardigliano 		"on port %u",
2027a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
2028a27d9013SAlfredo Cardigliano 
20290033e92fSAndrew Boyer 	chunk = ionic_adminq_space_avail(lif);
2030a27d9013SAlfredo Cardigliano 
20310033e92fSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i += chunk) {
20320033e92fSAndrew Boyer 		if (lif->rxqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) {
20330033e92fSAndrew Boyer 			IONIC_PRINT(DEBUG, "Rx queue start deferred");
20340033e92fSAndrew Boyer 			break;
20350033e92fSAndrew Boyer 		}
20360033e92fSAndrew Boyer 
20370033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) {
20380033e92fSAndrew Boyer 			err = ionic_dev_rx_queue_start_firsthalf(dev, i + j);
20390033e92fSAndrew Boyer 			if (err) {
20400033e92fSAndrew Boyer 				fatal = true;
20410033e92fSAndrew Boyer 				break;
20420033e92fSAndrew Boyer 			}
20430033e92fSAndrew Boyer 		}
20440033e92fSAndrew Boyer 
20450033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->nrxqcqs; j++) {
20460033e92fSAndrew Boyer 			/* Commands that failed to post return immediately */
20470033e92fSAndrew Boyer 			err = ionic_dev_rx_queue_start_secondhalf(dev, i + j);
2048a27d9013SAlfredo Cardigliano 			if (err)
20490033e92fSAndrew Boyer 				/* Don't break */
20500033e92fSAndrew Boyer 				fatal = true;
20510033e92fSAndrew Boyer 		}
20520033e92fSAndrew Boyer 	}
20530033e92fSAndrew Boyer 	if (fatal)
20540033e92fSAndrew Boyer 		return -EIO;
20550033e92fSAndrew Boyer 
20560033e92fSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i += chunk) {
20570033e92fSAndrew Boyer 		if (lif->txqcqs[0]->flags & IONIC_QCQ_F_DEFERRED) {
20580033e92fSAndrew Boyer 			IONIC_PRINT(DEBUG, "Tx queue start deferred");
20590033e92fSAndrew Boyer 			break;
20600033e92fSAndrew Boyer 		}
20610033e92fSAndrew Boyer 
20620033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) {
20630033e92fSAndrew Boyer 			err = ionic_dev_tx_queue_start_firsthalf(dev, i + j);
20640033e92fSAndrew Boyer 			if (err) {
20650033e92fSAndrew Boyer 				fatal = true;
20660033e92fSAndrew Boyer 				break;
2067a27d9013SAlfredo Cardigliano 			}
2068a27d9013SAlfredo Cardigliano 		}
2069a27d9013SAlfredo Cardigliano 
20700033e92fSAndrew Boyer 		for (j = 0; j < chunk && i + j < lif->ntxqcqs; j++) {
20710033e92fSAndrew Boyer 			/* Commands that failed to post return immediately */
20720033e92fSAndrew Boyer 			err = ionic_dev_tx_queue_start_secondhalf(dev, i + j);
2073a27d9013SAlfredo Cardigliano 			if (err)
20740033e92fSAndrew Boyer 				/* Don't break */
20750033e92fSAndrew Boyer 				fatal = true;
2076a27d9013SAlfredo Cardigliano 		}
2077a27d9013SAlfredo Cardigliano 	}
20780033e92fSAndrew Boyer 	if (fatal)
20790033e92fSAndrew Boyer 		return -EIO;
2080a27d9013SAlfredo Cardigliano 
2081598f6726SAlfredo Cardigliano 	/* Carrier ON here */
2082be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
2083be63459eSAndrew Boyer 
2084be63459eSAndrew Boyer 	ionic_link_status_check(lif);
2085598f6726SAlfredo Cardigliano 
2086598f6726SAlfredo Cardigliano 	return 0;
2087598f6726SAlfredo Cardigliano }
2088598f6726SAlfredo Cardigliano 
2089598f6726SAlfredo Cardigliano int
ionic_lif_identify(struct ionic_adapter * adapter)2090669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
2091669c8de6SAlfredo Cardigliano {
2092669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
2093669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
209409f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
209576276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
209676276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
209776276d71SAndrew Boyer 	uint32_t i, nwords;
2098669c8de6SAlfredo Cardigliano 	int err;
2099669c8de6SAlfredo Cardigliano 
2100669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
2101669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
2102669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
2103669c8de6SAlfredo Cardigliano 	if (err)
2104669c8de6SAlfredo Cardigliano 		return (err);
2105669c8de6SAlfredo Cardigliano 
2106669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
2107669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
2108669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
2109669c8de6SAlfredo Cardigliano 
2110669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
211109f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
2112669c8de6SAlfredo Cardigliano 
2113669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
211409f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
2115669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
211609f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
2117669c8de6SAlfredo Cardigliano 
2118669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
211909f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
2120669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
212109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
2122669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
212309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
2124669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
212509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
2126669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
212709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
2128669c8de6SAlfredo Cardigliano 
2129669c8de6SAlfredo Cardigliano 	return 0;
2130669c8de6SAlfredo Cardigliano }
2131669c8de6SAlfredo Cardigliano 
2132669c8de6SAlfredo Cardigliano int
ionic_lifs_size(struct ionic_adapter * adapter)2133669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
2134669c8de6SAlfredo Cardigliano {
2135669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
213609f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
213709f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
2138669c8de6SAlfredo Cardigliano 
2139669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
214009f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
2141669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
214209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
2143669c8de6SAlfredo Cardigliano 
214400b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
2145669c8de6SAlfredo Cardigliano 
2146669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
21474ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
21484ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
2149669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
2150669c8de6SAlfredo Cardigliano 		return -ENOSPC;
2151669c8de6SAlfredo Cardigliano 	}
2152669c8de6SAlfredo Cardigliano 
2153669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
2154669c8de6SAlfredo Cardigliano 
2155669c8de6SAlfredo Cardigliano 	return 0;
2156669c8de6SAlfredo Cardigliano }
2157