xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 4b53e9802b6b6040ad5622b1414aaa93d9581d0c)
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
3401a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
3501a6c311SAlfredo Cardigliano {
3601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
374ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
3801a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
3901a6c311SAlfredo Cardigliano 		.pending_work = true,
4001a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4101a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4201a6c311SAlfredo Cardigliano 			.type = q->type,
4309f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4401a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
4501a6c311SAlfredo Cardigliano 		},
4601a6c311SAlfredo Cardigliano 	};
4701a6c311SAlfredo Cardigliano 
4801a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4901a6c311SAlfredo Cardigliano }
5001a6c311SAlfredo Cardigliano 
51be63459eSAndrew Boyer void
52be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
53598f6726SAlfredo Cardigliano {
54a0a99f21SAndrew Boyer 	uint32_t i;
55a0a99f21SAndrew Boyer 
56be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
57598f6726SAlfredo Cardigliano 
58be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
59a0a99f21SAndrew Boyer 
60a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
61be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
62a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
63a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
64a0a99f21SAndrew Boyer 	}
65a0a99f21SAndrew Boyer 
66a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
67be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
68a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
69a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
70a0a99f21SAndrew Boyer 	}
71598f6726SAlfredo Cardigliano }
72598f6726SAlfredo Cardigliano 
73598f6726SAlfredo Cardigliano void
74598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
75598f6726SAlfredo Cardigliano {
76598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
7775f96902SAndrew Boyer 	int err;
78598f6726SAlfredo Cardigliano 
79598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
80598f6726SAlfredo Cardigliano 
8100b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
8275f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
8375f96902SAndrew Boyer 	if (err)
844ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
85598f6726SAlfredo Cardigliano }
86598f6726SAlfredo Cardigliano 
873cdfd905SAlfredo Cardigliano static void
883cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
893cdfd905SAlfredo Cardigliano {
903cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
913cdfd905SAlfredo Cardigliano 	uint32_t i;
923cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
933cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
943cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
953cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
963cdfd905SAlfredo Cardigliano 
973cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
983cdfd905SAlfredo Cardigliano 
993cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1003cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1013cdfd905SAlfredo Cardigliano 			lif->port_id);
1023cdfd905SAlfredo Cardigliano 		return;
1033cdfd905SAlfredo Cardigliano 	}
1043cdfd905SAlfredo Cardigliano 
1053cdfd905SAlfredo Cardigliano 	/* RX */
1063cdfd905SAlfredo Cardigliano 
1073cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1083cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1093cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1103cdfd905SAlfredo Cardigliano 
1113cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1123cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1133cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1143cdfd905SAlfredo Cardigliano 
1153cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
116be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
11726cc5dc2SAndrew Boyer 		stats->ierrors +=
1183cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1193cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1203cdfd905SAlfredo Cardigliano 	}
1213cdfd905SAlfredo Cardigliano 
1223cdfd905SAlfredo Cardigliano 	stats->imissed +=
1233cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1243cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1253cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1263cdfd905SAlfredo Cardigliano 
12726cc5dc2SAndrew Boyer 	stats->ierrors +=
1283cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1293cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1303cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1313cdfd905SAlfredo Cardigliano 
1323cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
133be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1343cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1353cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1363cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1373cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1383cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1393cdfd905SAlfredo Cardigliano 	}
1403cdfd905SAlfredo Cardigliano 
1413cdfd905SAlfredo Cardigliano 	/* TX */
1423cdfd905SAlfredo Cardigliano 
1433cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1443cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1453cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1463cdfd905SAlfredo Cardigliano 
1473cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1483cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1493cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1503cdfd905SAlfredo Cardigliano 
1513cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
152be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1533cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1543cdfd905SAlfredo Cardigliano 	}
1553cdfd905SAlfredo Cardigliano 
1563cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1573cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1583cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1593cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1603cdfd905SAlfredo Cardigliano 
1613cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1623cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1633cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1643cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1653cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1663cdfd905SAlfredo Cardigliano 
1673cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
168be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1693cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1703cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1713cdfd905SAlfredo Cardigliano 	}
1723cdfd905SAlfredo Cardigliano }
1733cdfd905SAlfredo Cardigliano 
1743cdfd905SAlfredo Cardigliano void
1753cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1763cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1773cdfd905SAlfredo Cardigliano {
1783cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1793cdfd905SAlfredo Cardigliano 
1803cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1813cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1823cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1833cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1843cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1853cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1863cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1873cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1883cdfd905SAlfredo Cardigliano }
1893cdfd905SAlfredo Cardigliano 
1903cdfd905SAlfredo Cardigliano void
1913cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
1923cdfd905SAlfredo Cardigliano {
1933cdfd905SAlfredo Cardigliano 	uint32_t i;
1943cdfd905SAlfredo Cardigliano 
1953cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
196be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
1973cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
198be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
1993cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2003cdfd905SAlfredo Cardigliano 	}
2013cdfd905SAlfredo Cardigliano 
2023cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2033cdfd905SAlfredo Cardigliano }
2043cdfd905SAlfredo Cardigliano 
2053cdfd905SAlfredo Cardigliano void
2063cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2073cdfd905SAlfredo Cardigliano {
2083cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2093cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2103cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2113cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2123cdfd905SAlfredo Cardigliano 
2133cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2143cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2153cdfd905SAlfredo Cardigliano }
2163cdfd905SAlfredo Cardigliano 
2173cdfd905SAlfredo Cardigliano void
2183cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2193cdfd905SAlfredo Cardigliano {
2203cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2213cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2223cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2233cdfd905SAlfredo Cardigliano 
2243cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2253cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2263cdfd905SAlfredo Cardigliano }
2273cdfd905SAlfredo Cardigliano 
228598f6726SAlfredo Cardigliano static int
22954fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
230598f6726SAlfredo Cardigliano {
23154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
23254fe083fSAlfredo Cardigliano 		.pending_work = true,
23354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
23454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
23509f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
23654fe083fSAlfredo Cardigliano 		},
23754fe083fSAlfredo Cardigliano 	};
23854fe083fSAlfredo Cardigliano 	int err;
23954fe083fSAlfredo Cardigliano 
24054fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
24154fe083fSAlfredo Cardigliano 
24254fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
24354fe083fSAlfredo Cardigliano 	if (err)
24454fe083fSAlfredo Cardigliano 		return err;
24554fe083fSAlfredo Cardigliano 
24654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
24709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
24854fe083fSAlfredo Cardigliano 
24954fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25054fe083fSAlfredo Cardigliano }
25154fe083fSAlfredo Cardigliano 
25254fe083fSAlfredo Cardigliano static int
25354fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
25454fe083fSAlfredo Cardigliano {
25554fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25654fe083fSAlfredo Cardigliano 		.pending_work = true,
25754fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
25854fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
25954fe083fSAlfredo Cardigliano 		},
26054fe083fSAlfredo Cardigliano 	};
26154fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
26254fe083fSAlfredo Cardigliano 	int err;
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
26554fe083fSAlfredo Cardigliano 
26654fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
26754fe083fSAlfredo Cardigliano 
26854fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
26954fe083fSAlfredo Cardigliano 	if (!f) {
27054fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
27154fe083fSAlfredo Cardigliano 		return -ENOENT;
27254fe083fSAlfredo Cardigliano 	}
27354fe083fSAlfredo Cardigliano 
27409f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
27554fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
27654fe083fSAlfredo Cardigliano 
27754fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
27854fe083fSAlfredo Cardigliano 
27954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28054fe083fSAlfredo Cardigliano 	if (err)
28154fe083fSAlfredo Cardigliano 		return err;
28254fe083fSAlfredo Cardigliano 
28354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
28409f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
285598f6726SAlfredo Cardigliano 
286598f6726SAlfredo Cardigliano 	return 0;
287598f6726SAlfredo Cardigliano }
288598f6726SAlfredo Cardigliano 
28954fe083fSAlfredo Cardigliano int
29054fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
29154fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
29254fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
293598f6726SAlfredo Cardigliano {
29454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
29554fe083fSAlfredo Cardigliano 
29654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
29754fe083fSAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
29954fe083fSAlfredo Cardigliano }
30054fe083fSAlfredo Cardigliano 
30154fe083fSAlfredo Cardigliano void
30275f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
30354fe083fSAlfredo Cardigliano {
30454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30554fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
30675f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
30754fe083fSAlfredo Cardigliano 
30854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30954fe083fSAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
31154fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
31254fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
31354fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
31454fe083fSAlfredo Cardigliano 		return;
31554fe083fSAlfredo Cardigliano 	}
31654fe083fSAlfredo Cardigliano 
31775f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
31875f96902SAndrew Boyer 
31975f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32054fe083fSAlfredo Cardigliano 		return;
32154fe083fSAlfredo Cardigliano 
32275f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
32354fe083fSAlfredo Cardigliano }
32454fe083fSAlfredo Cardigliano 
32554fe083fSAlfredo Cardigliano int
32654fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
32754fe083fSAlfredo Cardigliano {
32854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32954fe083fSAlfredo Cardigliano 
33054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
33354fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
33454fe083fSAlfredo Cardigliano 		return -1;
33554fe083fSAlfredo Cardigliano 	}
33654fe083fSAlfredo Cardigliano 
33754fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
33854fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
33954fe083fSAlfredo Cardigliano 			lif->mac_addr);
34054fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
34154fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
34254fe083fSAlfredo Cardigliano 	}
34354fe083fSAlfredo Cardigliano 
34454fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
34754fe083fSAlfredo Cardigliano 
34854fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
34954fe083fSAlfredo Cardigliano }
35054fe083fSAlfredo Cardigliano 
35154fe083fSAlfredo Cardigliano static int
35254fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
35354fe083fSAlfredo Cardigliano {
35454fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
35554fe083fSAlfredo Cardigliano 		.pending_work = true,
35654fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
35754fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
35809f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
35909f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
36054fe083fSAlfredo Cardigliano 		},
36154fe083fSAlfredo Cardigliano 	};
36254fe083fSAlfredo Cardigliano 	int err;
36354fe083fSAlfredo Cardigliano 
36454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
36554fe083fSAlfredo Cardigliano 	if (err)
36654fe083fSAlfredo Cardigliano 		return err;
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
36909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
37054fe083fSAlfredo Cardigliano 
37154fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
37254fe083fSAlfredo Cardigliano }
37354fe083fSAlfredo Cardigliano 
37454fe083fSAlfredo Cardigliano static int
37554fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
37654fe083fSAlfredo Cardigliano {
37754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37854fe083fSAlfredo Cardigliano 		.pending_work = true,
37954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
38154fe083fSAlfredo Cardigliano 		},
38254fe083fSAlfredo Cardigliano 	};
38354fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
38454fe083fSAlfredo Cardigliano 	int err;
38554fe083fSAlfredo Cardigliano 
38654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
38754fe083fSAlfredo Cardigliano 
38854fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
39154fe083fSAlfredo Cardigliano 	if (!f) {
39254fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
39354fe083fSAlfredo Cardigliano 		return -ENOENT;
39454fe083fSAlfredo Cardigliano 	}
39554fe083fSAlfredo Cardigliano 
39609f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
39754fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
39854fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
39954fe083fSAlfredo Cardigliano 
40054fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
40154fe083fSAlfredo Cardigliano 	if (err)
40254fe083fSAlfredo Cardigliano 		return err;
40354fe083fSAlfredo Cardigliano 
40454fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
40509f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
406598f6726SAlfredo Cardigliano 
407598f6726SAlfredo Cardigliano 	return 0;
408598f6726SAlfredo Cardigliano }
409598f6726SAlfredo Cardigliano 
41054fe083fSAlfredo Cardigliano int
41154fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
41254fe083fSAlfredo Cardigliano 		int on)
41354fe083fSAlfredo Cardigliano {
41454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
41554fe083fSAlfredo Cardigliano 	int err;
41654fe083fSAlfredo Cardigliano 
41754fe083fSAlfredo Cardigliano 	if (on)
41854fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
41954fe083fSAlfredo Cardigliano 	else
42054fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
42154fe083fSAlfredo Cardigliano 
42254fe083fSAlfredo Cardigliano 	return err;
42354fe083fSAlfredo Cardigliano }
42454fe083fSAlfredo Cardigliano 
425598f6726SAlfredo Cardigliano static void
426598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
427598f6726SAlfredo Cardigliano {
428598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
429598f6726SAlfredo Cardigliano 		.pending_work = true,
430598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
431598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
43209f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
433598f6726SAlfredo Cardigliano 		},
434598f6726SAlfredo Cardigliano 	};
435598f6726SAlfredo Cardigliano 	int err;
436598f6726SAlfredo Cardigliano 
437598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
438598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
439598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
440598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
441598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
442598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
443598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
444598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
445598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
446598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
447598f6726SAlfredo Cardigliano 
448598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
449598f6726SAlfredo Cardigliano 	if (err)
450598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
451598f6726SAlfredo Cardigliano }
452598f6726SAlfredo Cardigliano 
453598f6726SAlfredo Cardigliano static void
454598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
455598f6726SAlfredo Cardigliano {
456598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
457598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
458598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
459598f6726SAlfredo Cardigliano 	}
460598f6726SAlfredo Cardigliano }
461598f6726SAlfredo Cardigliano 
46254fe083fSAlfredo Cardigliano int
46354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
46454fe083fSAlfredo Cardigliano {
46554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
46654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
46754fe083fSAlfredo Cardigliano 
46854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
46954fe083fSAlfredo Cardigliano 
47054fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
47154fe083fSAlfredo Cardigliano 
47254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
47354fe083fSAlfredo Cardigliano 
47454fe083fSAlfredo Cardigliano 	return 0;
47554fe083fSAlfredo Cardigliano }
47654fe083fSAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano int
47854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(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 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
48454fe083fSAlfredo Cardigliano 
48554fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48654fe083fSAlfredo Cardigliano 
48754fe083fSAlfredo Cardigliano 	return 0;
48854fe083fSAlfredo Cardigliano }
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano int
49154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
49254fe083fSAlfredo Cardigliano {
49354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49454fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49954fe083fSAlfredo Cardigliano 
50054fe083fSAlfredo Cardigliano 	return 0;
50154fe083fSAlfredo Cardigliano }
50254fe083fSAlfredo Cardigliano 
50354fe083fSAlfredo Cardigliano int
50454fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
50554fe083fSAlfredo Cardigliano {
50654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50754fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51254fe083fSAlfredo Cardigliano 
51354fe083fSAlfredo Cardigliano 	return 0;
51454fe083fSAlfredo Cardigliano }
515598f6726SAlfredo Cardigliano 
516598f6726SAlfredo Cardigliano int
517b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
518598f6726SAlfredo Cardigliano {
519598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
520598f6726SAlfredo Cardigliano 		.pending_work = true,
521598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
522598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
523598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
52409f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
525598f6726SAlfredo Cardigliano 		},
526598f6726SAlfredo Cardigliano 	};
527598f6726SAlfredo Cardigliano 
528b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
529598f6726SAlfredo Cardigliano }
530598f6726SAlfredo Cardigliano 
531598f6726SAlfredo Cardigliano int
53201a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
53301a6c311SAlfredo Cardigliano {
53401a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
53501a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
53601a6c311SAlfredo Cardigliano 	unsigned long index;
53701a6c311SAlfredo Cardigliano 
53801a6c311SAlfredo Cardigliano 	/*
53901a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
54001a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5414ae96cb8SAndrew Boyer 	 * which has index = 0)
54201a6c311SAlfredo Cardigliano 	 */
54301a6c311SAlfredo Cardigliano 
54401a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
54501a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
54601a6c311SAlfredo Cardigliano 			break;
54701a6c311SAlfredo Cardigliano 
54801a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
54901a6c311SAlfredo Cardigliano 		return -ENOSPC;
55001a6c311SAlfredo Cardigliano 
55101a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
55201a6c311SAlfredo Cardigliano 
55301a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
55401a6c311SAlfredo Cardigliano 
55501a6c311SAlfredo Cardigliano 	return 0;
55601a6c311SAlfredo Cardigliano }
55701a6c311SAlfredo Cardigliano 
55801a6c311SAlfredo Cardigliano static int
5594ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5604ad56b7aSAndrew Boyer 		uint8_t type,
561be39f75cSAndrew Boyer 		size_t struct_size,
5628ec5ad7fSAndrew Boyer 		uint32_t socket_id,
56301a6c311SAlfredo Cardigliano 		uint32_t index,
5644ad56b7aSAndrew Boyer 		const char *type_name,
5654ad56b7aSAndrew Boyer 		uint16_t flags,
5664ad56b7aSAndrew Boyer 		uint16_t num_descs,
567d5850081SAndrew Boyer 		uint16_t num_segs,
5684ad56b7aSAndrew Boyer 		uint16_t desc_size,
5694ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5704ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5711abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
57201a6c311SAlfredo Cardigliano {
57301a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
57401a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
57501a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
57601a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
57701a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
57801a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
57915770e98SAndrew Boyer 	size_t page_size = rte_mem_page_size();
58001a6c311SAlfredo Cardigliano 	int err;
58101a6c311SAlfredo Cardigliano 
58201a6c311SAlfredo Cardigliano 	*qcq = NULL;
58301a6c311SAlfredo Cardigliano 
58401a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
58501a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
58601a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
58701a6c311SAlfredo Cardigliano 
58815770e98SAndrew Boyer 	total_size = RTE_ALIGN(q_size, page_size) +
58915770e98SAndrew Boyer 			RTE_ALIGN(cq_size, page_size);
59001a6c311SAlfredo Cardigliano 	/*
59101a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
59201a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
59315770e98SAndrew Boyer 	 * Adding page_size.
59401a6c311SAlfredo Cardigliano 	 */
59515770e98SAndrew Boyer 	total_size += page_size;
59601a6c311SAlfredo Cardigliano 
59701a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
59815770e98SAndrew Boyer 		total_size += RTE_ALIGN(sg_size, page_size);
59915770e98SAndrew Boyer 		total_size += page_size;
60001a6c311SAlfredo Cardigliano 	}
60101a6c311SAlfredo Cardigliano 
602c5d0bb79SAndrew Boyer 	new = rte_zmalloc_socket("ionic", struct_size,
603c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
60401a6c311SAlfredo Cardigliano 	if (!new) {
60501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
60601a6c311SAlfredo Cardigliano 		return -ENOMEM;
60701a6c311SAlfredo Cardigliano 	}
60801a6c311SAlfredo Cardigliano 
60901a6c311SAlfredo Cardigliano 	new->lif = lif;
61001a6c311SAlfredo Cardigliano 
6117b20fc2fSAndrew Boyer 	/* Most queue types will store 1 ptr per descriptor */
612be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
613*4b53e980SAndrew Boyer 				(uint64_t)num_descs * num_segs,
614*4b53e980SAndrew Boyer 				sizeof(void *), page_size, socket_id);
61501a6c311SAlfredo Cardigliano 	if (!new->q.info) {
61601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6174c8f8d57SAndrew Boyer 		err = -ENOMEM;
6184c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
61901a6c311SAlfredo Cardigliano 	}
62001a6c311SAlfredo Cardigliano 
621d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
62201a6c311SAlfredo Cardigliano 	new->q.type = type;
62301a6c311SAlfredo Cardigliano 
6244ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
62501a6c311SAlfredo Cardigliano 	if (err) {
62601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6274c8f8d57SAndrew Boyer 		goto err_out_free_info;
62801a6c311SAlfredo Cardigliano 	}
62901a6c311SAlfredo Cardigliano 
6302aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
63101a6c311SAlfredo Cardigliano 	if (err) {
63201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6334c8f8d57SAndrew Boyer 		goto err_out_free_info;
63401a6c311SAlfredo Cardigliano 	}
63501a6c311SAlfredo Cardigliano 
63601a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6374ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
63801a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
63901a6c311SAlfredo Cardigliano 
64001a6c311SAlfredo Cardigliano 	if (!new->base_z) {
64101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
64201a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6434c8f8d57SAndrew Boyer 		goto err_out_free_info;
64401a6c311SAlfredo Cardigliano 	}
64501a6c311SAlfredo Cardigliano 
64601a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
64701a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
64801a6c311SAlfredo Cardigliano 
64901a6c311SAlfredo Cardigliano 	q_base = new->base;
65001a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
65101a6c311SAlfredo Cardigliano 
65215770e98SAndrew Boyer 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, page_size);
65315770e98SAndrew Boyer 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, page_size);
65401a6c311SAlfredo Cardigliano 
65501a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
65601a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
65715770e98SAndrew Boyer 				page_size);
65815770e98SAndrew Boyer 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, page_size);
65901a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
66001a6c311SAlfredo Cardigliano 	}
66101a6c311SAlfredo Cardigliano 
6629de21005SAndrew Boyer 	if (flags & IONIC_QCQ_F_CMB) {
6639de21005SAndrew Boyer 		/* alloc descriptor ring from nic memory */
6649de21005SAndrew Boyer 		if (lif->adapter->cmb_offset + q_size >
6659de21005SAndrew Boyer 				lif->adapter->bars.bar[2].len) {
6669de21005SAndrew Boyer 			IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem");
6679de21005SAndrew Boyer 			return -ENOMEM;
6689de21005SAndrew Boyer 		}
6699de21005SAndrew Boyer 		q_base = (void *)
6709de21005SAndrew Boyer 			((uintptr_t)lif->adapter->bars.bar[2].vaddr +
6719de21005SAndrew Boyer 			 (uintptr_t)lif->adapter->cmb_offset);
6729de21005SAndrew Boyer 		/* CMB PA is a relative address */
6739de21005SAndrew Boyer 		q_base_pa = lif->adapter->cmb_offset;
6749de21005SAndrew Boyer 		lif->adapter->cmb_offset += q_size;
6759de21005SAndrew Boyer 	}
6769de21005SAndrew Boyer 
6774ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6784ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
67901a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68001a6c311SAlfredo Cardigliano 
68101a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
68201a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
68301a6c311SAlfredo Cardigliano 
68401a6c311SAlfredo Cardigliano 	*qcq = new;
68501a6c311SAlfredo Cardigliano 
68601a6c311SAlfredo Cardigliano 	return 0;
68701a6c311SAlfredo Cardigliano 
6884c8f8d57SAndrew Boyer err_out_free_info:
6894c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6904c8f8d57SAndrew Boyer err_out_free_qcq:
6914c8f8d57SAndrew Boyer 	rte_free(new);
69201a6c311SAlfredo Cardigliano 
69301a6c311SAlfredo Cardigliano 	return err;
69401a6c311SAlfredo Cardigliano }
69501a6c311SAlfredo Cardigliano 
69601a6c311SAlfredo Cardigliano void
69701a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
69801a6c311SAlfredo Cardigliano {
69901a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70001a6c311SAlfredo Cardigliano 		qcq->base = NULL;
70101a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
70201a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
70301a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
70401a6c311SAlfredo Cardigliano 	}
70501a6c311SAlfredo Cardigliano 
70601a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
70701a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
70801a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
70901a6c311SAlfredo Cardigliano 	}
71001a6c311SAlfredo Cardigliano 
71101a6c311SAlfredo Cardigliano 	rte_free(qcq);
71201a6c311SAlfredo Cardigliano }
71301a6c311SAlfredo Cardigliano 
7147b20fc2fSAndrew Boyer static uint64_t
7157b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif)
7167b20fc2fSAndrew Boyer {
7177b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7187b20fc2fSAndrew Boyer 
7197b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7207b20fc2fSAndrew Boyer 
7217b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7227b20fc2fSAndrew Boyer 	rxm.data_off = RTE_PKTMBUF_HEADROOM;
7237b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7247b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7257b20fc2fSAndrew Boyer 
7267b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7277b20fc2fSAndrew Boyer 
7287b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7297b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7307b20fc2fSAndrew Boyer }
7317b20fc2fSAndrew Boyer 
7327b20fc2fSAndrew Boyer static uint64_t
7337b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif)
7347b20fc2fSAndrew Boyer {
7357b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7367b20fc2fSAndrew Boyer 
7377b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7387b20fc2fSAndrew Boyer 
7397b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7407b20fc2fSAndrew Boyer 	rxm.data_off = 0;  /* no headroom */
7417b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7427b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7437b20fc2fSAndrew Boyer 
7447b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7457b20fc2fSAndrew Boyer 
7467b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7477b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7487b20fc2fSAndrew Boyer }
7497b20fc2fSAndrew Boyer 
750a27d9013SAlfredo Cardigliano int
7518ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
752d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
753d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
754a27d9013SAlfredo Cardigliano {
755be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
756e86a6fccSAndrew Boyer 	uint16_t flags = 0, seg_size, hdr_seg_size, max_segs, max_segs_fw = 1;
757d5850081SAndrew Boyer 	uint32_t max_mtu;
758be39f75cSAndrew Boyer 	int err;
759a27d9013SAlfredo Cardigliano 
7609de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
7619de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
762b671e69aSAndrew Boyer 
763d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
764d5850081SAndrew Boyer 
765d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
766d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
767d5850081SAndrew Boyer 
768d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
769d5850081SAndrew Boyer 
770e86a6fccSAndrew Boyer 	/* If mbufs are too small to hold received packets, enable SG */
771e86a6fccSAndrew Boyer 	if (max_mtu > hdr_seg_size) {
772e86a6fccSAndrew Boyer 		IONIC_PRINT(NOTICE, "Enabling RX_OFFLOAD_SCATTER");
773e86a6fccSAndrew Boyer 		lif->eth_dev->data->dev_conf.rxmode.offloads |=
774e86a6fccSAndrew Boyer 			RTE_ETH_RX_OFFLOAD_SCATTER;
775e86a6fccSAndrew Boyer 		ionic_lif_configure_rx_sg_offload(lif);
776e86a6fccSAndrew Boyer 	}
777e86a6fccSAndrew Boyer 
778e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_RX_SG) {
779e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
780d5850081SAndrew Boyer 		max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
781e86a6fccSAndrew Boyer 	}
782d5850081SAndrew Boyer 
783d5850081SAndrew Boyer 	/*
784d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
7857b20fc2fSAndrew Boyer 	 * This is the worst-case number, so that there's enough room in
7867b20fc2fSAndrew Boyer 	 * the info array.
787d5850081SAndrew Boyer 	 */
788d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
789d5850081SAndrew Boyer 
7907b20fc2fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
7917b20fc2fSAndrew Boyer 		index, max_mtu, seg_size, max_segs);
792d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
793d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
794d5850081SAndrew Boyer 			max_segs, max_segs_fw);
795d5850081SAndrew Boyer 		return -EINVAL;
796d5850081SAndrew Boyer 	}
797d5850081SAndrew Boyer 
7984ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7994ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
800be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
8018ec5ad7fSAndrew Boyer 		socket_id,
8024ad56b7aSAndrew Boyer 		index,
8034ad56b7aSAndrew Boyer 		"rx",
8044ad56b7aSAndrew Boyer 		flags,
805a27d9013SAlfredo Cardigliano 		nrxq_descs,
806d5850081SAndrew Boyer 		max_segs,
807a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
808a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
809a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
810be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
811a27d9013SAlfredo Cardigliano 	if (err)
812a27d9013SAlfredo Cardigliano 		return err;
813a27d9013SAlfredo Cardigliano 
814be39f75cSAndrew Boyer 	rxq->flags = flags;
815d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
816d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
8177b20fc2fSAndrew Boyer 	rxq->rearm_data = ionic_rx_rearm_data(lif);
8187b20fc2fSAndrew Boyer 	rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
819be39f75cSAndrew Boyer 
820be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
821be39f75cSAndrew Boyer 	*rxq_out = rxq;
822a27d9013SAlfredo Cardigliano 
823a27d9013SAlfredo Cardigliano 	return 0;
824a27d9013SAlfredo Cardigliano }
825a27d9013SAlfredo Cardigliano 
826a27d9013SAlfredo Cardigliano int
8278ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
828be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
829a27d9013SAlfredo Cardigliano {
830be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
831e86a6fccSAndrew Boyer 	uint16_t flags = 0, num_segs_fw = 1;
832be39f75cSAndrew Boyer 	int err;
833a27d9013SAlfredo Cardigliano 
834e86a6fccSAndrew Boyer 	if (lif->features & IONIC_ETH_HW_TX_SG) {
835e86a6fccSAndrew Boyer 		flags |= IONIC_QCQ_F_SG;
836e86a6fccSAndrew Boyer 		num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
837e86a6fccSAndrew Boyer 	}
8389de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
8399de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
840e19eea1eSAndrew Boyer 
841e86a6fccSAndrew Boyer 	IONIC_PRINT(DEBUG, "txq %u num_segs %u", index, num_segs_fw);
842e19eea1eSAndrew Boyer 
8434ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8444ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
845be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
8468ec5ad7fSAndrew Boyer 		socket_id,
8474ad56b7aSAndrew Boyer 		index,
8484ad56b7aSAndrew Boyer 		"tx",
8494ad56b7aSAndrew Boyer 		flags,
850a27d9013SAlfredo Cardigliano 		ntxq_descs,
851b4beb84aSAndrew Boyer 		num_segs_fw,
852a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
853a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
85456117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
855be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
856a27d9013SAlfredo Cardigliano 	if (err)
857a27d9013SAlfredo Cardigliano 		return err;
858a27d9013SAlfredo Cardigliano 
859be39f75cSAndrew Boyer 	txq->flags = flags;
860e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
861be39f75cSAndrew Boyer 
862be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
863be39f75cSAndrew Boyer 	*txq_out = txq;
864a27d9013SAlfredo Cardigliano 
865a27d9013SAlfredo Cardigliano 	return 0;
866a27d9013SAlfredo Cardigliano }
867a27d9013SAlfredo Cardigliano 
86801a6c311SAlfredo Cardigliano static int
86901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
87001a6c311SAlfredo Cardigliano {
871be39f75cSAndrew Boyer 	uint16_t flags = 0;
872be39f75cSAndrew Boyer 	int err;
87301a6c311SAlfredo Cardigliano 
8744ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8754ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
876be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8778ec5ad7fSAndrew Boyer 		rte_socket_id(),
8784ad56b7aSAndrew Boyer 		0,
8794ad56b7aSAndrew Boyer 		"admin",
8804ad56b7aSAndrew Boyer 		flags,
88101a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
882d5850081SAndrew Boyer 		1,
88301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
88401a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
88501a6c311SAlfredo Cardigliano 		0,
886be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
88727b942c8SAlfredo Cardigliano 	if (err)
88827b942c8SAlfredo Cardigliano 		return err;
88901a6c311SAlfredo Cardigliano 
89027b942c8SAlfredo Cardigliano 	return 0;
89127b942c8SAlfredo Cardigliano }
89227b942c8SAlfredo Cardigliano 
89327b942c8SAlfredo Cardigliano static int
89427b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
89527b942c8SAlfredo Cardigliano {
896be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8974c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
898be39f75cSAndrew Boyer 	uint16_t flags = 0;
899be39f75cSAndrew Boyer 	int err;
90027b942c8SAlfredo Cardigliano 
9014ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
9024ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
903be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
9048ec5ad7fSAndrew Boyer 		rte_socket_id(),
9054ad56b7aSAndrew Boyer 		0,
9064ad56b7aSAndrew Boyer 		"notify",
90727b942c8SAlfredo Cardigliano 		flags,
90827b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
909d5850081SAndrew Boyer 		1,
91027b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
91127b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
91227b942c8SAlfredo Cardigliano 		0,
913be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
91401a6c311SAlfredo Cardigliano 	if (err)
91501a6c311SAlfredo Cardigliano 		return err;
91601a6c311SAlfredo Cardigliano 
9174c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
9184c8f8d57SAndrew Boyer 	if (err) {
919be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
9204c8f8d57SAndrew Boyer 		return err;
9214c8f8d57SAndrew Boyer 	}
9224c8f8d57SAndrew Boyer 
9234c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
9244c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
9254c8f8d57SAndrew Boyer 
9264c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
9274c8f8d57SAndrew Boyer 
92801a6c311SAlfredo Cardigliano 	return 0;
92901a6c311SAlfredo Cardigliano }
93001a6c311SAlfredo Cardigliano 
931c5d15850SAndrew Boyer static void
932c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
933c5d15850SAndrew Boyer {
934c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
935c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
936c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
937c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
938c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
939c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
940c5d15850SAndrew Boyer 	int err;
941c5d15850SAndrew Boyer 
942c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
943c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
944c5d15850SAndrew Boyer 
945c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
946c5d15850SAndrew Boyer 		switch (qtype) {
947c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
948c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
949c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
950c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
951c5d15850SAndrew Boyer 			break;
952c5d15850SAndrew Boyer 		default:
953c5d15850SAndrew Boyer 			continue;
954c5d15850SAndrew Boyer 		}
955c5d15850SAndrew Boyer 
956c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
957c5d15850SAndrew Boyer 
958c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
959c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
960c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
961c5d15850SAndrew Boyer 		if (err == -EINVAL) {
962c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
963c5d15850SAndrew Boyer 			continue;
964c5d15850SAndrew Boyer 		} else if (err == -EIO) {
965c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
966c5d15850SAndrew Boyer 			return;
967c5d15850SAndrew Boyer 		} else if (err) {
968c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
969c5d15850SAndrew Boyer 				qtype, err);
970c5d15850SAndrew Boyer 			return;
971c5d15850SAndrew Boyer 		}
972c5d15850SAndrew Boyer 
973c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
974c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
975c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
976c5d15850SAndrew Boyer 
977c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
978c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
979c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
980c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
981c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
982c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
983c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
984c5d15850SAndrew Boyer 		qti->sg_desc_stride =
985c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
986c5d15850SAndrew Boyer 
987c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
988c5d15850SAndrew Boyer 			qtype, qti->version);
989c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
990c5d15850SAndrew Boyer 			qtype, qti->supported);
991c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
992c5d15850SAndrew Boyer 			qtype, qti->features);
993c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
994c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
995c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
996c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
997c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
998c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
999c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
1000c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
1001c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
1002c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
1003c5d15850SAndrew Boyer 	}
1004c5d15850SAndrew Boyer }
1005c5d15850SAndrew Boyer 
1006669c8de6SAlfredo Cardigliano int
1007669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
1008669c8de6SAlfredo Cardigliano {
1009c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
1010669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
101101a6c311SAlfredo Cardigliano 	int err;
1012669c8de6SAlfredo Cardigliano 
10134ae96cb8SAndrew Boyer 	/*
10144ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
10154ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
10164ae96cb8SAndrew Boyer 	 */
10174ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
10184ae96cb8SAndrew Boyer 
10194ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
1020669c8de6SAlfredo Cardigliano 
1021c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
1022c5d15850SAndrew Boyer 
102356117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
102456117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
102556117636SAndrew Boyer 		return -ENXIO;
102656117636SAndrew Boyer 	}
102756117636SAndrew Boyer 
10289de21005SAndrew Boyer 	if (adapter->q_in_cmb) {
10299de21005SAndrew Boyer 		if (adapter->bars.num_bars >= 3 &&
10309de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 &&
10319de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) {
10329de21005SAndrew Boyer 			IONIC_PRINT(INFO, "%s enabled on %s",
10339de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10349de21005SAndrew Boyer 			lif->state |= IONIC_LIF_F_Q_IN_CMB;
10359de21005SAndrew Boyer 		} else {
10369de21005SAndrew Boyer 			IONIC_PRINT(ERR, "%s not supported on %s, disabled",
10379de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
10389de21005SAndrew Boyer 		}
10399de21005SAndrew Boyer 	}
10409de21005SAndrew Boyer 
1041669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
1042669c8de6SAlfredo Cardigliano 
104301a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
104401a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
104501a6c311SAlfredo Cardigliano 
104684cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
1047c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
1048c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1049c67719e1SAlfredo Cardigliano 		return -ENOMEM;
1050c67719e1SAlfredo Cardigliano 	}
1051c67719e1SAlfredo Cardigliano 
1052c5d0bb79SAndrew Boyer 	lif->txqcqs = rte_calloc_socket("ionic",
1053c663c7ecSAndrew Boyer 				adapter->max_ntxqs_per_lif,
1054c5d0bb79SAndrew Boyer 				sizeof(*lif->txqcqs),
1055c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1056a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
1057a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1058a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1059a27d9013SAlfredo Cardigliano 	}
1060a27d9013SAlfredo Cardigliano 
1061c5d0bb79SAndrew Boyer 	lif->rxqcqs = rte_calloc_socket("ionic",
1062c663c7ecSAndrew Boyer 				adapter->max_nrxqs_per_lif,
1063c5d0bb79SAndrew Boyer 				sizeof(*lif->rxqcqs),
1064c5d0bb79SAndrew Boyer 				RTE_CACHE_LINE_SIZE, socket_id);
1065a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
1066a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1067a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1068a27d9013SAlfredo Cardigliano 	}
1069a27d9013SAlfredo Cardigliano 
107027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
107127b942c8SAlfredo Cardigliano 
107227b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
107327b942c8SAlfredo Cardigliano 	if (err) {
107427b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
107527b942c8SAlfredo Cardigliano 		return err;
107627b942c8SAlfredo Cardigliano 	}
107727b942c8SAlfredo Cardigliano 
107827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
107927b942c8SAlfredo Cardigliano 
108001a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
108101a6c311SAlfredo Cardigliano 	if (err) {
108201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
108301a6c311SAlfredo Cardigliano 		return err;
108401a6c311SAlfredo Cardigliano 	}
108501a6c311SAlfredo Cardigliano 
108601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
108701a6c311SAlfredo Cardigliano 
1088924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1089669c8de6SAlfredo Cardigliano 
1090669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1091669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1092669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1093669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1094669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1095669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1096669c8de6SAlfredo Cardigliano 	}
1097669c8de6SAlfredo Cardigliano 
1098669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1099669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1100669c8de6SAlfredo Cardigliano 
1101669c8de6SAlfredo Cardigliano 	return 0;
1102669c8de6SAlfredo Cardigliano }
1103669c8de6SAlfredo Cardigliano 
1104669c8de6SAlfredo Cardigliano void
1105669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1106669c8de6SAlfredo Cardigliano {
110727b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1108be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
110927b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
111027b942c8SAlfredo Cardigliano 	}
111127b942c8SAlfredo Cardigliano 
111201a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1113be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
111401a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
111501a6c311SAlfredo Cardigliano 	}
111601a6c311SAlfredo Cardigliano 
1117a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1118a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1119a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1120a27d9013SAlfredo Cardigliano 	}
1121a27d9013SAlfredo Cardigliano 
1122a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1123a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1124a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1125a27d9013SAlfredo Cardigliano 	}
1126a27d9013SAlfredo Cardigliano 
1127669c8de6SAlfredo Cardigliano 	if (lif->info) {
1128669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1129669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1130669c8de6SAlfredo Cardigliano 	}
1131669c8de6SAlfredo Cardigliano }
1132669c8de6SAlfredo Cardigliano 
1133175e4e7eSAndrew Boyer void
1134175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1135175e4e7eSAndrew Boyer {
1136175e4e7eSAndrew Boyer 	uint32_t i;
1137175e4e7eSAndrew Boyer 
1138175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
11397483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1140175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1141175e4e7eSAndrew Boyer 	}
1142175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
11437483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1144175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1145175e4e7eSAndrew Boyer 	}
1146175e4e7eSAndrew Boyer }
1147175e4e7eSAndrew Boyer 
114822e7171bSAlfredo Cardigliano int
114922e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
115022e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
115122e7171bSAlfredo Cardigliano {
115209f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
115322e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
115422e7171bSAlfredo Cardigliano 		.pending_work = true,
115522e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
115622e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
115722e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
115809f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
115909f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
116022e7171bSAlfredo Cardigliano 		},
116122e7171bSAlfredo Cardigliano 	};
116222e7171bSAlfredo Cardigliano 	unsigned int i;
116309f806e9SAndrew Boyer 	uint16_t tbl_sz =
116409f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
116522e7171bSAlfredo Cardigliano 
116622e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
116722e7171bSAlfredo Cardigliano 
116822e7171bSAlfredo Cardigliano 	lif->rss_types = types;
116922e7171bSAlfredo Cardigliano 
117022e7171bSAlfredo Cardigliano 	if (key)
117122e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
117222e7171bSAlfredo Cardigliano 
117322e7171bSAlfredo Cardigliano 	if (indir)
117409f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
117522e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
117622e7171bSAlfredo Cardigliano 
117722e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
117822e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
117922e7171bSAlfredo Cardigliano 
118022e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
118122e7171bSAlfredo Cardigliano }
118222e7171bSAlfredo Cardigliano 
118322e7171bSAlfredo Cardigliano static int
118422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
118522e7171bSAlfredo Cardigliano {
118609f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
118722e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
118822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
118922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
119022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
119122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
119222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
119322e7171bSAlfredo Cardigliano 	};
119422e7171bSAlfredo Cardigliano 	uint32_t i;
119509f806e9SAndrew Boyer 	uint16_t tbl_sz =
119609f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
119722e7171bSAlfredo Cardigliano 
119822e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
119922e7171bSAlfredo Cardigliano 
12003d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
120122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
12023d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
12033d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
12043d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
120522e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
120622e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
120722e7171bSAlfredo Cardigliano 			return -ENOMEM;
120822e7171bSAlfredo Cardigliano 		}
120922e7171bSAlfredo Cardigliano 
121022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
121122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
12123d845eddSAndrew Boyer 	}
12133d845eddSAndrew Boyer 
12143d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
12153d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
121622e7171bSAlfredo Cardigliano 
121722e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
12183d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
121922e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
12203d845eddSAndrew Boyer 	}
122122e7171bSAlfredo Cardigliano 
12223d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
122322e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
122422e7171bSAlfredo Cardigliano }
122522e7171bSAlfredo Cardigliano 
122622e7171bSAlfredo Cardigliano static void
122722e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
122822e7171bSAlfredo Cardigliano {
122922e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
123022e7171bSAlfredo Cardigliano 		return;
123122e7171bSAlfredo Cardigliano 
123222e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
123322e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
123422e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
123522e7171bSAlfredo Cardigliano 
123622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
123722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
123822e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
123922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
124022e7171bSAlfredo Cardigliano 	}
124122e7171bSAlfredo Cardigliano }
124222e7171bSAlfredo Cardigliano 
1243be39f75cSAndrew Boyer void
1244be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1245be39f75cSAndrew Boyer {
1246e7222f94SAndrew Boyer 	ionic_qcq_disable(&txq->qcq);
1247e7222f94SAndrew Boyer 
1248be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1249be39f75cSAndrew Boyer }
1250be39f75cSAndrew Boyer 
1251be39f75cSAndrew Boyer void
1252be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1253be39f75cSAndrew Boyer {
1254e7222f94SAndrew Boyer 	ionic_qcq_disable(&rxq->qcq);
1255e7222f94SAndrew Boyer 
1256be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1257be39f75cSAndrew Boyer }
1258be39f75cSAndrew Boyer 
125901a6c311SAlfredo Cardigliano static void
1260be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
126101a6c311SAlfredo Cardigliano {
1262be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
12634c8f8d57SAndrew Boyer }
12644c8f8d57SAndrew Boyer 
12654c8f8d57SAndrew Boyer static void
12664c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
12674c8f8d57SAndrew Boyer {
1268be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
12694c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
12704c8f8d57SAndrew Boyer 
12714c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
12724c8f8d57SAndrew Boyer 		return;
12734c8f8d57SAndrew Boyer 
12744c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
12754c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
12764c8f8d57SAndrew Boyer 
12774c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1278a27d9013SAlfredo Cardigliano }
1279a27d9013SAlfredo Cardigliano 
128001a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
128101a6c311SAlfredo Cardigliano int
128201a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
128301a6c311SAlfredo Cardigliano 		void *cb_arg)
128401a6c311SAlfredo Cardigliano {
128501a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
128601a6c311SAlfredo Cardigliano 	uint32_t work_done;
128701a6c311SAlfredo Cardigliano 
128801a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
128901a6c311SAlfredo Cardigliano 
129001a6c311SAlfredo Cardigliano 	return work_done;
129101a6c311SAlfredo Cardigliano }
129201a6c311SAlfredo Cardigliano 
129327b942c8SAlfredo Cardigliano static void
129427b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
129527b942c8SAlfredo Cardigliano {
129627b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
129727b942c8SAlfredo Cardigliano 	bool link_up;
129827b942c8SAlfredo Cardigliano 
129927b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
130027b942c8SAlfredo Cardigliano 
130127b942c8SAlfredo Cardigliano 	if (!lif->info)
130227b942c8SAlfredo Cardigliano 		return;
130327b942c8SAlfredo Cardigliano 
130427b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
130527b942c8SAlfredo Cardigliano 
130627b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
130727b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
130827b942c8SAlfredo Cardigliano 		return;
130927b942c8SAlfredo Cardigliano 
131027b942c8SAlfredo Cardigliano 	if (link_up) {
131109f806e9SAndrew Boyer 		adapter->link_speed =
131209f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1313be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1314be63459eSAndrew Boyer 			adapter->link_speed);
131527b942c8SAlfredo Cardigliano 	} else {
131627b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
131727b942c8SAlfredo Cardigliano 	}
131827b942c8SAlfredo Cardigliano 
131927b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1320be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1321be63459eSAndrew Boyer }
1322be63459eSAndrew Boyer 
1323be63459eSAndrew Boyer static void
1324be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1325be63459eSAndrew Boyer {
1326be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1327be63459eSAndrew Boyer 		return;
1328be63459eSAndrew Boyer 
1329be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1330be63459eSAndrew Boyer 
1331be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1332be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1333be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1334be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1335be63459eSAndrew Boyer 	}
1336be63459eSAndrew Boyer 
1337be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
133827b942c8SAlfredo Cardigliano }
133927b942c8SAlfredo Cardigliano 
134027b942c8SAlfredo Cardigliano static bool
13414ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
134227b942c8SAlfredo Cardigliano {
134327b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
134427b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
134527b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
134627b942c8SAlfredo Cardigliano 
134727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
134827b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
134927b942c8SAlfredo Cardigliano 
135027b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
135127b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
135227b942c8SAlfredo Cardigliano 		return false;
135327b942c8SAlfredo Cardigliano 
135427b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
135527b942c8SAlfredo Cardigliano 
135627b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
135727b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
135827b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1359be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1360be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1361be63459eSAndrew Boyer 			lif->name,
136227b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
136327b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
136427b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
136527b942c8SAlfredo Cardigliano 
136627b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
136727b942c8SAlfredo Cardigliano 		break;
1368be63459eSAndrew Boyer 
1369be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1370be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1371be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1372be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1373be63459eSAndrew Boyer 			lif->name,
1374be63459eSAndrew Boyer 			cq_desc->event.eid,
1375be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1376be63459eSAndrew Boyer 			cq_desc->reset.state);
1377be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1378be63459eSAndrew Boyer 		break;
1379be63459eSAndrew Boyer 
138027b942c8SAlfredo Cardigliano 	default:
138127b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
138227b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
138327b942c8SAlfredo Cardigliano 		break;
138427b942c8SAlfredo Cardigliano 	}
138527b942c8SAlfredo Cardigliano 
138627b942c8SAlfredo Cardigliano 	return true;
138727b942c8SAlfredo Cardigliano }
138827b942c8SAlfredo Cardigliano 
138927b942c8SAlfredo Cardigliano int
139027b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
139127b942c8SAlfredo Cardigliano {
139227b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1393be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
139427b942c8SAlfredo Cardigliano 	uint32_t work_done;
139527b942c8SAlfredo Cardigliano 
1396be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
139727b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
139827b942c8SAlfredo Cardigliano 		return -1;
139927b942c8SAlfredo Cardigliano 	}
140027b942c8SAlfredo Cardigliano 
1401be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
140227b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
140327b942c8SAlfredo Cardigliano 
1404be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1405be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
140627b942c8SAlfredo Cardigliano 
140727b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
140827b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
140927b942c8SAlfredo Cardigliano 
1410be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
141127b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
141227b942c8SAlfredo Cardigliano 
1413be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
141427b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
141527b942c8SAlfredo Cardigliano 
141627b942c8SAlfredo Cardigliano 	return 0;
141727b942c8SAlfredo Cardigliano }
141827b942c8SAlfredo Cardigliano 
141901a6c311SAlfredo Cardigliano static int
142001a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
142101a6c311SAlfredo Cardigliano {
142201a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1423be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1424be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
142501a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
142613133a28SAndrew Boyer 	uint32_t retries = 5;
142701a6c311SAlfredo Cardigliano 	int err;
142801a6c311SAlfredo Cardigliano 
142913133a28SAndrew Boyer retry_adminq_init:
1430be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
143101a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
143213133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
143313133a28SAndrew Boyer 		retries--;
143413133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
143513133a28SAndrew Boyer 		goto retry_adminq_init;
143613133a28SAndrew Boyer 	}
143701a6c311SAlfredo Cardigliano 	if (err)
143801a6c311SAlfredo Cardigliano 		return err;
143901a6c311SAlfredo Cardigliano 
144001a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
144101a6c311SAlfredo Cardigliano 
144201a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
144309f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
144401a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
144501a6c311SAlfredo Cardigliano 
144601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
144701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
144801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
144901a6c311SAlfredo Cardigliano 
1450be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
145101a6c311SAlfredo Cardigliano 
145201a6c311SAlfredo Cardigliano 	return 0;
145301a6c311SAlfredo Cardigliano }
145401a6c311SAlfredo Cardigliano 
145527b942c8SAlfredo Cardigliano static int
145627b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
145727b942c8SAlfredo Cardigliano {
145827b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1459be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1460be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
14610a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
146227b942c8SAlfredo Cardigliano 	int err;
146327b942c8SAlfredo Cardigliano 
146427b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
146527b942c8SAlfredo Cardigliano 		.pending_work = true,
146627b942c8SAlfredo Cardigliano 		.cmd.q_init = {
146727b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
146827b942c8SAlfredo Cardigliano 			.type = q->type,
1469c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
147009f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
14710a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
147227b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
147309f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
147427b942c8SAlfredo Cardigliano 		}
147527b942c8SAlfredo Cardigliano 	};
147627b942c8SAlfredo Cardigliano 
14770a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
14780a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
14790a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
14800a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
14810a00bdafSAndrew Boyer 	}
14820a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
14830a00bdafSAndrew Boyer 
148409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
148509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
148627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
148727b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14884ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
148927b942c8SAlfredo Cardigliano 
149027b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
149127b942c8SAlfredo Cardigliano 	if (err)
149227b942c8SAlfredo Cardigliano 		return err;
149327b942c8SAlfredo Cardigliano 
149427b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
149509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
149627b942c8SAlfredo Cardigliano 	q->db = NULL;
149727b942c8SAlfredo Cardigliano 
149827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
149927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
150027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
150127b942c8SAlfredo Cardigliano 
1502be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
150327b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
150427b942c8SAlfredo Cardigliano 
1505be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
150627b942c8SAlfredo Cardigliano 
150727b942c8SAlfredo Cardigliano 	return 0;
150827b942c8SAlfredo Cardigliano }
150927b942c8SAlfredo Cardigliano 
1510669c8de6SAlfredo Cardigliano int
1511598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1512598f6726SAlfredo Cardigliano {
1513598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1514598f6726SAlfredo Cardigliano 		.pending_work = true,
1515598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1516598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1517598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
151809f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1519598f6726SAlfredo Cardigliano 		},
1520598f6726SAlfredo Cardigliano 	};
1521598f6726SAlfredo Cardigliano 	int err;
1522598f6726SAlfredo Cardigliano 
1523598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1524598f6726SAlfredo Cardigliano 	if (err)
1525598f6726SAlfredo Cardigliano 		return err;
1526598f6726SAlfredo Cardigliano 
152709f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1528598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1529598f6726SAlfredo Cardigliano 
1530598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1531598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1532598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1533598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1534598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1535598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1536598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1537598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1538598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1539598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1540598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1541598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1542598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1543598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1544598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1545598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1546598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1547598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1548598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1549598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1550598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1551598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1552598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1553598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1554598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1555598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1556598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1557598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1558598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1559598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1560598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1561598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1562598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1563598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1564598f6726SAlfredo Cardigliano 
1565598f6726SAlfredo Cardigliano 	return 0;
1566598f6726SAlfredo Cardigliano }
1567598f6726SAlfredo Cardigliano 
1568a27d9013SAlfredo Cardigliano int
1569be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1570a27d9013SAlfredo Cardigliano {
1571be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1572a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1573a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1574a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1575a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1576a27d9013SAlfredo Cardigliano 		.pending_work = true,
1577a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1578a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1579a27d9013SAlfredo Cardigliano 			.type = q->type,
1580c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
158109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1582e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
158309f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1584a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
158509f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
158609f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
158709f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1588a27d9013SAlfredo Cardigliano 		},
1589a27d9013SAlfredo Cardigliano 	};
1590a27d9013SAlfredo Cardigliano 	int err;
1591a27d9013SAlfredo Cardigliano 
1592e86a6fccSAndrew Boyer 	if (txq->flags & IONIC_QCQ_F_SG)
1593e86a6fccSAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
15949de21005SAndrew Boyer 	if (txq->flags & IONIC_QCQ_F_CMB)
15959de21005SAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
15969de21005SAndrew Boyer 
159709f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
159809f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1599a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1600a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
16014ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1602a27d9013SAlfredo Cardigliano 
1603e7222f94SAndrew Boyer 	ionic_q_reset(q);
1604e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1605e7222f94SAndrew Boyer 
1606be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1607a27d9013SAlfredo Cardigliano 	if (err)
1608a27d9013SAlfredo Cardigliano 		return err;
1609a27d9013SAlfredo Cardigliano 
1610a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
161109f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1612a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1613a27d9013SAlfredo Cardigliano 
1614a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1615a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1616a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1617a27d9013SAlfredo Cardigliano 
1618be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1619a27d9013SAlfredo Cardigliano 
1620a27d9013SAlfredo Cardigliano 	return 0;
1621a27d9013SAlfredo Cardigliano }
1622a27d9013SAlfredo Cardigliano 
1623a27d9013SAlfredo Cardigliano int
1624be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1625a27d9013SAlfredo Cardigliano {
1626be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1627a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1628a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1629a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1630a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1631a27d9013SAlfredo Cardigliano 		.pending_work = true,
1632a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1633a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1634a27d9013SAlfredo Cardigliano 			.type = q->type,
1635c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
163609f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1637e86a6fccSAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA),
163809f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1639a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
164009f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
164109f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
164209f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1643a27d9013SAlfredo Cardigliano 		},
1644a27d9013SAlfredo Cardigliano 	};
1645a27d9013SAlfredo Cardigliano 	int err;
1646a27d9013SAlfredo Cardigliano 
1647e86a6fccSAndrew Boyer 	if (rxq->flags & IONIC_QCQ_F_SG)
1648e86a6fccSAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_SG);
16499de21005SAndrew Boyer 	if (rxq->flags & IONIC_QCQ_F_CMB)
16509de21005SAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
16519de21005SAndrew Boyer 
165209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
165309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1654a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1655a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
16564ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1657a27d9013SAlfredo Cardigliano 
1658e7222f94SAndrew Boyer 	ionic_q_reset(q);
1659e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1660e7222f94SAndrew Boyer 
1661be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1662a27d9013SAlfredo Cardigliano 	if (err)
1663a27d9013SAlfredo Cardigliano 		return err;
1664a27d9013SAlfredo Cardigliano 
1665a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
166609f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1667a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1668a27d9013SAlfredo Cardigliano 
1669be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1670a27d9013SAlfredo Cardigliano 
1671a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1672a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1673a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1674a27d9013SAlfredo Cardigliano 
1675a27d9013SAlfredo Cardigliano 	return 0;
1676a27d9013SAlfredo Cardigliano }
1677a27d9013SAlfredo Cardigliano 
1678598f6726SAlfredo Cardigliano static int
1679598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1680598f6726SAlfredo Cardigliano {
1681598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1682598f6726SAlfredo Cardigliano 		.pending_work = true,
1683598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1684598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1685598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1686598f6726SAlfredo Cardigliano 		},
1687598f6726SAlfredo Cardigliano 	};
1688598f6726SAlfredo Cardigliano 	int err;
1689598f6726SAlfredo Cardigliano 
1690598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1691598f6726SAlfredo Cardigliano 
1692598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1693598f6726SAlfredo Cardigliano 	if (err)
1694598f6726SAlfredo Cardigliano 		return err;
1695598f6726SAlfredo Cardigliano 
1696598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1697598f6726SAlfredo Cardigliano 
1698598f6726SAlfredo Cardigliano 	return 0;
1699598f6726SAlfredo Cardigliano }
1700598f6726SAlfredo Cardigliano 
1701598f6726SAlfredo Cardigliano static void
1702598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1703598f6726SAlfredo Cardigliano {
1704598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1705598f6726SAlfredo Cardigliano 		.pending_work = true,
1706598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1707598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1708598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1709598f6726SAlfredo Cardigliano 		},
1710598f6726SAlfredo Cardigliano 	};
1711598f6726SAlfredo Cardigliano 
17124ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
17134ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1714598f6726SAlfredo Cardigliano 
1715598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1716598f6726SAlfredo Cardigliano }
1717598f6726SAlfredo Cardigliano 
1718598f6726SAlfredo Cardigliano int
1719669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1720669c8de6SAlfredo Cardigliano {
1721669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1722656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
172313133a28SAndrew Boyer 	uint32_t retries = 5;
1724669c8de6SAlfredo Cardigliano 	int err;
1725669c8de6SAlfredo Cardigliano 
17263cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
17273cdfd905SAlfredo Cardigliano 
172813133a28SAndrew Boyer retry_lif_init:
172900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1730669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
173113133a28SAndrew Boyer 	if (err == -EAGAIN && retries > 0) {
173213133a28SAndrew Boyer 		retries--;
173313133a28SAndrew Boyer 		rte_delay_us_block(IONIC_DEVCMD_RETRY_WAIT_US);
173413133a28SAndrew Boyer 		goto retry_lif_init;
173513133a28SAndrew Boyer 	}
1736669c8de6SAlfredo Cardigliano 	if (err)
1737669c8de6SAlfredo Cardigliano 		return err;
1738669c8de6SAlfredo Cardigliano 
1739656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1740656bfc9aSAndrew Boyer 
174109f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1742669c8de6SAlfredo Cardigliano 
174301a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
174401a6c311SAlfredo Cardigliano 	if (err)
174501a6c311SAlfredo Cardigliano 		return err;
174601a6c311SAlfredo Cardigliano 
174727b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
174827b942c8SAlfredo Cardigliano 	if (err)
174927b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
175027b942c8SAlfredo Cardigliano 
175118a44465SAndrew Boyer 	/*
175218a44465SAndrew Boyer 	 * Configure initial feature set
175318a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
175418a44465SAndrew Boyer 	 */
175518a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1756598f6726SAlfredo Cardigliano 
1757598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1758598f6726SAlfredo Cardigliano 	if (err)
1759598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1760598f6726SAlfredo Cardigliano 
176154fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1762598f6726SAlfredo Cardigliano 	if (err)
1763598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1764598f6726SAlfredo Cardigliano 
176554fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
176654fe083fSAlfredo Cardigliano 	if (err)
176754fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
176854fe083fSAlfredo Cardigliano 
1769598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1770598f6726SAlfredo Cardigliano 
1771669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1772669c8de6SAlfredo Cardigliano 
1773669c8de6SAlfredo Cardigliano 	return 0;
177427b942c8SAlfredo Cardigliano 
177554fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
177654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
177754fe083fSAlfredo Cardigliano 
1778598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
17794c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1780598f6726SAlfredo Cardigliano 
178127b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1782be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
178327b942c8SAlfredo Cardigliano 
178427b942c8SAlfredo Cardigliano 	return err;
1785669c8de6SAlfredo Cardigliano }
1786669c8de6SAlfredo Cardigliano 
1787669c8de6SAlfredo Cardigliano void
1788669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1789669c8de6SAlfredo Cardigliano {
1790669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1791669c8de6SAlfredo Cardigliano 		return;
1792669c8de6SAlfredo Cardigliano 
179354fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
179422e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
17954c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1796be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
179701a6c311SAlfredo Cardigliano 
1798669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1799669c8de6SAlfredo Cardigliano }
1800669c8de6SAlfredo Cardigliano 
180118a44465SAndrew Boyer void
180218a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
180318a44465SAndrew Boyer {
180418a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
180518a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
180618a44465SAndrew Boyer 
180718a44465SAndrew Boyer 	/*
180818a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1809295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
181018a44465SAndrew Boyer 	 */
1811295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
181218a44465SAndrew Boyer 
1813295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1814295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
181518a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
181618a44465SAndrew Boyer 		else
181718a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
181818a44465SAndrew Boyer 	}
181918a44465SAndrew Boyer }
182018a44465SAndrew Boyer 
182118a44465SAndrew Boyer void
1822e86a6fccSAndrew Boyer ionic_lif_configure_rx_sg_offload(struct ionic_lif *lif)
1823e86a6fccSAndrew Boyer {
1824e86a6fccSAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
1825e86a6fccSAndrew Boyer 
1826e86a6fccSAndrew Boyer 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
1827e86a6fccSAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
1828e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
1829e86a6fccSAndrew Boyer 	} else {
1830e86a6fccSAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
1831e86a6fccSAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
1832e86a6fccSAndrew Boyer 	}
1833e86a6fccSAndrew Boyer }
1834e86a6fccSAndrew Boyer 
1835e86a6fccSAndrew Boyer void
1836598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1837598f6726SAlfredo Cardigliano {
183818a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
183918a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
184022e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
184109f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
184222e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
184309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
184422e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
184509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
184622e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
184722e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
184822e7171bSAlfredo Cardigliano 
1849598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1850598f6726SAlfredo Cardigliano 
185122e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
185222e7171bSAlfredo Cardigliano 		lif->port_id);
185322e7171bSAlfredo Cardigliano 
185422e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
185522e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
185622e7171bSAlfredo Cardigliano 
185722e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
185822e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
185922e7171bSAlfredo Cardigliano 
186022e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
186122e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1862a27d9013SAlfredo Cardigliano 
186318a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
186418a44465SAndrew Boyer 
186518a44465SAndrew Boyer 	/*
186618a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
186718a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1868295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
186918a44465SAndrew Boyer 	 */
187018a44465SAndrew Boyer 
187118a44465SAndrew Boyer 	/* RX per-port */
187218a44465SAndrew Boyer 
1873295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1874295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1875295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
187618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
187718a44465SAndrew Boyer 	else
187818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
187918a44465SAndrew Boyer 
1880e86a6fccSAndrew Boyer 	/*
1881e86a6fccSAndrew Boyer 	 * NB: RX_SG may be enabled later during rx_queue_setup() if
1882e86a6fccSAndrew Boyer 	 * required by the mbuf/mtu configuration
1883e86a6fccSAndrew Boyer 	 */
1884e86a6fccSAndrew Boyer 	ionic_lif_configure_rx_sg_offload(lif);
188518a44465SAndrew Boyer 
188618a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1887295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
188818a44465SAndrew Boyer 
188918a44465SAndrew Boyer 	/* TX per-port */
189018a44465SAndrew Boyer 
1891295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1892295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1893295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1894295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1895295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
189618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
189718a44465SAndrew Boyer 	else
189818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
189918a44465SAndrew Boyer 
1900295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
190118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
190218a44465SAndrew Boyer 	else
190318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
190418a44465SAndrew Boyer 
1905295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
190618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
190718a44465SAndrew Boyer 	else
190818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
190918a44465SAndrew Boyer 
1910295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
191118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
191218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
191318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
191418a44465SAndrew Boyer 	} else {
191518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
191618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
191718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
191818a44465SAndrew Boyer 	}
1919598f6726SAlfredo Cardigliano }
1920598f6726SAlfredo Cardigliano 
1921598f6726SAlfredo Cardigliano int
1922598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1923598f6726SAlfredo Cardigliano {
19240578335aSAndrew Boyer 	uint32_t rx_mode;
1925a27d9013SAlfredo Cardigliano 	uint32_t i;
1926a27d9013SAlfredo Cardigliano 	int err;
1927598f6726SAlfredo Cardigliano 
192822e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
192922e7171bSAlfredo Cardigliano 	if (err)
193022e7171bSAlfredo Cardigliano 		return err;
193122e7171bSAlfredo Cardigliano 
19320578335aSAndrew Boyer 	if (!lif->rx_mode) {
19330578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
19340578335aSAndrew Boyer 			lif->name);
1935598f6726SAlfredo Cardigliano 
19360578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1937598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1938598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1939598f6726SAlfredo Cardigliano 
1940598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
19410578335aSAndrew Boyer 	}
1942598f6726SAlfredo Cardigliano 
1943a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1944a27d9013SAlfredo Cardigliano 		"on port %u",
1945a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1946a27d9013SAlfredo Cardigliano 
1947a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1948be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
194902eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1950a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1951a27d9013SAlfredo Cardigliano 
1952a27d9013SAlfredo Cardigliano 			if (err)
1953a27d9013SAlfredo Cardigliano 				return err;
1954a27d9013SAlfredo Cardigliano 		}
1955a27d9013SAlfredo Cardigliano 	}
1956a27d9013SAlfredo Cardigliano 
1957a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1958be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
195902eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1960a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1961a27d9013SAlfredo Cardigliano 
1962a27d9013SAlfredo Cardigliano 			if (err)
1963a27d9013SAlfredo Cardigliano 				return err;
1964a27d9013SAlfredo Cardigliano 		}
1965a27d9013SAlfredo Cardigliano 	}
1966a27d9013SAlfredo Cardigliano 
1967598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1968be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1969be63459eSAndrew Boyer 
1970be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1971598f6726SAlfredo Cardigliano 
1972598f6726SAlfredo Cardigliano 	return 0;
1973598f6726SAlfredo Cardigliano }
1974598f6726SAlfredo Cardigliano 
1975598f6726SAlfredo Cardigliano int
1976669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1977669c8de6SAlfredo Cardigliano {
1978669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1979669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
198009f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
198176276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
198276276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
198376276d71SAndrew Boyer 	uint32_t i, nwords;
1984669c8de6SAlfredo Cardigliano 	int err;
1985669c8de6SAlfredo Cardigliano 
1986669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1987669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1988669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1989669c8de6SAlfredo Cardigliano 	if (err)
1990669c8de6SAlfredo Cardigliano 		return (err);
1991669c8de6SAlfredo Cardigliano 
1992669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1993669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1994669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1995669c8de6SAlfredo Cardigliano 
1996669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
199709f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1998669c8de6SAlfredo Cardigliano 
1999669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
200009f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
2001669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
200209f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
2003669c8de6SAlfredo Cardigliano 
2004669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
200509f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
2006669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
200709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
2008669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
200909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
2010669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
201109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
2012669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
201309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
2014669c8de6SAlfredo Cardigliano 
2015669c8de6SAlfredo Cardigliano 	return 0;
2016669c8de6SAlfredo Cardigliano }
2017669c8de6SAlfredo Cardigliano 
2018669c8de6SAlfredo Cardigliano int
2019669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
2020669c8de6SAlfredo Cardigliano {
2021669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
202209f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
202309f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
2024669c8de6SAlfredo Cardigliano 
2025669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
202609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
2027669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
202809f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
2029669c8de6SAlfredo Cardigliano 
203000b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
2031669c8de6SAlfredo Cardigliano 
2032669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
20334ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
20344ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
2035669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
2036669c8de6SAlfredo Cardigliano 		return -ENOSPC;
2037669c8de6SAlfredo Cardigliano 	}
2038669c8de6SAlfredo Cardigliano 
2039669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
2040669c8de6SAlfredo Cardigliano 
2041669c8de6SAlfredo Cardigliano 	return 0;
2042669c8de6SAlfredo Cardigliano }
2043