xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 9de21005e201af6ba8dc3836c09384e0b40b4a89)
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;
57901a6c311SAlfredo Cardigliano 	int err;
58001a6c311SAlfredo Cardigliano 
58101a6c311SAlfredo Cardigliano 	*qcq = NULL;
58201a6c311SAlfredo Cardigliano 
58301a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
58401a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
58501a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
58601a6c311SAlfredo Cardigliano 
587924e6b76SThomas Monjalon 	total_size = RTE_ALIGN(q_size, rte_mem_page_size()) +
588924e6b76SThomas Monjalon 			RTE_ALIGN(cq_size, rte_mem_page_size());
58901a6c311SAlfredo Cardigliano 	/*
59001a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
59101a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
592924e6b76SThomas Monjalon 	 * Adding rte_mem_page_size().
59301a6c311SAlfredo Cardigliano 	 */
594924e6b76SThomas Monjalon 	total_size += rte_mem_page_size();
59501a6c311SAlfredo Cardigliano 
59601a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
597924e6b76SThomas Monjalon 		total_size += RTE_ALIGN(sg_size, rte_mem_page_size());
598924e6b76SThomas Monjalon 		total_size += rte_mem_page_size();
59901a6c311SAlfredo Cardigliano 	}
60001a6c311SAlfredo Cardigliano 
601be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
60201a6c311SAlfredo Cardigliano 	if (!new) {
60301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
60401a6c311SAlfredo Cardigliano 		return -ENOMEM;
60501a6c311SAlfredo Cardigliano 	}
60601a6c311SAlfredo Cardigliano 
60701a6c311SAlfredo Cardigliano 	new->lif = lif;
60801a6c311SAlfredo Cardigliano 
6097b20fc2fSAndrew Boyer 	/* Most queue types will store 1 ptr per descriptor */
610be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
6117b20fc2fSAndrew Boyer 				num_descs * num_segs, sizeof(void *),
612924e6b76SThomas Monjalon 				rte_mem_page_size(), socket_id);
61301a6c311SAlfredo Cardigliano 	if (!new->q.info) {
61401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6154c8f8d57SAndrew Boyer 		err = -ENOMEM;
6164c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
61701a6c311SAlfredo Cardigliano 	}
61801a6c311SAlfredo Cardigliano 
619d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
62001a6c311SAlfredo Cardigliano 	new->q.type = type;
62101a6c311SAlfredo Cardigliano 
6224ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
62301a6c311SAlfredo Cardigliano 	if (err) {
62401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6254c8f8d57SAndrew Boyer 		goto err_out_free_info;
62601a6c311SAlfredo Cardigliano 	}
62701a6c311SAlfredo Cardigliano 
6282aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
62901a6c311SAlfredo Cardigliano 	if (err) {
63001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6314c8f8d57SAndrew Boyer 		goto err_out_free_info;
63201a6c311SAlfredo Cardigliano 	}
63301a6c311SAlfredo Cardigliano 
63401a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6354ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
63601a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
63701a6c311SAlfredo Cardigliano 
63801a6c311SAlfredo Cardigliano 	if (!new->base_z) {
63901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
64001a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6414c8f8d57SAndrew Boyer 		goto err_out_free_info;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
64401a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
64501a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
64601a6c311SAlfredo Cardigliano 
64701a6c311SAlfredo Cardigliano 	q_base = new->base;
64801a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
64901a6c311SAlfredo Cardigliano 
650924e6b76SThomas Monjalon 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size,
651924e6b76SThomas Monjalon 			rte_mem_page_size());
652924e6b76SThomas Monjalon 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size,
653924e6b76SThomas Monjalon 			rte_mem_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,
657924e6b76SThomas Monjalon 				rte_mem_page_size());
658924e6b76SThomas Monjalon 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size,
659924e6b76SThomas Monjalon 				rte_mem_page_size());
66001a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
66101a6c311SAlfredo Cardigliano 	}
66201a6c311SAlfredo Cardigliano 
663*9de21005SAndrew Boyer 	if (flags & IONIC_QCQ_F_CMB) {
664*9de21005SAndrew Boyer 		/* alloc descriptor ring from nic memory */
665*9de21005SAndrew Boyer 		if (lif->adapter->cmb_offset + q_size >
666*9de21005SAndrew Boyer 				lif->adapter->bars.bar[2].len) {
667*9de21005SAndrew Boyer 			IONIC_PRINT(ERR, "Cannot reserve queue from NIC mem");
668*9de21005SAndrew Boyer 			return -ENOMEM;
669*9de21005SAndrew Boyer 		}
670*9de21005SAndrew Boyer 		q_base = (void *)
671*9de21005SAndrew Boyer 			((uintptr_t)lif->adapter->bars.bar[2].vaddr +
672*9de21005SAndrew Boyer 			 (uintptr_t)lif->adapter->cmb_offset);
673*9de21005SAndrew Boyer 		/* CMB PA is a relative address */
674*9de21005SAndrew Boyer 		q_base_pa = lif->adapter->cmb_offset;
675*9de21005SAndrew Boyer 		lif->adapter->cmb_offset += q_size;
676*9de21005SAndrew Boyer 	}
677*9de21005SAndrew Boyer 
6784ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6794ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68001a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68101a6c311SAlfredo Cardigliano 
68201a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
68301a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
68401a6c311SAlfredo Cardigliano 
68501a6c311SAlfredo Cardigliano 	*qcq = new;
68601a6c311SAlfredo Cardigliano 
68701a6c311SAlfredo Cardigliano 	return 0;
68801a6c311SAlfredo Cardigliano 
6894c8f8d57SAndrew Boyer err_out_free_info:
6904c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6914c8f8d57SAndrew Boyer err_out_free_qcq:
6924c8f8d57SAndrew Boyer 	rte_free(new);
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	return err;
69501a6c311SAlfredo Cardigliano }
69601a6c311SAlfredo Cardigliano 
69701a6c311SAlfredo Cardigliano void
69801a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
69901a6c311SAlfredo Cardigliano {
70001a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70101a6c311SAlfredo Cardigliano 		qcq->base = NULL;
70201a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
70301a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
70401a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
70501a6c311SAlfredo Cardigliano 	}
70601a6c311SAlfredo Cardigliano 
70701a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
70801a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
70901a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71001a6c311SAlfredo Cardigliano 	}
71101a6c311SAlfredo Cardigliano 
71201a6c311SAlfredo Cardigliano 	rte_free(qcq);
71301a6c311SAlfredo Cardigliano }
71401a6c311SAlfredo Cardigliano 
7157b20fc2fSAndrew Boyer static uint64_t
7167b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif)
7177b20fc2fSAndrew Boyer {
7187b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7197b20fc2fSAndrew Boyer 
7207b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7217b20fc2fSAndrew Boyer 
7227b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7237b20fc2fSAndrew Boyer 	rxm.data_off = RTE_PKTMBUF_HEADROOM;
7247b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7257b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7267b20fc2fSAndrew Boyer 
7277b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7287b20fc2fSAndrew Boyer 
7297b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7307b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7317b20fc2fSAndrew Boyer }
7327b20fc2fSAndrew Boyer 
7337b20fc2fSAndrew Boyer static uint64_t
7347b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif)
7357b20fc2fSAndrew Boyer {
7367b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7377b20fc2fSAndrew Boyer 
7387b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7397b20fc2fSAndrew Boyer 
7407b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7417b20fc2fSAndrew Boyer 	rxm.data_off = 0;  /* no headroom */
7427b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7437b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7447b20fc2fSAndrew Boyer 
7457b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7467b20fc2fSAndrew Boyer 
7477b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7487b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7497b20fc2fSAndrew Boyer }
7507b20fc2fSAndrew Boyer 
751a27d9013SAlfredo Cardigliano int
7528ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
753d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
754d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
755a27d9013SAlfredo Cardigliano {
756be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
757d5850081SAndrew Boyer 	uint16_t flags, seg_size, hdr_seg_size, max_segs, max_segs_fw;
758d5850081SAndrew Boyer 	uint32_t max_mtu;
759be39f75cSAndrew Boyer 	int err;
760a27d9013SAlfredo Cardigliano 
761a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
762*9de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
763*9de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
764b671e69aSAndrew Boyer 
765d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
766d5850081SAndrew Boyer 
767d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
768d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
769d5850081SAndrew Boyer 
770d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
771d5850081SAndrew Boyer 
772d5850081SAndrew Boyer 	max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
773d5850081SAndrew Boyer 
774d5850081SAndrew Boyer 	/*
775d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
7767b20fc2fSAndrew Boyer 	 * This is the worst-case number, so that there's enough room in
7777b20fc2fSAndrew Boyer 	 * the info array.
778d5850081SAndrew Boyer 	 */
779d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
780d5850081SAndrew Boyer 
7817b20fc2fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
7827b20fc2fSAndrew Boyer 		index, max_mtu, seg_size, max_segs);
783d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
784d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
785d5850081SAndrew Boyer 			max_segs, max_segs_fw);
786d5850081SAndrew Boyer 		return -EINVAL;
787d5850081SAndrew Boyer 	}
788d5850081SAndrew Boyer 
7894ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7904ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
791be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7928ec5ad7fSAndrew Boyer 		socket_id,
7934ad56b7aSAndrew Boyer 		index,
7944ad56b7aSAndrew Boyer 		"rx",
7954ad56b7aSAndrew Boyer 		flags,
796a27d9013SAlfredo Cardigliano 		nrxq_descs,
797d5850081SAndrew Boyer 		max_segs,
798a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
799a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
800a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
801be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
802a27d9013SAlfredo Cardigliano 	if (err)
803a27d9013SAlfredo Cardigliano 		return err;
804a27d9013SAlfredo Cardigliano 
805be39f75cSAndrew Boyer 	rxq->flags = flags;
806d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
807d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
8087b20fc2fSAndrew Boyer 	rxq->rearm_data = ionic_rx_rearm_data(lif);
8097b20fc2fSAndrew Boyer 	rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
810be39f75cSAndrew Boyer 
811be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
812be39f75cSAndrew Boyer 	*rxq_out = rxq;
813a27d9013SAlfredo Cardigliano 
814a27d9013SAlfredo Cardigliano 	return 0;
815a27d9013SAlfredo Cardigliano }
816a27d9013SAlfredo Cardigliano 
817a27d9013SAlfredo Cardigliano int
8188ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
819be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
820a27d9013SAlfredo Cardigliano {
821be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
822e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
823be39f75cSAndrew Boyer 	int err;
824a27d9013SAlfredo Cardigliano 
825a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
826*9de21005SAndrew Boyer 	if (lif->state & IONIC_LIF_F_Q_IN_CMB)
827*9de21005SAndrew Boyer 		flags |= IONIC_QCQ_F_CMB;
828e19eea1eSAndrew Boyer 
829e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
830e19eea1eSAndrew Boyer 
8314ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8324ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
833be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
8348ec5ad7fSAndrew Boyer 		socket_id,
8354ad56b7aSAndrew Boyer 		index,
8364ad56b7aSAndrew Boyer 		"tx",
8374ad56b7aSAndrew Boyer 		flags,
838a27d9013SAlfredo Cardigliano 		ntxq_descs,
839b4beb84aSAndrew Boyer 		num_segs_fw,
840a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
841a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
84256117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
843be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
844a27d9013SAlfredo Cardigliano 	if (err)
845a27d9013SAlfredo Cardigliano 		return err;
846a27d9013SAlfredo Cardigliano 
847be39f75cSAndrew Boyer 	txq->flags = flags;
848e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
849be39f75cSAndrew Boyer 
850be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
851be39f75cSAndrew Boyer 	*txq_out = txq;
852a27d9013SAlfredo Cardigliano 
853a27d9013SAlfredo Cardigliano 	return 0;
854a27d9013SAlfredo Cardigliano }
855a27d9013SAlfredo Cardigliano 
85601a6c311SAlfredo Cardigliano static int
85701a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
85801a6c311SAlfredo Cardigliano {
859be39f75cSAndrew Boyer 	uint16_t flags = 0;
860be39f75cSAndrew Boyer 	int err;
86101a6c311SAlfredo Cardigliano 
8624ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8634ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
864be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8658ec5ad7fSAndrew Boyer 		rte_socket_id(),
8664ad56b7aSAndrew Boyer 		0,
8674ad56b7aSAndrew Boyer 		"admin",
8684ad56b7aSAndrew Boyer 		flags,
86901a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
870d5850081SAndrew Boyer 		1,
87101a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
87201a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
87301a6c311SAlfredo Cardigliano 		0,
874be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
87527b942c8SAlfredo Cardigliano 	if (err)
87627b942c8SAlfredo Cardigliano 		return err;
87701a6c311SAlfredo Cardigliano 
87827b942c8SAlfredo Cardigliano 	return 0;
87927b942c8SAlfredo Cardigliano }
88027b942c8SAlfredo Cardigliano 
88127b942c8SAlfredo Cardigliano static int
88227b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
88327b942c8SAlfredo Cardigliano {
884be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8854c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
886be39f75cSAndrew Boyer 	uint16_t flags = 0;
887be39f75cSAndrew Boyer 	int err;
88827b942c8SAlfredo Cardigliano 
8894ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8904ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
891be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8928ec5ad7fSAndrew Boyer 		rte_socket_id(),
8934ad56b7aSAndrew Boyer 		0,
8944ad56b7aSAndrew Boyer 		"notify",
89527b942c8SAlfredo Cardigliano 		flags,
89627b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
897d5850081SAndrew Boyer 		1,
89827b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
89927b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
90027b942c8SAlfredo Cardigliano 		0,
901be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
90201a6c311SAlfredo Cardigliano 	if (err)
90301a6c311SAlfredo Cardigliano 		return err;
90401a6c311SAlfredo Cardigliano 
9054c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
9064c8f8d57SAndrew Boyer 	if (err) {
907be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
9084c8f8d57SAndrew Boyer 		return err;
9094c8f8d57SAndrew Boyer 	}
9104c8f8d57SAndrew Boyer 
9114c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
9124c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
9134c8f8d57SAndrew Boyer 
9144c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
9154c8f8d57SAndrew Boyer 
91601a6c311SAlfredo Cardigliano 	return 0;
91701a6c311SAlfredo Cardigliano }
91801a6c311SAlfredo Cardigliano 
919c5d15850SAndrew Boyer static void
920c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
921c5d15850SAndrew Boyer {
922c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
923c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
924c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
925c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
926c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
927c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
928c5d15850SAndrew Boyer 	int err;
929c5d15850SAndrew Boyer 
930c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
931c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
932c5d15850SAndrew Boyer 
933c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
934c5d15850SAndrew Boyer 		switch (qtype) {
935c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
936c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
937c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
938c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
939c5d15850SAndrew Boyer 			break;
940c5d15850SAndrew Boyer 		default:
941c5d15850SAndrew Boyer 			continue;
942c5d15850SAndrew Boyer 		}
943c5d15850SAndrew Boyer 
944c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
945c5d15850SAndrew Boyer 
946c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
947c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
948c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
949c5d15850SAndrew Boyer 		if (err == -EINVAL) {
950c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
951c5d15850SAndrew Boyer 			continue;
952c5d15850SAndrew Boyer 		} else if (err == -EIO) {
953c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
954c5d15850SAndrew Boyer 			return;
955c5d15850SAndrew Boyer 		} else if (err) {
956c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
957c5d15850SAndrew Boyer 				qtype, err);
958c5d15850SAndrew Boyer 			return;
959c5d15850SAndrew Boyer 		}
960c5d15850SAndrew Boyer 
961c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
962c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
963c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
964c5d15850SAndrew Boyer 
965c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
966c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
967c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
968c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
969c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
970c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
971c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
972c5d15850SAndrew Boyer 		qti->sg_desc_stride =
973c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
974c5d15850SAndrew Boyer 
975c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
976c5d15850SAndrew Boyer 			qtype, qti->version);
977c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
978c5d15850SAndrew Boyer 			qtype, qti->supported);
979c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
980c5d15850SAndrew Boyer 			qtype, qti->features);
981c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
982c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
983c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
984c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
985c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
986c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
987c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
988c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
989c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
990c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
991c5d15850SAndrew Boyer 	}
992c5d15850SAndrew Boyer }
993c5d15850SAndrew Boyer 
994669c8de6SAlfredo Cardigliano int
995669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
996669c8de6SAlfredo Cardigliano {
997c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
998669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
99901a6c311SAlfredo Cardigliano 	int err;
1000669c8de6SAlfredo Cardigliano 
10014ae96cb8SAndrew Boyer 	/*
10024ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
10034ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
10044ae96cb8SAndrew Boyer 	 */
10054ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
10064ae96cb8SAndrew Boyer 
10074ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
1008669c8de6SAlfredo Cardigliano 
1009c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
1010c5d15850SAndrew Boyer 
101156117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
101256117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
101356117636SAndrew Boyer 		return -ENXIO;
101456117636SAndrew Boyer 	}
101556117636SAndrew Boyer 
1016*9de21005SAndrew Boyer 	if (adapter->q_in_cmb) {
1017*9de21005SAndrew Boyer 		if (adapter->bars.num_bars >= 3 &&
1018*9de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_RXQ].version >= 2 &&
1019*9de21005SAndrew Boyer 		    lif->qtype_info[IONIC_QTYPE_TXQ].version >= 3) {
1020*9de21005SAndrew Boyer 			IONIC_PRINT(INFO, "%s enabled on %s",
1021*9de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
1022*9de21005SAndrew Boyer 			lif->state |= IONIC_LIF_F_Q_IN_CMB;
1023*9de21005SAndrew Boyer 		} else {
1024*9de21005SAndrew Boyer 			IONIC_PRINT(ERR, "%s not supported on %s, disabled",
1025*9de21005SAndrew Boyer 				PMD_IONIC_CMB_KVARG, lif->name);
1026*9de21005SAndrew Boyer 		}
1027*9de21005SAndrew Boyer 	}
1028*9de21005SAndrew Boyer 
1029669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
1030669c8de6SAlfredo Cardigliano 
103101a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
103201a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
103301a6c311SAlfredo Cardigliano 
103484cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
1035c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
1036c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1037c67719e1SAlfredo Cardigliano 		return -ENOMEM;
1038c67719e1SAlfredo Cardigliano 	}
1039c67719e1SAlfredo Cardigliano 
1040a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
1041a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
1042a27d9013SAlfredo Cardigliano 
1043a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
1044a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1045a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1046a27d9013SAlfredo Cardigliano 	}
1047a27d9013SAlfredo Cardigliano 
1048a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
1049a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
1050a27d9013SAlfredo Cardigliano 
1051a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
1052a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1053a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1054a27d9013SAlfredo Cardigliano 	}
1055a27d9013SAlfredo Cardigliano 
105627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
105727b942c8SAlfredo Cardigliano 
105827b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
105927b942c8SAlfredo Cardigliano 	if (err) {
106027b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
106127b942c8SAlfredo Cardigliano 		return err;
106227b942c8SAlfredo Cardigliano 	}
106327b942c8SAlfredo Cardigliano 
106427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
106527b942c8SAlfredo Cardigliano 
106601a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
106701a6c311SAlfredo Cardigliano 	if (err) {
106801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
106901a6c311SAlfredo Cardigliano 		return err;
107001a6c311SAlfredo Cardigliano 	}
107101a6c311SAlfredo Cardigliano 
107201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
107301a6c311SAlfredo Cardigliano 
1074924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1075669c8de6SAlfredo Cardigliano 
1076669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1077669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1078669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1079669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1080669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1081669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1082669c8de6SAlfredo Cardigliano 	}
1083669c8de6SAlfredo Cardigliano 
1084669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1085669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1086669c8de6SAlfredo Cardigliano 
1087669c8de6SAlfredo Cardigliano 	return 0;
1088669c8de6SAlfredo Cardigliano }
1089669c8de6SAlfredo Cardigliano 
1090669c8de6SAlfredo Cardigliano void
1091669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1092669c8de6SAlfredo Cardigliano {
109327b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1094be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
109527b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
109627b942c8SAlfredo Cardigliano 	}
109727b942c8SAlfredo Cardigliano 
109801a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1099be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
110001a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
110101a6c311SAlfredo Cardigliano 	}
110201a6c311SAlfredo Cardigliano 
1103a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1104a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1105a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1106a27d9013SAlfredo Cardigliano 	}
1107a27d9013SAlfredo Cardigliano 
1108a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1109a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1110a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1111a27d9013SAlfredo Cardigliano 	}
1112a27d9013SAlfredo Cardigliano 
1113669c8de6SAlfredo Cardigliano 	if (lif->info) {
1114669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1115669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1116669c8de6SAlfredo Cardigliano 	}
1117669c8de6SAlfredo Cardigliano }
1118669c8de6SAlfredo Cardigliano 
1119175e4e7eSAndrew Boyer void
1120175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1121175e4e7eSAndrew Boyer {
1122175e4e7eSAndrew Boyer 	uint32_t i;
1123175e4e7eSAndrew Boyer 
1124175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
11257483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1126175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1127175e4e7eSAndrew Boyer 	}
1128175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
11297483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1130175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1131175e4e7eSAndrew Boyer 	}
1132175e4e7eSAndrew Boyer }
1133175e4e7eSAndrew Boyer 
113422e7171bSAlfredo Cardigliano int
113522e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
113622e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
113722e7171bSAlfredo Cardigliano {
113809f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
113922e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
114022e7171bSAlfredo Cardigliano 		.pending_work = true,
114122e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
114222e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
114322e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
114409f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
114509f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
114622e7171bSAlfredo Cardigliano 		},
114722e7171bSAlfredo Cardigliano 	};
114822e7171bSAlfredo Cardigliano 	unsigned int i;
114909f806e9SAndrew Boyer 	uint16_t tbl_sz =
115009f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
115122e7171bSAlfredo Cardigliano 
115222e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
115322e7171bSAlfredo Cardigliano 
115422e7171bSAlfredo Cardigliano 	lif->rss_types = types;
115522e7171bSAlfredo Cardigliano 
115622e7171bSAlfredo Cardigliano 	if (key)
115722e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
115822e7171bSAlfredo Cardigliano 
115922e7171bSAlfredo Cardigliano 	if (indir)
116009f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
116122e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
116222e7171bSAlfredo Cardigliano 
116322e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
116422e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
116522e7171bSAlfredo Cardigliano 
116622e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
116722e7171bSAlfredo Cardigliano }
116822e7171bSAlfredo Cardigliano 
116922e7171bSAlfredo Cardigliano static int
117022e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
117122e7171bSAlfredo Cardigliano {
117209f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
117322e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
117422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
117522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
117622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
117722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
117822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
117922e7171bSAlfredo Cardigliano 	};
118022e7171bSAlfredo Cardigliano 	uint32_t i;
118109f806e9SAndrew Boyer 	uint16_t tbl_sz =
118209f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
118322e7171bSAlfredo Cardigliano 
118422e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
118522e7171bSAlfredo Cardigliano 
11863d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
118722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11883d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11893d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11903d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
119122e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
119222e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
119322e7171bSAlfredo Cardigliano 			return -ENOMEM;
119422e7171bSAlfredo Cardigliano 		}
119522e7171bSAlfredo Cardigliano 
119622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
119722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11983d845eddSAndrew Boyer 	}
11993d845eddSAndrew Boyer 
12003d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
12013d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
120222e7171bSAlfredo Cardigliano 
120322e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
12043d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
120522e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
12063d845eddSAndrew Boyer 	}
120722e7171bSAlfredo Cardigliano 
12083d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
120922e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
121022e7171bSAlfredo Cardigliano }
121122e7171bSAlfredo Cardigliano 
121222e7171bSAlfredo Cardigliano static void
121322e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
121422e7171bSAlfredo Cardigliano {
121522e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
121622e7171bSAlfredo Cardigliano 		return;
121722e7171bSAlfredo Cardigliano 
121822e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
121922e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
122022e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
122122e7171bSAlfredo Cardigliano 
122222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
122322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
122422e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
122522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
122622e7171bSAlfredo Cardigliano 	}
122722e7171bSAlfredo Cardigliano }
122822e7171bSAlfredo Cardigliano 
1229be39f75cSAndrew Boyer void
1230be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1231be39f75cSAndrew Boyer {
1232e7222f94SAndrew Boyer 	ionic_qcq_disable(&txq->qcq);
1233e7222f94SAndrew Boyer 
1234be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1235be39f75cSAndrew Boyer }
1236be39f75cSAndrew Boyer 
1237be39f75cSAndrew Boyer void
1238be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1239be39f75cSAndrew Boyer {
1240e7222f94SAndrew Boyer 	ionic_qcq_disable(&rxq->qcq);
1241e7222f94SAndrew Boyer 
1242be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1243be39f75cSAndrew Boyer }
1244be39f75cSAndrew Boyer 
124501a6c311SAlfredo Cardigliano static void
1246be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
124701a6c311SAlfredo Cardigliano {
1248be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
12494c8f8d57SAndrew Boyer }
12504c8f8d57SAndrew Boyer 
12514c8f8d57SAndrew Boyer static void
12524c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
12534c8f8d57SAndrew Boyer {
1254be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
12554c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
12564c8f8d57SAndrew Boyer 
12574c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
12584c8f8d57SAndrew Boyer 		return;
12594c8f8d57SAndrew Boyer 
12604c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
12614c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
12624c8f8d57SAndrew Boyer 
12634c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1264a27d9013SAlfredo Cardigliano }
1265a27d9013SAlfredo Cardigliano 
126601a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
126701a6c311SAlfredo Cardigliano int
126801a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
126901a6c311SAlfredo Cardigliano 		void *cb_arg)
127001a6c311SAlfredo Cardigliano {
127101a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
127201a6c311SAlfredo Cardigliano 	uint32_t work_done;
127301a6c311SAlfredo Cardigliano 
127401a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
127501a6c311SAlfredo Cardigliano 
127601a6c311SAlfredo Cardigliano 	return work_done;
127701a6c311SAlfredo Cardigliano }
127801a6c311SAlfredo Cardigliano 
127927b942c8SAlfredo Cardigliano static void
128027b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
128127b942c8SAlfredo Cardigliano {
128227b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
128327b942c8SAlfredo Cardigliano 	bool link_up;
128427b942c8SAlfredo Cardigliano 
128527b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
128627b942c8SAlfredo Cardigliano 
128727b942c8SAlfredo Cardigliano 	if (!lif->info)
128827b942c8SAlfredo Cardigliano 		return;
128927b942c8SAlfredo Cardigliano 
129027b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
129127b942c8SAlfredo Cardigliano 
129227b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
129327b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
129427b942c8SAlfredo Cardigliano 		return;
129527b942c8SAlfredo Cardigliano 
129627b942c8SAlfredo Cardigliano 	if (link_up) {
129709f806e9SAndrew Boyer 		adapter->link_speed =
129809f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1299be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1300be63459eSAndrew Boyer 			adapter->link_speed);
130127b942c8SAlfredo Cardigliano 	} else {
130227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
130327b942c8SAlfredo Cardigliano 	}
130427b942c8SAlfredo Cardigliano 
130527b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1306be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1307be63459eSAndrew Boyer }
1308be63459eSAndrew Boyer 
1309be63459eSAndrew Boyer static void
1310be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1311be63459eSAndrew Boyer {
1312be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1313be63459eSAndrew Boyer 		return;
1314be63459eSAndrew Boyer 
1315be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1316be63459eSAndrew Boyer 
1317be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1318be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1319be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1320be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1321be63459eSAndrew Boyer 	}
1322be63459eSAndrew Boyer 
1323be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
132427b942c8SAlfredo Cardigliano }
132527b942c8SAlfredo Cardigliano 
132627b942c8SAlfredo Cardigliano static bool
13274ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
132827b942c8SAlfredo Cardigliano {
132927b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
133027b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
133127b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
133227b942c8SAlfredo Cardigliano 
133327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
133427b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
133527b942c8SAlfredo Cardigliano 
133627b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
133727b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
133827b942c8SAlfredo Cardigliano 		return false;
133927b942c8SAlfredo Cardigliano 
134027b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
134127b942c8SAlfredo Cardigliano 
134227b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
134327b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
134427b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1345be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1346be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1347be63459eSAndrew Boyer 			lif->name,
134827b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
134927b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
135027b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
135127b942c8SAlfredo Cardigliano 
135227b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
135327b942c8SAlfredo Cardigliano 		break;
1354be63459eSAndrew Boyer 
1355be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1356be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1357be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1358be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1359be63459eSAndrew Boyer 			lif->name,
1360be63459eSAndrew Boyer 			cq_desc->event.eid,
1361be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1362be63459eSAndrew Boyer 			cq_desc->reset.state);
1363be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1364be63459eSAndrew Boyer 		break;
1365be63459eSAndrew Boyer 
136627b942c8SAlfredo Cardigliano 	default:
136727b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
136827b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
136927b942c8SAlfredo Cardigliano 		break;
137027b942c8SAlfredo Cardigliano 	}
137127b942c8SAlfredo Cardigliano 
137227b942c8SAlfredo Cardigliano 	return true;
137327b942c8SAlfredo Cardigliano }
137427b942c8SAlfredo Cardigliano 
137527b942c8SAlfredo Cardigliano int
137627b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
137727b942c8SAlfredo Cardigliano {
137827b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1379be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
138027b942c8SAlfredo Cardigliano 	uint32_t work_done;
138127b942c8SAlfredo Cardigliano 
1382be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
138327b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
138427b942c8SAlfredo Cardigliano 		return -1;
138527b942c8SAlfredo Cardigliano 	}
138627b942c8SAlfredo Cardigliano 
1387be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
138827b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
138927b942c8SAlfredo Cardigliano 
1390be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1391be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
139227b942c8SAlfredo Cardigliano 
139327b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
139427b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
139527b942c8SAlfredo Cardigliano 
1396be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
139727b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
139827b942c8SAlfredo Cardigliano 
1399be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
140027b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
140127b942c8SAlfredo Cardigliano 
140227b942c8SAlfredo Cardigliano 	return 0;
140327b942c8SAlfredo Cardigliano }
140427b942c8SAlfredo Cardigliano 
140501a6c311SAlfredo Cardigliano static int
140601a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
140701a6c311SAlfredo Cardigliano {
140801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1409be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1410be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
141101a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
141201a6c311SAlfredo Cardigliano 	int err;
141301a6c311SAlfredo Cardigliano 
1414be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
141501a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
141601a6c311SAlfredo Cardigliano 	if (err)
141701a6c311SAlfredo Cardigliano 		return err;
141801a6c311SAlfredo Cardigliano 
141901a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
142001a6c311SAlfredo Cardigliano 
142101a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
142209f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
142301a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
142401a6c311SAlfredo Cardigliano 
142501a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
142601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
142701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
142801a6c311SAlfredo Cardigliano 
1429be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
143001a6c311SAlfredo Cardigliano 
143101a6c311SAlfredo Cardigliano 	return 0;
143201a6c311SAlfredo Cardigliano }
143301a6c311SAlfredo Cardigliano 
143427b942c8SAlfredo Cardigliano static int
143527b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
143627b942c8SAlfredo Cardigliano {
143727b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1438be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1439be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
14400a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
144127b942c8SAlfredo Cardigliano 	int err;
144227b942c8SAlfredo Cardigliano 
144327b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
144427b942c8SAlfredo Cardigliano 		.pending_work = true,
144527b942c8SAlfredo Cardigliano 		.cmd.q_init = {
144627b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
144727b942c8SAlfredo Cardigliano 			.type = q->type,
1448c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
144909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
14500a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
145127b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
145209f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
145327b942c8SAlfredo Cardigliano 		}
145427b942c8SAlfredo Cardigliano 	};
145527b942c8SAlfredo Cardigliano 
14560a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
14570a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
14580a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
14590a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
14600a00bdafSAndrew Boyer 	}
14610a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
14620a00bdafSAndrew Boyer 
146309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
146409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
146527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
146627b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14674ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
146827b942c8SAlfredo Cardigliano 
146927b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
147027b942c8SAlfredo Cardigliano 	if (err)
147127b942c8SAlfredo Cardigliano 		return err;
147227b942c8SAlfredo Cardigliano 
147327b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
147409f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
147527b942c8SAlfredo Cardigliano 	q->db = NULL;
147627b942c8SAlfredo Cardigliano 
147727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
147827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
147927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
148027b942c8SAlfredo Cardigliano 
1481be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
148227b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
148327b942c8SAlfredo Cardigliano 
1484be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
148527b942c8SAlfredo Cardigliano 
148627b942c8SAlfredo Cardigliano 	return 0;
148727b942c8SAlfredo Cardigliano }
148827b942c8SAlfredo Cardigliano 
1489669c8de6SAlfredo Cardigliano int
1490598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1491598f6726SAlfredo Cardigliano {
1492598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1493598f6726SAlfredo Cardigliano 		.pending_work = true,
1494598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1495598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1496598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
149709f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1498598f6726SAlfredo Cardigliano 		},
1499598f6726SAlfredo Cardigliano 	};
1500598f6726SAlfredo Cardigliano 	int err;
1501598f6726SAlfredo Cardigliano 
1502598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1503598f6726SAlfredo Cardigliano 	if (err)
1504598f6726SAlfredo Cardigliano 		return err;
1505598f6726SAlfredo Cardigliano 
150609f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1507598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1508598f6726SAlfredo Cardigliano 
1509598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1510598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1511598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1512598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1513598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1514598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1515598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1516598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1517598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1518598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1519598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1520598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1521598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1522598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1523598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1524598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1525598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1526598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1527598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1528598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1529598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1530598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1531598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1532598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1533598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1534598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1535598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1536598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1537598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1538598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1539598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1540598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1541598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1542598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1543598f6726SAlfredo Cardigliano 
1544598f6726SAlfredo Cardigliano 	return 0;
1545598f6726SAlfredo Cardigliano }
1546598f6726SAlfredo Cardigliano 
1547a27d9013SAlfredo Cardigliano int
1548be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1549a27d9013SAlfredo Cardigliano {
1550be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1551a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1552a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1553a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1554a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1555a27d9013SAlfredo Cardigliano 		.pending_work = true,
1556a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1557a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1558a27d9013SAlfredo Cardigliano 			.type = q->type,
1559c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
156009f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
156109f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
156209f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
156309f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1564a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
156509f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
156609f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
156709f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1568a27d9013SAlfredo Cardigliano 		},
1569a27d9013SAlfredo Cardigliano 	};
1570a27d9013SAlfredo Cardigliano 	int err;
1571a27d9013SAlfredo Cardigliano 
1572*9de21005SAndrew Boyer 	if (txq->flags & IONIC_QCQ_F_CMB)
1573*9de21005SAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1574*9de21005SAndrew Boyer 
157509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
157609f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1577a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1578a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15794ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1580a27d9013SAlfredo Cardigliano 
1581e7222f94SAndrew Boyer 	ionic_q_reset(q);
1582e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1583e7222f94SAndrew Boyer 
1584be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1585a27d9013SAlfredo Cardigliano 	if (err)
1586a27d9013SAlfredo Cardigliano 		return err;
1587a27d9013SAlfredo Cardigliano 
1588a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
158909f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1590a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1591a27d9013SAlfredo Cardigliano 
1592a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1593a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1594a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1595a27d9013SAlfredo Cardigliano 
1596be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1597a27d9013SAlfredo Cardigliano 
1598a27d9013SAlfredo Cardigliano 	return 0;
1599a27d9013SAlfredo Cardigliano }
1600a27d9013SAlfredo Cardigliano 
1601a27d9013SAlfredo Cardigliano int
1602be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1603a27d9013SAlfredo Cardigliano {
1604be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1605a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1606a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1607a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1608a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1609a27d9013SAlfredo Cardigliano 		.pending_work = true,
1610a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1611a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1612a27d9013SAlfredo Cardigliano 			.type = q->type,
1613c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
161409f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
161509f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
161609f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
161709f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1618a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
161909f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
162009f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
162109f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1622a27d9013SAlfredo Cardigliano 		},
1623a27d9013SAlfredo Cardigliano 	};
1624a27d9013SAlfredo Cardigliano 	int err;
1625a27d9013SAlfredo Cardigliano 
1626*9de21005SAndrew Boyer 	if (rxq->flags & IONIC_QCQ_F_CMB)
1627*9de21005SAndrew Boyer 		ctx.cmd.q_init.flags |= rte_cpu_to_le_16(IONIC_QINIT_F_CMB);
1628*9de21005SAndrew Boyer 
162909f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
163009f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1631a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1632a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
16334ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1634a27d9013SAlfredo Cardigliano 
1635e7222f94SAndrew Boyer 	ionic_q_reset(q);
1636e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1637e7222f94SAndrew Boyer 
1638be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1639a27d9013SAlfredo Cardigliano 	if (err)
1640a27d9013SAlfredo Cardigliano 		return err;
1641a27d9013SAlfredo Cardigliano 
1642a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
164309f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1644a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1645a27d9013SAlfredo Cardigliano 
1646be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1647a27d9013SAlfredo Cardigliano 
1648a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1649a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1650a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1651a27d9013SAlfredo Cardigliano 
1652a27d9013SAlfredo Cardigliano 	return 0;
1653a27d9013SAlfredo Cardigliano }
1654a27d9013SAlfredo Cardigliano 
1655598f6726SAlfredo Cardigliano static int
1656598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1657598f6726SAlfredo Cardigliano {
1658598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1659598f6726SAlfredo Cardigliano 		.pending_work = true,
1660598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1661598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1662598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1663598f6726SAlfredo Cardigliano 		},
1664598f6726SAlfredo Cardigliano 	};
1665598f6726SAlfredo Cardigliano 	int err;
1666598f6726SAlfredo Cardigliano 
1667598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1668598f6726SAlfredo Cardigliano 
1669598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1670598f6726SAlfredo Cardigliano 	if (err)
1671598f6726SAlfredo Cardigliano 		return err;
1672598f6726SAlfredo Cardigliano 
1673598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1674598f6726SAlfredo Cardigliano 
1675598f6726SAlfredo Cardigliano 	return 0;
1676598f6726SAlfredo Cardigliano }
1677598f6726SAlfredo Cardigliano 
1678598f6726SAlfredo Cardigliano static void
1679598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1680598f6726SAlfredo Cardigliano {
1681598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1682598f6726SAlfredo Cardigliano 		.pending_work = true,
1683598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1684598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1685598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1686598f6726SAlfredo Cardigliano 		},
1687598f6726SAlfredo Cardigliano 	};
1688598f6726SAlfredo Cardigliano 
16894ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
16904ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1691598f6726SAlfredo Cardigliano 
1692598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1693598f6726SAlfredo Cardigliano }
1694598f6726SAlfredo Cardigliano 
1695598f6726SAlfredo Cardigliano int
1696669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1697669c8de6SAlfredo Cardigliano {
1698669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1699656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
1700669c8de6SAlfredo Cardigliano 	int err;
1701669c8de6SAlfredo Cardigliano 
17023cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
17033cdfd905SAlfredo Cardigliano 
170400b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1705669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1706669c8de6SAlfredo Cardigliano 	if (err)
1707669c8de6SAlfredo Cardigliano 		return err;
1708669c8de6SAlfredo Cardigliano 
1709656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1710656bfc9aSAndrew Boyer 
171109f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1712669c8de6SAlfredo Cardigliano 
171301a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
171401a6c311SAlfredo Cardigliano 	if (err)
171501a6c311SAlfredo Cardigliano 		return err;
171601a6c311SAlfredo Cardigliano 
171727b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
171827b942c8SAlfredo Cardigliano 	if (err)
171927b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
172027b942c8SAlfredo Cardigliano 
172118a44465SAndrew Boyer 	/*
172218a44465SAndrew Boyer 	 * Configure initial feature set
172318a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
172418a44465SAndrew Boyer 	 */
172518a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1726598f6726SAlfredo Cardigliano 
1727598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1728598f6726SAlfredo Cardigliano 	if (err)
1729598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1730598f6726SAlfredo Cardigliano 
173154fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1732598f6726SAlfredo Cardigliano 	if (err)
1733598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1734598f6726SAlfredo Cardigliano 
173554fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
173654fe083fSAlfredo Cardigliano 	if (err)
173754fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
173854fe083fSAlfredo Cardigliano 
1739598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1740598f6726SAlfredo Cardigliano 
1741669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1742669c8de6SAlfredo Cardigliano 
1743669c8de6SAlfredo Cardigliano 	return 0;
174427b942c8SAlfredo Cardigliano 
174554fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
174654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
174754fe083fSAlfredo Cardigliano 
1748598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
17494c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1750598f6726SAlfredo Cardigliano 
175127b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1752be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
175327b942c8SAlfredo Cardigliano 
175427b942c8SAlfredo Cardigliano 	return err;
1755669c8de6SAlfredo Cardigliano }
1756669c8de6SAlfredo Cardigliano 
1757669c8de6SAlfredo Cardigliano void
1758669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1759669c8de6SAlfredo Cardigliano {
1760669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1761669c8de6SAlfredo Cardigliano 		return;
1762669c8de6SAlfredo Cardigliano 
176354fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
176422e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
17654c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1766be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
176701a6c311SAlfredo Cardigliano 
1768669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1769669c8de6SAlfredo Cardigliano }
1770669c8de6SAlfredo Cardigliano 
177118a44465SAndrew Boyer void
177218a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
177318a44465SAndrew Boyer {
177418a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
177518a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
177618a44465SAndrew Boyer 
177718a44465SAndrew Boyer 	/*
177818a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1779295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
178018a44465SAndrew Boyer 	 */
1781295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
178218a44465SAndrew Boyer 
1783295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1784295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
178518a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
178618a44465SAndrew Boyer 		else
178718a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
178818a44465SAndrew Boyer 	}
178918a44465SAndrew Boyer }
179018a44465SAndrew Boyer 
179118a44465SAndrew Boyer void
1792598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1793598f6726SAlfredo Cardigliano {
179418a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
179518a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
179622e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
179709f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
179822e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
179909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
180022e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
180109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
180222e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
180322e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
180422e7171bSAlfredo Cardigliano 
1805598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1806598f6726SAlfredo Cardigliano 
180722e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
180822e7171bSAlfredo Cardigliano 		lif->port_id);
180922e7171bSAlfredo Cardigliano 
181022e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
181122e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
181222e7171bSAlfredo Cardigliano 
181322e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
181422e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
181522e7171bSAlfredo Cardigliano 
181622e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
181722e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1818a27d9013SAlfredo Cardigliano 
181918a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
182018a44465SAndrew Boyer 
182118a44465SAndrew Boyer 	/*
182218a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
182318a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1824295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
182518a44465SAndrew Boyer 	 */
182618a44465SAndrew Boyer 
182718a44465SAndrew Boyer 	/* RX per-port */
182818a44465SAndrew Boyer 
1829295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1830295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1831295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
183218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
183318a44465SAndrew Boyer 	else
183418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
183518a44465SAndrew Boyer 
1836295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
183718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
183818a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
183918a44465SAndrew Boyer 	} else {
184018a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
184118a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
184218a44465SAndrew Boyer 	}
184318a44465SAndrew Boyer 
184418a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1845295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
184618a44465SAndrew Boyer 
184718a44465SAndrew Boyer 	/* TX per-port */
184818a44465SAndrew Boyer 
1849295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1850295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1851295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1852295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1853295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
185418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
185518a44465SAndrew Boyer 	else
185618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
185718a44465SAndrew Boyer 
1858295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
185918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
186018a44465SAndrew Boyer 	else
186118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
186218a44465SAndrew Boyer 
1863295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
186418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
186518a44465SAndrew Boyer 	else
186618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
186718a44465SAndrew Boyer 
1868295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
186918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
187018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
187118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
187218a44465SAndrew Boyer 	} else {
187318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
187418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
187518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
187618a44465SAndrew Boyer 	}
1877598f6726SAlfredo Cardigliano }
1878598f6726SAlfredo Cardigliano 
1879598f6726SAlfredo Cardigliano int
1880598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1881598f6726SAlfredo Cardigliano {
18820578335aSAndrew Boyer 	uint32_t rx_mode;
1883a27d9013SAlfredo Cardigliano 	uint32_t i;
1884a27d9013SAlfredo Cardigliano 	int err;
1885598f6726SAlfredo Cardigliano 
188622e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
188722e7171bSAlfredo Cardigliano 	if (err)
188822e7171bSAlfredo Cardigliano 		return err;
188922e7171bSAlfredo Cardigliano 
18900578335aSAndrew Boyer 	if (!lif->rx_mode) {
18910578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
18920578335aSAndrew Boyer 			lif->name);
1893598f6726SAlfredo Cardigliano 
18940578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1895598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1896598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1897598f6726SAlfredo Cardigliano 
1898598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18990578335aSAndrew Boyer 	}
1900598f6726SAlfredo Cardigliano 
1901a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1902a27d9013SAlfredo Cardigliano 		"on port %u",
1903a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1904a27d9013SAlfredo Cardigliano 
1905a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1906be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
190702eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1908a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1909a27d9013SAlfredo Cardigliano 
1910a27d9013SAlfredo Cardigliano 			if (err)
1911a27d9013SAlfredo Cardigliano 				return err;
1912a27d9013SAlfredo Cardigliano 		}
1913a27d9013SAlfredo Cardigliano 	}
1914a27d9013SAlfredo Cardigliano 
1915a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1916be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
191702eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1918a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1919a27d9013SAlfredo Cardigliano 
1920a27d9013SAlfredo Cardigliano 			if (err)
1921a27d9013SAlfredo Cardigliano 				return err;
1922a27d9013SAlfredo Cardigliano 		}
1923a27d9013SAlfredo Cardigliano 	}
1924a27d9013SAlfredo Cardigliano 
1925598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1926be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1927be63459eSAndrew Boyer 
1928be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1929598f6726SAlfredo Cardigliano 
1930598f6726SAlfredo Cardigliano 	return 0;
1931598f6726SAlfredo Cardigliano }
1932598f6726SAlfredo Cardigliano 
1933598f6726SAlfredo Cardigliano int
1934669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1935669c8de6SAlfredo Cardigliano {
1936669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1937669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
193809f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
193976276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
194076276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
194176276d71SAndrew Boyer 	uint32_t i, nwords;
1942669c8de6SAlfredo Cardigliano 	int err;
1943669c8de6SAlfredo Cardigliano 
1944669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1945669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1946669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1947669c8de6SAlfredo Cardigliano 	if (err)
1948669c8de6SAlfredo Cardigliano 		return (err);
1949669c8de6SAlfredo Cardigliano 
1950669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1951669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1952669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1953669c8de6SAlfredo Cardigliano 
1954669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
195509f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1956669c8de6SAlfredo Cardigliano 
1957669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
195809f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1959669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
196009f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1961669c8de6SAlfredo Cardigliano 
1962669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
196309f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1964669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
196509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1966669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
196709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1968669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
196909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1970669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
197109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1972669c8de6SAlfredo Cardigliano 
1973669c8de6SAlfredo Cardigliano 	return 0;
1974669c8de6SAlfredo Cardigliano }
1975669c8de6SAlfredo Cardigliano 
1976669c8de6SAlfredo Cardigliano int
1977669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1978669c8de6SAlfredo Cardigliano {
1979669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
198009f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
198109f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1982669c8de6SAlfredo Cardigliano 
1983669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
198409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1985669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
198609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1987669c8de6SAlfredo Cardigliano 
198800b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1989669c8de6SAlfredo Cardigliano 
1990669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
19914ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
19924ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1993669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1994669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1995669c8de6SAlfredo Cardigliano 	}
1996669c8de6SAlfredo Cardigliano 
1997669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1998669c8de6SAlfredo Cardigliano 
1999669c8de6SAlfredo Cardigliano 	return 0;
2000669c8de6SAlfredo Cardigliano }
2001