xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision d5850081d240cbeb86b3bc13bd5b04c3e3ff4fe6)
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->no_room +
1203cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1213cdfd905SAlfredo Cardigliano 	}
1223cdfd905SAlfredo Cardigliano 
1233cdfd905SAlfredo Cardigliano 	stats->imissed +=
1243cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1253cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1263cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1273cdfd905SAlfredo Cardigliano 
12826cc5dc2SAndrew Boyer 	stats->ierrors +=
1293cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1303cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1313cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1323cdfd905SAlfredo Cardigliano 
1333cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
134be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1353cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1363cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1373cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1383cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1393cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1403cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1413cdfd905SAlfredo Cardigliano 	}
1423cdfd905SAlfredo Cardigliano 
1433cdfd905SAlfredo Cardigliano 	/* TX */
1443cdfd905SAlfredo Cardigliano 
1453cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1463cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1473cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1483cdfd905SAlfredo Cardigliano 
1493cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1503cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1513cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1523cdfd905SAlfredo Cardigliano 
1533cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
154be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1553cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1563cdfd905SAlfredo Cardigliano 	}
1573cdfd905SAlfredo Cardigliano 
1583cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1593cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1603cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1613cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1623cdfd905SAlfredo Cardigliano 
1633cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1643cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1653cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1663cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1673cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1683cdfd905SAlfredo Cardigliano 
1693cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
170be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1713cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1723cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1733cdfd905SAlfredo Cardigliano 	}
1743cdfd905SAlfredo Cardigliano }
1753cdfd905SAlfredo Cardigliano 
1763cdfd905SAlfredo Cardigliano void
1773cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1783cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1793cdfd905SAlfredo Cardigliano {
1803cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1813cdfd905SAlfredo Cardigliano 
1823cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1833cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1843cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1853cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1863cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1873cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1883cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1893cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1903cdfd905SAlfredo Cardigliano }
1913cdfd905SAlfredo Cardigliano 
1923cdfd905SAlfredo Cardigliano void
1933cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
1943cdfd905SAlfredo Cardigliano {
1953cdfd905SAlfredo Cardigliano 	uint32_t i;
1963cdfd905SAlfredo Cardigliano 
1973cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
198be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
1993cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
200be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
2013cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2023cdfd905SAlfredo Cardigliano 	}
2033cdfd905SAlfredo Cardigliano 
2043cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2053cdfd905SAlfredo Cardigliano }
2063cdfd905SAlfredo Cardigliano 
2073cdfd905SAlfredo Cardigliano void
2083cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2093cdfd905SAlfredo Cardigliano {
2103cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2113cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2123cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2133cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2143cdfd905SAlfredo Cardigliano 
2153cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2163cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2173cdfd905SAlfredo Cardigliano }
2183cdfd905SAlfredo Cardigliano 
2193cdfd905SAlfredo Cardigliano void
2203cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2213cdfd905SAlfredo Cardigliano {
2223cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2233cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2243cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2253cdfd905SAlfredo Cardigliano 
2263cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2273cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2283cdfd905SAlfredo Cardigliano }
2293cdfd905SAlfredo Cardigliano 
230598f6726SAlfredo Cardigliano static int
23154fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
232598f6726SAlfredo Cardigliano {
23354fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
23454fe083fSAlfredo Cardigliano 		.pending_work = true,
23554fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
23654fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
23709f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
23854fe083fSAlfredo Cardigliano 		},
23954fe083fSAlfredo Cardigliano 	};
24054fe083fSAlfredo Cardigliano 	int err;
24154fe083fSAlfredo Cardigliano 
24254fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
24354fe083fSAlfredo Cardigliano 
24454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
24554fe083fSAlfredo Cardigliano 	if (err)
24654fe083fSAlfredo Cardigliano 		return err;
24754fe083fSAlfredo Cardigliano 
24854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
24909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
25054fe083fSAlfredo Cardigliano 
25154fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25254fe083fSAlfredo Cardigliano }
25354fe083fSAlfredo Cardigliano 
25454fe083fSAlfredo Cardigliano static int
25554fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
25654fe083fSAlfredo Cardigliano {
25754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25854fe083fSAlfredo Cardigliano 		.pending_work = true,
25954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
26054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
26154fe083fSAlfredo Cardigliano 		},
26254fe083fSAlfredo Cardigliano 	};
26354fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
26454fe083fSAlfredo Cardigliano 	int err;
26554fe083fSAlfredo Cardigliano 
26654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
26754fe083fSAlfredo Cardigliano 
26854fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
26954fe083fSAlfredo Cardigliano 
27054fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
27154fe083fSAlfredo Cardigliano 	if (!f) {
27254fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
27354fe083fSAlfredo Cardigliano 		return -ENOENT;
27454fe083fSAlfredo Cardigliano 	}
27554fe083fSAlfredo Cardigliano 
27609f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
27754fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
27854fe083fSAlfredo Cardigliano 
27954fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
28054fe083fSAlfredo Cardigliano 
28154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28254fe083fSAlfredo Cardigliano 	if (err)
28354fe083fSAlfredo Cardigliano 		return err;
28454fe083fSAlfredo Cardigliano 
28554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
28609f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
287598f6726SAlfredo Cardigliano 
288598f6726SAlfredo Cardigliano 	return 0;
289598f6726SAlfredo Cardigliano }
290598f6726SAlfredo Cardigliano 
29154fe083fSAlfredo Cardigliano int
29254fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
29354fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
29454fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
295598f6726SAlfredo Cardigliano {
29654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
29754fe083fSAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
29954fe083fSAlfredo Cardigliano 
30054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
30154fe083fSAlfredo Cardigliano }
30254fe083fSAlfredo Cardigliano 
30354fe083fSAlfredo Cardigliano void
30475f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
30554fe083fSAlfredo Cardigliano {
30654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30754fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
30875f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
30954fe083fSAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31154fe083fSAlfredo Cardigliano 
31254fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
31354fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
31454fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
31554fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
31654fe083fSAlfredo Cardigliano 		return;
31754fe083fSAlfredo Cardigliano 	}
31854fe083fSAlfredo Cardigliano 
31975f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
32075f96902SAndrew Boyer 
32175f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32254fe083fSAlfredo Cardigliano 		return;
32354fe083fSAlfredo Cardigliano 
32475f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
32554fe083fSAlfredo Cardigliano }
32654fe083fSAlfredo Cardigliano 
32754fe083fSAlfredo Cardigliano int
32854fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
32954fe083fSAlfredo Cardigliano {
33054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33354fe083fSAlfredo Cardigliano 
33454fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
33554fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
33654fe083fSAlfredo Cardigliano 		return -1;
33754fe083fSAlfredo Cardigliano 	}
33854fe083fSAlfredo Cardigliano 
33954fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
34054fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
34154fe083fSAlfredo Cardigliano 			lif->mac_addr);
34254fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
34354fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
34454fe083fSAlfredo Cardigliano 	}
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
34754fe083fSAlfredo Cardigliano 
34854fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
34954fe083fSAlfredo Cardigliano 
35054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
35154fe083fSAlfredo Cardigliano }
35254fe083fSAlfredo Cardigliano 
35354fe083fSAlfredo Cardigliano static int
35454fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
35554fe083fSAlfredo Cardigliano {
35654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
35754fe083fSAlfredo Cardigliano 		.pending_work = true,
35854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
35954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
36009f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
36109f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
36254fe083fSAlfredo Cardigliano 		},
36354fe083fSAlfredo Cardigliano 	};
36454fe083fSAlfredo Cardigliano 	int err;
36554fe083fSAlfredo Cardigliano 
36654fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
36754fe083fSAlfredo Cardigliano 	if (err)
36854fe083fSAlfredo Cardigliano 		return err;
36954fe083fSAlfredo Cardigliano 
37054fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
37109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
37254fe083fSAlfredo Cardigliano 
37354fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
37454fe083fSAlfredo Cardigliano }
37554fe083fSAlfredo Cardigliano 
37654fe083fSAlfredo Cardigliano static int
37754fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
37854fe083fSAlfredo Cardigliano {
37954fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
38054fe083fSAlfredo Cardigliano 		.pending_work = true,
38154fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38254fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
38354fe083fSAlfredo Cardigliano 		},
38454fe083fSAlfredo Cardigliano 	};
38554fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
38654fe083fSAlfredo Cardigliano 	int err;
38754fe083fSAlfredo Cardigliano 
38854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
39154fe083fSAlfredo Cardigliano 
39254fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
39354fe083fSAlfredo Cardigliano 	if (!f) {
39454fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
39554fe083fSAlfredo Cardigliano 		return -ENOENT;
39654fe083fSAlfredo Cardigliano 	}
39754fe083fSAlfredo Cardigliano 
39809f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
39954fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
40054fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
40154fe083fSAlfredo Cardigliano 
40254fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
40354fe083fSAlfredo Cardigliano 	if (err)
40454fe083fSAlfredo Cardigliano 		return err;
40554fe083fSAlfredo Cardigliano 
40654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
40709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
408598f6726SAlfredo Cardigliano 
409598f6726SAlfredo Cardigliano 	return 0;
410598f6726SAlfredo Cardigliano }
411598f6726SAlfredo Cardigliano 
41254fe083fSAlfredo Cardigliano int
41354fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
41454fe083fSAlfredo Cardigliano 		int on)
41554fe083fSAlfredo Cardigliano {
41654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
41754fe083fSAlfredo Cardigliano 	int err;
41854fe083fSAlfredo Cardigliano 
41954fe083fSAlfredo Cardigliano 	if (on)
42054fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
42154fe083fSAlfredo Cardigliano 	else
42254fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
42354fe083fSAlfredo Cardigliano 
42454fe083fSAlfredo Cardigliano 	return err;
42554fe083fSAlfredo Cardigliano }
42654fe083fSAlfredo Cardigliano 
427598f6726SAlfredo Cardigliano static void
428598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
429598f6726SAlfredo Cardigliano {
430598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
431598f6726SAlfredo Cardigliano 		.pending_work = true,
432598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
433598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
43409f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
435598f6726SAlfredo Cardigliano 		},
436598f6726SAlfredo Cardigliano 	};
437598f6726SAlfredo Cardigliano 	int err;
438598f6726SAlfredo Cardigliano 
439598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
440598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
441598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
442598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
443598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
444598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
445598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
446598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
447598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
448598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
449598f6726SAlfredo Cardigliano 
450598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
451598f6726SAlfredo Cardigliano 	if (err)
452598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
453598f6726SAlfredo Cardigliano }
454598f6726SAlfredo Cardigliano 
455598f6726SAlfredo Cardigliano static void
456598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
457598f6726SAlfredo Cardigliano {
458598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
459598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
460598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
461598f6726SAlfredo Cardigliano 	}
462598f6726SAlfredo Cardigliano }
463598f6726SAlfredo Cardigliano 
46454fe083fSAlfredo Cardigliano int
46554fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
46654fe083fSAlfredo Cardigliano {
46754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
46854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
46954fe083fSAlfredo Cardigliano 
47054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
47154fe083fSAlfredo Cardigliano 
47254fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
47354fe083fSAlfredo Cardigliano 
47454fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
47554fe083fSAlfredo Cardigliano 
47654fe083fSAlfredo Cardigliano 	return 0;
47754fe083fSAlfredo Cardigliano }
47854fe083fSAlfredo Cardigliano 
47954fe083fSAlfredo Cardigliano int
48054fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
48154fe083fSAlfredo Cardigliano {
48254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48354fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48454fe083fSAlfredo Cardigliano 
48554fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
48654fe083fSAlfredo Cardigliano 
48754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48854fe083fSAlfredo Cardigliano 
48954fe083fSAlfredo Cardigliano 	return 0;
49054fe083fSAlfredo Cardigliano }
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano int
49354fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
49454fe083fSAlfredo Cardigliano {
49554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
49954fe083fSAlfredo Cardigliano 
50054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50154fe083fSAlfredo Cardigliano 
50254fe083fSAlfredo Cardigliano 	return 0;
50354fe083fSAlfredo Cardigliano }
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano int
50654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
50754fe083fSAlfredo Cardigliano {
50854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50954fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51254fe083fSAlfredo Cardigliano 
51354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51454fe083fSAlfredo Cardigliano 
51554fe083fSAlfredo Cardigliano 	return 0;
51654fe083fSAlfredo Cardigliano }
517598f6726SAlfredo Cardigliano 
518598f6726SAlfredo Cardigliano int
519b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
520598f6726SAlfredo Cardigliano {
521598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
522598f6726SAlfredo Cardigliano 		.pending_work = true,
523598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
524598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
525598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
52609f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
527598f6726SAlfredo Cardigliano 		},
528598f6726SAlfredo Cardigliano 	};
529598f6726SAlfredo Cardigliano 
530b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
531598f6726SAlfredo Cardigliano }
532598f6726SAlfredo Cardigliano 
533598f6726SAlfredo Cardigliano int
53401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
53501a6c311SAlfredo Cardigliano {
53601a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
53701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
53801a6c311SAlfredo Cardigliano 	unsigned long index;
53901a6c311SAlfredo Cardigliano 
54001a6c311SAlfredo Cardigliano 	/*
54101a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
54201a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5434ae96cb8SAndrew Boyer 	 * which has index = 0)
54401a6c311SAlfredo Cardigliano 	 */
54501a6c311SAlfredo Cardigliano 
54601a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
54701a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
54801a6c311SAlfredo Cardigliano 			break;
54901a6c311SAlfredo Cardigliano 
55001a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
55101a6c311SAlfredo Cardigliano 		return -ENOSPC;
55201a6c311SAlfredo Cardigliano 
55301a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
55401a6c311SAlfredo Cardigliano 
55501a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
55601a6c311SAlfredo Cardigliano 
55701a6c311SAlfredo Cardigliano 	return 0;
55801a6c311SAlfredo Cardigliano }
55901a6c311SAlfredo Cardigliano 
56001a6c311SAlfredo Cardigliano static int
5614ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5624ad56b7aSAndrew Boyer 		uint8_t type,
563be39f75cSAndrew Boyer 		size_t struct_size,
5648ec5ad7fSAndrew Boyer 		uint32_t socket_id,
56501a6c311SAlfredo Cardigliano 		uint32_t index,
5664ad56b7aSAndrew Boyer 		const char *type_name,
5674ad56b7aSAndrew Boyer 		uint16_t flags,
5684ad56b7aSAndrew Boyer 		uint16_t num_descs,
569*d5850081SAndrew Boyer 		uint16_t num_segs,
5704ad56b7aSAndrew Boyer 		uint16_t desc_size,
5714ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5724ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5731abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
57401a6c311SAlfredo Cardigliano {
57501a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
57601a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
57701a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
57801a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
57901a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
58001a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
58101a6c311SAlfredo Cardigliano 	int err;
58201a6c311SAlfredo Cardigliano 
58301a6c311SAlfredo Cardigliano 	*qcq = NULL;
58401a6c311SAlfredo Cardigliano 
58501a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
58601a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
58701a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
58801a6c311SAlfredo Cardigliano 
589924e6b76SThomas Monjalon 	total_size = RTE_ALIGN(q_size, rte_mem_page_size()) +
590924e6b76SThomas Monjalon 			RTE_ALIGN(cq_size, rte_mem_page_size());
59101a6c311SAlfredo Cardigliano 	/*
59201a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
59301a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
594924e6b76SThomas Monjalon 	 * Adding rte_mem_page_size().
59501a6c311SAlfredo Cardigliano 	 */
596924e6b76SThomas Monjalon 	total_size += rte_mem_page_size();
59701a6c311SAlfredo Cardigliano 
59801a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
599924e6b76SThomas Monjalon 		total_size += RTE_ALIGN(sg_size, rte_mem_page_size());
600924e6b76SThomas Monjalon 		total_size += rte_mem_page_size();
60101a6c311SAlfredo Cardigliano 	}
60201a6c311SAlfredo Cardigliano 
603be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
60401a6c311SAlfredo Cardigliano 	if (!new) {
60501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
60601a6c311SAlfredo Cardigliano 		return -ENOMEM;
60701a6c311SAlfredo Cardigliano 	}
60801a6c311SAlfredo Cardigliano 
60901a6c311SAlfredo Cardigliano 	new->lif = lif;
61001a6c311SAlfredo Cardigliano 
611be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
612be39f75cSAndrew Boyer 				num_descs, sizeof(void *),
613924e6b76SThomas Monjalon 				rte_mem_page_size(), socket_id);
61401a6c311SAlfredo Cardigliano 	if (!new->q.info) {
61501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6164c8f8d57SAndrew Boyer 		err = -ENOMEM;
6174c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
61801a6c311SAlfredo Cardigliano 	}
61901a6c311SAlfredo Cardigliano 
620*d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
62101a6c311SAlfredo Cardigliano 	new->q.type = type;
62201a6c311SAlfredo Cardigliano 
6234ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
62401a6c311SAlfredo Cardigliano 	if (err) {
62501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6264c8f8d57SAndrew Boyer 		goto err_out_free_info;
62701a6c311SAlfredo Cardigliano 	}
62801a6c311SAlfredo Cardigliano 
6292aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
63001a6c311SAlfredo Cardigliano 	if (err) {
63101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6324c8f8d57SAndrew Boyer 		goto err_out_free_info;
63301a6c311SAlfredo Cardigliano 	}
63401a6c311SAlfredo Cardigliano 
63501a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6364ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
63701a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
63801a6c311SAlfredo Cardigliano 
63901a6c311SAlfredo Cardigliano 	if (!new->base_z) {
64001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
64101a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6424c8f8d57SAndrew Boyer 		goto err_out_free_info;
64301a6c311SAlfredo Cardigliano 	}
64401a6c311SAlfredo Cardigliano 
64501a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
64601a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
64701a6c311SAlfredo Cardigliano 
64801a6c311SAlfredo Cardigliano 	q_base = new->base;
64901a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
65001a6c311SAlfredo Cardigliano 
651924e6b76SThomas Monjalon 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size,
652924e6b76SThomas Monjalon 			rte_mem_page_size());
653924e6b76SThomas Monjalon 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size,
654924e6b76SThomas Monjalon 			rte_mem_page_size());
65501a6c311SAlfredo Cardigliano 
65601a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
65701a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
658924e6b76SThomas Monjalon 				rte_mem_page_size());
659924e6b76SThomas Monjalon 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size,
660924e6b76SThomas Monjalon 				rte_mem_page_size());
66101a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
66201a6c311SAlfredo Cardigliano 	}
66301a6c311SAlfredo Cardigliano 
6644ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6654ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
66601a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
66701a6c311SAlfredo Cardigliano 
66801a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
66901a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
67001a6c311SAlfredo Cardigliano 
67101a6c311SAlfredo Cardigliano 	*qcq = new;
67201a6c311SAlfredo Cardigliano 
67301a6c311SAlfredo Cardigliano 	return 0;
67401a6c311SAlfredo Cardigliano 
6754c8f8d57SAndrew Boyer err_out_free_info:
6764c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6774c8f8d57SAndrew Boyer err_out_free_qcq:
6784c8f8d57SAndrew Boyer 	rte_free(new);
67901a6c311SAlfredo Cardigliano 
68001a6c311SAlfredo Cardigliano 	return err;
68101a6c311SAlfredo Cardigliano }
68201a6c311SAlfredo Cardigliano 
68301a6c311SAlfredo Cardigliano void
68401a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
68501a6c311SAlfredo Cardigliano {
68601a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
68701a6c311SAlfredo Cardigliano 		qcq->base = NULL;
68801a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
68901a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
69001a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
69101a6c311SAlfredo Cardigliano 	}
69201a6c311SAlfredo Cardigliano 
69301a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
69401a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
69501a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
69601a6c311SAlfredo Cardigliano 	}
69701a6c311SAlfredo Cardigliano 
69801a6c311SAlfredo Cardigliano 	rte_free(qcq);
69901a6c311SAlfredo Cardigliano }
70001a6c311SAlfredo Cardigliano 
701a27d9013SAlfredo Cardigliano int
7028ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
703*d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
704*d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
705a27d9013SAlfredo Cardigliano {
706be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
707*d5850081SAndrew Boyer 	uint16_t flags, seg_size, hdr_seg_size, max_segs, max_segs_fw;
708*d5850081SAndrew Boyer 	uint32_t max_mtu;
709be39f75cSAndrew Boyer 	int err;
710a27d9013SAlfredo Cardigliano 
711a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
712b671e69aSAndrew Boyer 
713*d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
714*d5850081SAndrew Boyer 
715*d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
716*d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
717*d5850081SAndrew Boyer 
718*d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
719*d5850081SAndrew Boyer 
720*d5850081SAndrew Boyer 	max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
721*d5850081SAndrew Boyer 
722*d5850081SAndrew Boyer 	/*
723*d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
724*d5850081SAndrew Boyer 	 */
725*d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
726*d5850081SAndrew Boyer 
727*d5850081SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u frame_size %u seg_size %u max_segs %u",
728*d5850081SAndrew Boyer 		index, lif->frame_size, seg_size, max_segs);
729*d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
730*d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
731*d5850081SAndrew Boyer 			max_segs, max_segs_fw);
732*d5850081SAndrew Boyer 		return -EINVAL;
733*d5850081SAndrew Boyer 	}
734*d5850081SAndrew Boyer 
7354ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7364ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
737be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7388ec5ad7fSAndrew Boyer 		socket_id,
7394ad56b7aSAndrew Boyer 		index,
7404ad56b7aSAndrew Boyer 		"rx",
7414ad56b7aSAndrew Boyer 		flags,
742a27d9013SAlfredo Cardigliano 		nrxq_descs,
743*d5850081SAndrew Boyer 		max_segs,
744a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
745a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
746a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
747be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
748a27d9013SAlfredo Cardigliano 	if (err)
749a27d9013SAlfredo Cardigliano 		return err;
750a27d9013SAlfredo Cardigliano 
751be39f75cSAndrew Boyer 	rxq->flags = flags;
752*d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
753*d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
754be39f75cSAndrew Boyer 
755be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
756be39f75cSAndrew Boyer 	*rxq_out = rxq;
757a27d9013SAlfredo Cardigliano 
758a27d9013SAlfredo Cardigliano 	return 0;
759a27d9013SAlfredo Cardigliano }
760a27d9013SAlfredo Cardigliano 
761a27d9013SAlfredo Cardigliano int
7628ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
763be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
764a27d9013SAlfredo Cardigliano {
765be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
766e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
767be39f75cSAndrew Boyer 	int err;
768a27d9013SAlfredo Cardigliano 
769a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
770e19eea1eSAndrew Boyer 
771e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
772e19eea1eSAndrew Boyer 
7734ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7744ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
775be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
7768ec5ad7fSAndrew Boyer 		socket_id,
7774ad56b7aSAndrew Boyer 		index,
7784ad56b7aSAndrew Boyer 		"tx",
7794ad56b7aSAndrew Boyer 		flags,
780a27d9013SAlfredo Cardigliano 		ntxq_descs,
781*d5850081SAndrew Boyer 		1,
782a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
783a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
78456117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
785be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
786a27d9013SAlfredo Cardigliano 	if (err)
787a27d9013SAlfredo Cardigliano 		return err;
788a27d9013SAlfredo Cardigliano 
789be39f75cSAndrew Boyer 	txq->flags = flags;
790e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
791be39f75cSAndrew Boyer 
792be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
793be39f75cSAndrew Boyer 	*txq_out = txq;
794a27d9013SAlfredo Cardigliano 
795a27d9013SAlfredo Cardigliano 	return 0;
796a27d9013SAlfredo Cardigliano }
797a27d9013SAlfredo Cardigliano 
79801a6c311SAlfredo Cardigliano static int
79901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
80001a6c311SAlfredo Cardigliano {
801be39f75cSAndrew Boyer 	uint16_t flags = 0;
802be39f75cSAndrew Boyer 	int err;
80301a6c311SAlfredo Cardigliano 
8044ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8054ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
806be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8078ec5ad7fSAndrew Boyer 		rte_socket_id(),
8084ad56b7aSAndrew Boyer 		0,
8094ad56b7aSAndrew Boyer 		"admin",
8104ad56b7aSAndrew Boyer 		flags,
81101a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
812*d5850081SAndrew Boyer 		1,
81301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
81401a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
81501a6c311SAlfredo Cardigliano 		0,
816be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
81727b942c8SAlfredo Cardigliano 	if (err)
81827b942c8SAlfredo Cardigliano 		return err;
81901a6c311SAlfredo Cardigliano 
82027b942c8SAlfredo Cardigliano 	return 0;
82127b942c8SAlfredo Cardigliano }
82227b942c8SAlfredo Cardigliano 
82327b942c8SAlfredo Cardigliano static int
82427b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
82527b942c8SAlfredo Cardigliano {
826be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8274c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
828be39f75cSAndrew Boyer 	uint16_t flags = 0;
829be39f75cSAndrew Boyer 	int err;
83027b942c8SAlfredo Cardigliano 
8314ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8324ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
833be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8348ec5ad7fSAndrew Boyer 		rte_socket_id(),
8354ad56b7aSAndrew Boyer 		0,
8364ad56b7aSAndrew Boyer 		"notify",
83727b942c8SAlfredo Cardigliano 		flags,
83827b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
839*d5850081SAndrew Boyer 		1,
84027b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
84127b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
84227b942c8SAlfredo Cardigliano 		0,
843be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
84401a6c311SAlfredo Cardigliano 	if (err)
84501a6c311SAlfredo Cardigliano 		return err;
84601a6c311SAlfredo Cardigliano 
8474c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8484c8f8d57SAndrew Boyer 	if (err) {
849be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
8504c8f8d57SAndrew Boyer 		return err;
8514c8f8d57SAndrew Boyer 	}
8524c8f8d57SAndrew Boyer 
8534c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8544c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8554c8f8d57SAndrew Boyer 
8564c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8574c8f8d57SAndrew Boyer 
85801a6c311SAlfredo Cardigliano 	return 0;
85901a6c311SAlfredo Cardigliano }
86001a6c311SAlfredo Cardigliano 
861c5d15850SAndrew Boyer static void
862c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
863c5d15850SAndrew Boyer {
864c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
865c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
866c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
867c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
868c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
869c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
870c5d15850SAndrew Boyer 	int err;
871c5d15850SAndrew Boyer 
872c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
873c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
874c5d15850SAndrew Boyer 
875c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
876c5d15850SAndrew Boyer 		switch (qtype) {
877c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
878c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
879c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
880c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
881c5d15850SAndrew Boyer 			break;
882c5d15850SAndrew Boyer 		default:
883c5d15850SAndrew Boyer 			continue;
884c5d15850SAndrew Boyer 		}
885c5d15850SAndrew Boyer 
886c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
887c5d15850SAndrew Boyer 
888c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
889c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
890c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
891c5d15850SAndrew Boyer 		if (err == -EINVAL) {
892c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
893c5d15850SAndrew Boyer 			continue;
894c5d15850SAndrew Boyer 		} else if (err == -EIO) {
895c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
896c5d15850SAndrew Boyer 			return;
897c5d15850SAndrew Boyer 		} else if (err) {
898c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
899c5d15850SAndrew Boyer 				qtype, err);
900c5d15850SAndrew Boyer 			return;
901c5d15850SAndrew Boyer 		}
902c5d15850SAndrew Boyer 
903c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
904c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
905c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
906c5d15850SAndrew Boyer 
907c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
908c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
909c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
910c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
911c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
912c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
913c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
914c5d15850SAndrew Boyer 		qti->sg_desc_stride =
915c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
916c5d15850SAndrew Boyer 
917c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
918c5d15850SAndrew Boyer 			qtype, qti->version);
919c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
920c5d15850SAndrew Boyer 			qtype, qti->supported);
921c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
922c5d15850SAndrew Boyer 			qtype, qti->features);
923c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
924c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
925c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
926c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
927c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
928c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
929c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
930c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
931c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
932c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
933c5d15850SAndrew Boyer 	}
934c5d15850SAndrew Boyer }
935c5d15850SAndrew Boyer 
936669c8de6SAlfredo Cardigliano int
937669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
938669c8de6SAlfredo Cardigliano {
939c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
940669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
94101a6c311SAlfredo Cardigliano 	int err;
942669c8de6SAlfredo Cardigliano 
9434ae96cb8SAndrew Boyer 	/*
9444ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9454ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9464ae96cb8SAndrew Boyer 	 */
9474ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9484ae96cb8SAndrew Boyer 
9494ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
950669c8de6SAlfredo Cardigliano 
951c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
952c5d15850SAndrew Boyer 
95356117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
95456117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
95556117636SAndrew Boyer 		return -ENXIO;
95656117636SAndrew Boyer 	}
95756117636SAndrew Boyer 
958669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
959669c8de6SAlfredo Cardigliano 
96001a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
96101a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
96201a6c311SAlfredo Cardigliano 
96384cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
964c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
965c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
966c67719e1SAlfredo Cardigliano 		return -ENOMEM;
967c67719e1SAlfredo Cardigliano 	}
968c67719e1SAlfredo Cardigliano 
969a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
970a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
971a27d9013SAlfredo Cardigliano 
972a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
973a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
974a27d9013SAlfredo Cardigliano 		return -ENOMEM;
975a27d9013SAlfredo Cardigliano 	}
976a27d9013SAlfredo Cardigliano 
977a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
978a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
979a27d9013SAlfredo Cardigliano 
980a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
981a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
982a27d9013SAlfredo Cardigliano 		return -ENOMEM;
983a27d9013SAlfredo Cardigliano 	}
984a27d9013SAlfredo Cardigliano 
98527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
98627b942c8SAlfredo Cardigliano 
98727b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
98827b942c8SAlfredo Cardigliano 	if (err) {
98927b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
99027b942c8SAlfredo Cardigliano 		return err;
99127b942c8SAlfredo Cardigliano 	}
99227b942c8SAlfredo Cardigliano 
99327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
99427b942c8SAlfredo Cardigliano 
99501a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
99601a6c311SAlfredo Cardigliano 	if (err) {
99701a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
99801a6c311SAlfredo Cardigliano 		return err;
99901a6c311SAlfredo Cardigliano 	}
100001a6c311SAlfredo Cardigliano 
100101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
100201a6c311SAlfredo Cardigliano 
1003924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1004669c8de6SAlfredo Cardigliano 
1005669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1006669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1007669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1008669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1009669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1010669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1011669c8de6SAlfredo Cardigliano 	}
1012669c8de6SAlfredo Cardigliano 
1013669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1014669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1015669c8de6SAlfredo Cardigliano 
1016669c8de6SAlfredo Cardigliano 	return 0;
1017669c8de6SAlfredo Cardigliano }
1018669c8de6SAlfredo Cardigliano 
1019669c8de6SAlfredo Cardigliano void
1020669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1021669c8de6SAlfredo Cardigliano {
102227b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1023be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
102427b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
102527b942c8SAlfredo Cardigliano 	}
102627b942c8SAlfredo Cardigliano 
102701a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1028be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
102901a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
103001a6c311SAlfredo Cardigliano 	}
103101a6c311SAlfredo Cardigliano 
1032a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1033a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1034a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1035a27d9013SAlfredo Cardigliano 	}
1036a27d9013SAlfredo Cardigliano 
1037a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1038a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1039a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1040a27d9013SAlfredo Cardigliano 	}
1041a27d9013SAlfredo Cardigliano 
1042669c8de6SAlfredo Cardigliano 	if (lif->info) {
1043669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1044669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1045669c8de6SAlfredo Cardigliano 	}
1046669c8de6SAlfredo Cardigliano }
1047669c8de6SAlfredo Cardigliano 
1048175e4e7eSAndrew Boyer void
1049175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1050175e4e7eSAndrew Boyer {
1051175e4e7eSAndrew Boyer 	uint32_t i;
1052175e4e7eSAndrew Boyer 
1053175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
10547483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1055175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1056175e4e7eSAndrew Boyer 	}
1057175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
10587483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1059175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1060175e4e7eSAndrew Boyer 	}
1061175e4e7eSAndrew Boyer }
1062175e4e7eSAndrew Boyer 
106322e7171bSAlfredo Cardigliano int
106422e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
106522e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
106622e7171bSAlfredo Cardigliano {
106709f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
106822e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
106922e7171bSAlfredo Cardigliano 		.pending_work = true,
107022e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
107122e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
107222e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
107309f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
107409f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
107522e7171bSAlfredo Cardigliano 		},
107622e7171bSAlfredo Cardigliano 	};
107722e7171bSAlfredo Cardigliano 	unsigned int i;
107809f806e9SAndrew Boyer 	uint16_t tbl_sz =
107909f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
108022e7171bSAlfredo Cardigliano 
108122e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
108222e7171bSAlfredo Cardigliano 
108322e7171bSAlfredo Cardigliano 	lif->rss_types = types;
108422e7171bSAlfredo Cardigliano 
108522e7171bSAlfredo Cardigliano 	if (key)
108622e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
108722e7171bSAlfredo Cardigliano 
108822e7171bSAlfredo Cardigliano 	if (indir)
108909f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
109022e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
109122e7171bSAlfredo Cardigliano 
109222e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
109322e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
109422e7171bSAlfredo Cardigliano 
109522e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
109622e7171bSAlfredo Cardigliano }
109722e7171bSAlfredo Cardigliano 
109822e7171bSAlfredo Cardigliano static int
109922e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
110022e7171bSAlfredo Cardigliano {
110109f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
110222e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
110322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110822e7171bSAlfredo Cardigliano 	};
110922e7171bSAlfredo Cardigliano 	uint32_t i;
111009f806e9SAndrew Boyer 	uint16_t tbl_sz =
111109f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
111222e7171bSAlfredo Cardigliano 
111322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
111422e7171bSAlfredo Cardigliano 
11153d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
111622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11173d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11183d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11193d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
112022e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
112122e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
112222e7171bSAlfredo Cardigliano 			return -ENOMEM;
112322e7171bSAlfredo Cardigliano 		}
112422e7171bSAlfredo Cardigliano 
112522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
112622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11273d845eddSAndrew Boyer 	}
11283d845eddSAndrew Boyer 
11293d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11303d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
113122e7171bSAlfredo Cardigliano 
113222e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11333d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
113422e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11353d845eddSAndrew Boyer 	}
113622e7171bSAlfredo Cardigliano 
11373d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
113822e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
113922e7171bSAlfredo Cardigliano }
114022e7171bSAlfredo Cardigliano 
114122e7171bSAlfredo Cardigliano static void
114222e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
114322e7171bSAlfredo Cardigliano {
114422e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
114522e7171bSAlfredo Cardigliano 		return;
114622e7171bSAlfredo Cardigliano 
114722e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
114822e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
114922e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
115022e7171bSAlfredo Cardigliano 
115122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
115222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
115322e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
115422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
115522e7171bSAlfredo Cardigliano 	}
115622e7171bSAlfredo Cardigliano }
115722e7171bSAlfredo Cardigliano 
1158be39f75cSAndrew Boyer void
1159be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1160be39f75cSAndrew Boyer {
1161e7222f94SAndrew Boyer 	ionic_qcq_disable(&txq->qcq);
1162e7222f94SAndrew Boyer 
1163be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1164be39f75cSAndrew Boyer }
1165be39f75cSAndrew Boyer 
1166be39f75cSAndrew Boyer void
1167be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1168be39f75cSAndrew Boyer {
1169e7222f94SAndrew Boyer 	ionic_qcq_disable(&rxq->qcq);
1170e7222f94SAndrew Boyer 
1171be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1172be39f75cSAndrew Boyer }
1173be39f75cSAndrew Boyer 
117401a6c311SAlfredo Cardigliano static void
1175be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
117601a6c311SAlfredo Cardigliano {
1177be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
11784c8f8d57SAndrew Boyer }
11794c8f8d57SAndrew Boyer 
11804c8f8d57SAndrew Boyer static void
11814c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
11824c8f8d57SAndrew Boyer {
1183be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
11844c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
11854c8f8d57SAndrew Boyer 
11864c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
11874c8f8d57SAndrew Boyer 		return;
11884c8f8d57SAndrew Boyer 
11894c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
11904c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
11914c8f8d57SAndrew Boyer 
11924c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1193a27d9013SAlfredo Cardigliano }
1194a27d9013SAlfredo Cardigliano 
119501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
119601a6c311SAlfredo Cardigliano int
119701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
119801a6c311SAlfredo Cardigliano 		void *cb_arg)
119901a6c311SAlfredo Cardigliano {
120001a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
120101a6c311SAlfredo Cardigliano 	uint32_t work_done;
120201a6c311SAlfredo Cardigliano 
120301a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
120401a6c311SAlfredo Cardigliano 
120501a6c311SAlfredo Cardigliano 	return work_done;
120601a6c311SAlfredo Cardigliano }
120701a6c311SAlfredo Cardigliano 
120827b942c8SAlfredo Cardigliano static void
120927b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
121027b942c8SAlfredo Cardigliano {
121127b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
121227b942c8SAlfredo Cardigliano 	bool link_up;
121327b942c8SAlfredo Cardigliano 
121427b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
121527b942c8SAlfredo Cardigliano 
121627b942c8SAlfredo Cardigliano 	if (!lif->info)
121727b942c8SAlfredo Cardigliano 		return;
121827b942c8SAlfredo Cardigliano 
121927b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
122027b942c8SAlfredo Cardigliano 
122127b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
122227b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
122327b942c8SAlfredo Cardigliano 		return;
122427b942c8SAlfredo Cardigliano 
122527b942c8SAlfredo Cardigliano 	if (link_up) {
122609f806e9SAndrew Boyer 		adapter->link_speed =
122709f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1228be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1229be63459eSAndrew Boyer 			adapter->link_speed);
123027b942c8SAlfredo Cardigliano 	} else {
123127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
123227b942c8SAlfredo Cardigliano 	}
123327b942c8SAlfredo Cardigliano 
123427b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1235be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1236be63459eSAndrew Boyer }
1237be63459eSAndrew Boyer 
1238be63459eSAndrew Boyer static void
1239be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1240be63459eSAndrew Boyer {
1241be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1242be63459eSAndrew Boyer 		return;
1243be63459eSAndrew Boyer 
1244be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1245be63459eSAndrew Boyer 
1246be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1247be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1248be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1249be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1250be63459eSAndrew Boyer 	}
1251be63459eSAndrew Boyer 
1252be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
125327b942c8SAlfredo Cardigliano }
125427b942c8SAlfredo Cardigliano 
125527b942c8SAlfredo Cardigliano static bool
12564ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
125727b942c8SAlfredo Cardigliano {
125827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
125927b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
126027b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
126127b942c8SAlfredo Cardigliano 
126227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
126327b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
126427b942c8SAlfredo Cardigliano 
126527b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
126627b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
126727b942c8SAlfredo Cardigliano 		return false;
126827b942c8SAlfredo Cardigliano 
126927b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
127027b942c8SAlfredo Cardigliano 
127127b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
127227b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
127327b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1274be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1275be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1276be63459eSAndrew Boyer 			lif->name,
127727b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
127827b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
127927b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
128027b942c8SAlfredo Cardigliano 
128127b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
128227b942c8SAlfredo Cardigliano 		break;
1283be63459eSAndrew Boyer 
1284be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1285be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1286be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1287be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1288be63459eSAndrew Boyer 			lif->name,
1289be63459eSAndrew Boyer 			cq_desc->event.eid,
1290be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1291be63459eSAndrew Boyer 			cq_desc->reset.state);
1292be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1293be63459eSAndrew Boyer 		break;
1294be63459eSAndrew Boyer 
129527b942c8SAlfredo Cardigliano 	default:
129627b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
129727b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
129827b942c8SAlfredo Cardigliano 		break;
129927b942c8SAlfredo Cardigliano 	}
130027b942c8SAlfredo Cardigliano 
130127b942c8SAlfredo Cardigliano 	return true;
130227b942c8SAlfredo Cardigliano }
130327b942c8SAlfredo Cardigliano 
130427b942c8SAlfredo Cardigliano int
130527b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
130627b942c8SAlfredo Cardigliano {
130727b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1308be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
130927b942c8SAlfredo Cardigliano 	uint32_t work_done;
131027b942c8SAlfredo Cardigliano 
1311be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
131227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
131327b942c8SAlfredo Cardigliano 		return -1;
131427b942c8SAlfredo Cardigliano 	}
131527b942c8SAlfredo Cardigliano 
1316be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
131727b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
131827b942c8SAlfredo Cardigliano 
1319be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1320be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
132127b942c8SAlfredo Cardigliano 
132227b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
132327b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
132427b942c8SAlfredo Cardigliano 
1325be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
132627b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
132727b942c8SAlfredo Cardigliano 
1328be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
132927b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
133027b942c8SAlfredo Cardigliano 
133127b942c8SAlfredo Cardigliano 	return 0;
133227b942c8SAlfredo Cardigliano }
133327b942c8SAlfredo Cardigliano 
133401a6c311SAlfredo Cardigliano static int
133501a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
133601a6c311SAlfredo Cardigliano {
133701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1338be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1339be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
134001a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
134101a6c311SAlfredo Cardigliano 	int err;
134201a6c311SAlfredo Cardigliano 
1343be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
134401a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
134501a6c311SAlfredo Cardigliano 	if (err)
134601a6c311SAlfredo Cardigliano 		return err;
134701a6c311SAlfredo Cardigliano 
134801a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
134901a6c311SAlfredo Cardigliano 
135001a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
135109f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
135201a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
135301a6c311SAlfredo Cardigliano 
135401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
135501a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
135601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
135701a6c311SAlfredo Cardigliano 
1358be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
135901a6c311SAlfredo Cardigliano 
136001a6c311SAlfredo Cardigliano 	return 0;
136101a6c311SAlfredo Cardigliano }
136201a6c311SAlfredo Cardigliano 
136327b942c8SAlfredo Cardigliano static int
136427b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
136527b942c8SAlfredo Cardigliano {
136627b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1367be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1368be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
13690a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
137027b942c8SAlfredo Cardigliano 	int err;
137127b942c8SAlfredo Cardigliano 
137227b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
137327b942c8SAlfredo Cardigliano 		.pending_work = true,
137427b942c8SAlfredo Cardigliano 		.cmd.q_init = {
137527b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
137627b942c8SAlfredo Cardigliano 			.type = q->type,
1377c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
137809f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
13790a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
138027b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
138109f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
138227b942c8SAlfredo Cardigliano 		}
138327b942c8SAlfredo Cardigliano 	};
138427b942c8SAlfredo Cardigliano 
13850a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
13860a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
13870a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
13880a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
13890a00bdafSAndrew Boyer 	}
13900a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
13910a00bdafSAndrew Boyer 
139209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
139309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
139427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
139527b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13964ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
139727b942c8SAlfredo Cardigliano 
139827b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
139927b942c8SAlfredo Cardigliano 	if (err)
140027b942c8SAlfredo Cardigliano 		return err;
140127b942c8SAlfredo Cardigliano 
140227b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
140309f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
140427b942c8SAlfredo Cardigliano 	q->db = NULL;
140527b942c8SAlfredo Cardigliano 
140627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
140727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
140827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
140927b942c8SAlfredo Cardigliano 
1410be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
141127b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
141227b942c8SAlfredo Cardigliano 
1413be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
141427b942c8SAlfredo Cardigliano 
141527b942c8SAlfredo Cardigliano 	return 0;
141627b942c8SAlfredo Cardigliano }
141727b942c8SAlfredo Cardigliano 
1418669c8de6SAlfredo Cardigliano int
1419598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1420598f6726SAlfredo Cardigliano {
1421598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1422598f6726SAlfredo Cardigliano 		.pending_work = true,
1423598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1424598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1425598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
142609f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1427598f6726SAlfredo Cardigliano 		},
1428598f6726SAlfredo Cardigliano 	};
1429598f6726SAlfredo Cardigliano 	int err;
1430598f6726SAlfredo Cardigliano 
1431598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1432598f6726SAlfredo Cardigliano 	if (err)
1433598f6726SAlfredo Cardigliano 		return err;
1434598f6726SAlfredo Cardigliano 
143509f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1436598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1437598f6726SAlfredo Cardigliano 
1438598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1439598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1440598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1441598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1442598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1443598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1444598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1445598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1446598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1448598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1450598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1452598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1454598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1455598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1456598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1457598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1458598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1459598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1460598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1461598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1462598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1463598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1464598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1465598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1466598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1467598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1468598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1469598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1470598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1471598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1472598f6726SAlfredo Cardigliano 
1473598f6726SAlfredo Cardigliano 	return 0;
1474598f6726SAlfredo Cardigliano }
1475598f6726SAlfredo Cardigliano 
1476a27d9013SAlfredo Cardigliano int
1477be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1478a27d9013SAlfredo Cardigliano {
1479be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1480a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1481a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1482a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1483a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1484a27d9013SAlfredo Cardigliano 		.pending_work = true,
1485a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1486a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1487a27d9013SAlfredo Cardigliano 			.type = q->type,
1488c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
148909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
149009f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
149109f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
149209f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1493a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
149409f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
149509f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
149609f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1497a27d9013SAlfredo Cardigliano 		},
1498a27d9013SAlfredo Cardigliano 	};
1499a27d9013SAlfredo Cardigliano 	int err;
1500a27d9013SAlfredo Cardigliano 
150109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
150209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1503a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1504a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15054ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1506a27d9013SAlfredo Cardigliano 
1507e7222f94SAndrew Boyer 	ionic_q_reset(q);
1508e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1509e7222f94SAndrew Boyer 
1510be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1511a27d9013SAlfredo Cardigliano 	if (err)
1512a27d9013SAlfredo Cardigliano 		return err;
1513a27d9013SAlfredo Cardigliano 
1514a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
151509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1516a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1517a27d9013SAlfredo Cardigliano 
1518a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1519a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1520a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1521a27d9013SAlfredo Cardigliano 
1522be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1523a27d9013SAlfredo Cardigliano 
1524a27d9013SAlfredo Cardigliano 	return 0;
1525a27d9013SAlfredo Cardigliano }
1526a27d9013SAlfredo Cardigliano 
1527a27d9013SAlfredo Cardigliano int
1528be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1529a27d9013SAlfredo Cardigliano {
1530be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1531a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1532a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1533a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1534a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1535a27d9013SAlfredo Cardigliano 		.pending_work = true,
1536a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1537a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1538a27d9013SAlfredo Cardigliano 			.type = q->type,
1539c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
154009f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
154109f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
154209f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
154309f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1544a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
154509f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
154609f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
154709f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1548a27d9013SAlfredo Cardigliano 		},
1549a27d9013SAlfredo Cardigliano 	};
1550a27d9013SAlfredo Cardigliano 	int err;
1551a27d9013SAlfredo Cardigliano 
155209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
155309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1554a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1555a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15564ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1557a27d9013SAlfredo Cardigliano 
1558e7222f94SAndrew Boyer 	ionic_q_reset(q);
1559e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1560e7222f94SAndrew Boyer 
1561be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1562a27d9013SAlfredo Cardigliano 	if (err)
1563a27d9013SAlfredo Cardigliano 		return err;
1564a27d9013SAlfredo Cardigliano 
1565a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
156609f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1567a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1568a27d9013SAlfredo Cardigliano 
1569be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1570a27d9013SAlfredo Cardigliano 
1571a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1572a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1573a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1574a27d9013SAlfredo Cardigliano 
1575a27d9013SAlfredo Cardigliano 	return 0;
1576a27d9013SAlfredo Cardigliano }
1577a27d9013SAlfredo Cardigliano 
1578598f6726SAlfredo Cardigliano static int
1579598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1580598f6726SAlfredo Cardigliano {
1581598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1582598f6726SAlfredo Cardigliano 		.pending_work = true,
1583598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1584598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1585598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1586598f6726SAlfredo Cardigliano 		},
1587598f6726SAlfredo Cardigliano 	};
1588598f6726SAlfredo Cardigliano 	int err;
1589598f6726SAlfredo Cardigliano 
1590598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1591598f6726SAlfredo Cardigliano 
1592598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1593598f6726SAlfredo Cardigliano 	if (err)
1594598f6726SAlfredo Cardigliano 		return err;
1595598f6726SAlfredo Cardigliano 
1596598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1597598f6726SAlfredo Cardigliano 
1598598f6726SAlfredo Cardigliano 	return 0;
1599598f6726SAlfredo Cardigliano }
1600598f6726SAlfredo Cardigliano 
1601598f6726SAlfredo Cardigliano static void
1602598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1603598f6726SAlfredo Cardigliano {
1604598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1605598f6726SAlfredo Cardigliano 		.pending_work = true,
1606598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1607598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1608598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1609598f6726SAlfredo Cardigliano 		},
1610598f6726SAlfredo Cardigliano 	};
1611598f6726SAlfredo Cardigliano 
16124ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
16134ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1614598f6726SAlfredo Cardigliano 
1615598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1616598f6726SAlfredo Cardigliano }
1617598f6726SAlfredo Cardigliano 
1618598f6726SAlfredo Cardigliano int
1619669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1620669c8de6SAlfredo Cardigliano {
1621669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1622656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
1623669c8de6SAlfredo Cardigliano 	int err;
1624669c8de6SAlfredo Cardigliano 
16253cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
16263cdfd905SAlfredo Cardigliano 
162700b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1628669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1629669c8de6SAlfredo Cardigliano 	if (err)
1630669c8de6SAlfredo Cardigliano 		return err;
1631669c8de6SAlfredo Cardigliano 
1632656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1633656bfc9aSAndrew Boyer 
163409f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1635669c8de6SAlfredo Cardigliano 
163601a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
163701a6c311SAlfredo Cardigliano 	if (err)
163801a6c311SAlfredo Cardigliano 		return err;
163901a6c311SAlfredo Cardigliano 
164027b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
164127b942c8SAlfredo Cardigliano 	if (err)
164227b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
164327b942c8SAlfredo Cardigliano 
164418a44465SAndrew Boyer 	/*
164518a44465SAndrew Boyer 	 * Configure initial feature set
164618a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
164718a44465SAndrew Boyer 	 */
164818a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1649598f6726SAlfredo Cardigliano 
1650598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1651598f6726SAlfredo Cardigliano 	if (err)
1652598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1653598f6726SAlfredo Cardigliano 
165454fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1655598f6726SAlfredo Cardigliano 	if (err)
1656598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1657598f6726SAlfredo Cardigliano 
165854fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
165954fe083fSAlfredo Cardigliano 	if (err)
166054fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
166154fe083fSAlfredo Cardigliano 
1662598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1663598f6726SAlfredo Cardigliano 
1664669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1665669c8de6SAlfredo Cardigliano 
1666669c8de6SAlfredo Cardigliano 	return 0;
166727b942c8SAlfredo Cardigliano 
166854fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
166954fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
167054fe083fSAlfredo Cardigliano 
1671598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
16724c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1673598f6726SAlfredo Cardigliano 
167427b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1675be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
167627b942c8SAlfredo Cardigliano 
167727b942c8SAlfredo Cardigliano 	return err;
1678669c8de6SAlfredo Cardigliano }
1679669c8de6SAlfredo Cardigliano 
1680669c8de6SAlfredo Cardigliano void
1681669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1682669c8de6SAlfredo Cardigliano {
1683669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1684669c8de6SAlfredo Cardigliano 		return;
1685669c8de6SAlfredo Cardigliano 
168654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
168722e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
16884c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1689be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
169001a6c311SAlfredo Cardigliano 
1691669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1692669c8de6SAlfredo Cardigliano }
1693669c8de6SAlfredo Cardigliano 
169418a44465SAndrew Boyer void
169518a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
169618a44465SAndrew Boyer {
169718a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
169818a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
169918a44465SAndrew Boyer 
170018a44465SAndrew Boyer 	/*
170118a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1702295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
170318a44465SAndrew Boyer 	 */
1704295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
170518a44465SAndrew Boyer 
1706295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1707295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
170818a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
170918a44465SAndrew Boyer 		else
171018a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
171118a44465SAndrew Boyer 	}
171218a44465SAndrew Boyer }
171318a44465SAndrew Boyer 
171418a44465SAndrew Boyer void
1715598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1716598f6726SAlfredo Cardigliano {
171718a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
171818a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
171922e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
172009f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
172122e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
172209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
172322e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
172409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
172522e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
172622e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
172722e7171bSAlfredo Cardigliano 
1728598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1729598f6726SAlfredo Cardigliano 
173022e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
173122e7171bSAlfredo Cardigliano 		lif->port_id);
173222e7171bSAlfredo Cardigliano 
173322e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
173422e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
173522e7171bSAlfredo Cardigliano 
173622e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
173722e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
173822e7171bSAlfredo Cardigliano 
173922e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
174022e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1741a27d9013SAlfredo Cardigliano 
174218a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
174318a44465SAndrew Boyer 
174418a44465SAndrew Boyer 	/*
174518a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
174618a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1747295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
174818a44465SAndrew Boyer 	 */
174918a44465SAndrew Boyer 
175018a44465SAndrew Boyer 	/* RX per-port */
175118a44465SAndrew Boyer 
1752295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1753295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1754295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
175518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
175618a44465SAndrew Boyer 	else
175718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
175818a44465SAndrew Boyer 
1759295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
176018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
176118a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
176218a44465SAndrew Boyer 	} else {
176318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
176418a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
176518a44465SAndrew Boyer 	}
176618a44465SAndrew Boyer 
176718a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1768295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
176918a44465SAndrew Boyer 
177018a44465SAndrew Boyer 	/* TX per-port */
177118a44465SAndrew Boyer 
1772295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1773295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1774295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1775295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1776295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
177718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
177818a44465SAndrew Boyer 	else
177918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
178018a44465SAndrew Boyer 
1781295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
178218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
178318a44465SAndrew Boyer 	else
178418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
178518a44465SAndrew Boyer 
1786295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
178718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
178818a44465SAndrew Boyer 	else
178918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
179018a44465SAndrew Boyer 
1791295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
179218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
179318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
179418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
179518a44465SAndrew Boyer 	} else {
179618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
179718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
179818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
179918a44465SAndrew Boyer 	}
1800598f6726SAlfredo Cardigliano }
1801598f6726SAlfredo Cardigliano 
1802598f6726SAlfredo Cardigliano int
1803598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1804598f6726SAlfredo Cardigliano {
18050578335aSAndrew Boyer 	uint32_t rx_mode;
1806a27d9013SAlfredo Cardigliano 	uint32_t i;
1807a27d9013SAlfredo Cardigliano 	int err;
1808598f6726SAlfredo Cardigliano 
180922e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
181022e7171bSAlfredo Cardigliano 	if (err)
181122e7171bSAlfredo Cardigliano 		return err;
181222e7171bSAlfredo Cardigliano 
18130578335aSAndrew Boyer 	if (!lif->rx_mode) {
18140578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
18150578335aSAndrew Boyer 			lif->name);
1816598f6726SAlfredo Cardigliano 
18170578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1818598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1819598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1820598f6726SAlfredo Cardigliano 
1821598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18220578335aSAndrew Boyer 	}
1823598f6726SAlfredo Cardigliano 
1824a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1825a27d9013SAlfredo Cardigliano 		"on port %u",
1826a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1827a27d9013SAlfredo Cardigliano 
1828a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1829be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
183002eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1831a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1832a27d9013SAlfredo Cardigliano 
1833a27d9013SAlfredo Cardigliano 			if (err)
1834a27d9013SAlfredo Cardigliano 				return err;
1835a27d9013SAlfredo Cardigliano 		}
1836a27d9013SAlfredo Cardigliano 	}
1837a27d9013SAlfredo Cardigliano 
1838a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1839be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
184002eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1841a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1842a27d9013SAlfredo Cardigliano 
1843a27d9013SAlfredo Cardigliano 			if (err)
1844a27d9013SAlfredo Cardigliano 				return err;
1845a27d9013SAlfredo Cardigliano 		}
1846a27d9013SAlfredo Cardigliano 	}
1847a27d9013SAlfredo Cardigliano 
1848598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1849be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1850be63459eSAndrew Boyer 
1851be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1852598f6726SAlfredo Cardigliano 
1853598f6726SAlfredo Cardigliano 	return 0;
1854598f6726SAlfredo Cardigliano }
1855598f6726SAlfredo Cardigliano 
1856598f6726SAlfredo Cardigliano int
1857669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1858669c8de6SAlfredo Cardigliano {
1859669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1860669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
186109f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
186276276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
186376276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
186476276d71SAndrew Boyer 	uint32_t i, nwords;
1865669c8de6SAlfredo Cardigliano 	int err;
1866669c8de6SAlfredo Cardigliano 
1867669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1868669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1869669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1870669c8de6SAlfredo Cardigliano 	if (err)
1871669c8de6SAlfredo Cardigliano 		return (err);
1872669c8de6SAlfredo Cardigliano 
1873669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1874669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1875669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1876669c8de6SAlfredo Cardigliano 
1877669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
187809f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1879669c8de6SAlfredo Cardigliano 
1880669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
188109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1882669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
188309f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1884669c8de6SAlfredo Cardigliano 
1885669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
188609f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1887669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
188809f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1889669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
189009f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1891669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
189209f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1893669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
189409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1895669c8de6SAlfredo Cardigliano 
1896669c8de6SAlfredo Cardigliano 	return 0;
1897669c8de6SAlfredo Cardigliano }
1898669c8de6SAlfredo Cardigliano 
1899669c8de6SAlfredo Cardigliano int
1900669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1901669c8de6SAlfredo Cardigliano {
1902669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
190309f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
190409f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1905669c8de6SAlfredo Cardigliano 
1906669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
190709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1908669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
190909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1910669c8de6SAlfredo Cardigliano 
191100b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1912669c8de6SAlfredo Cardigliano 
1913669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
19144ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
19154ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1916669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1917669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1918669c8de6SAlfredo Cardigliano 	}
1919669c8de6SAlfredo Cardigliano 
1920669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1921669c8de6SAlfredo Cardigliano 
1922669c8de6SAlfredo Cardigliano 	return 0;
1923669c8de6SAlfredo Cardigliano }
1924