xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision a5205992d9789a84a7ff803f80308cbf82847f5c)
1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2*a5205992SAndrew 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 
3301a6c311SAlfredo Cardigliano int
3401a6c311SAlfredo Cardigliano ionic_qcq_enable(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_ENABLE,
4501a6c311SAlfredo Cardigliano 		},
4601a6c311SAlfredo Cardigliano 	};
4701a6c311SAlfredo Cardigliano 
4801a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4901a6c311SAlfredo Cardigliano }
5001a6c311SAlfredo Cardigliano 
5101a6c311SAlfredo Cardigliano int
5201a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
5301a6c311SAlfredo Cardigliano {
5401a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
554ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
5601a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
5701a6c311SAlfredo Cardigliano 		.pending_work = true,
5801a6c311SAlfredo Cardigliano 		.cmd.q_control = {
5901a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
6001a6c311SAlfredo Cardigliano 			.type = q->type,
6109f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
6201a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
6301a6c311SAlfredo Cardigliano 		},
6401a6c311SAlfredo Cardigliano 	};
6501a6c311SAlfredo Cardigliano 
6601a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6701a6c311SAlfredo Cardigliano }
6801a6c311SAlfredo Cardigliano 
69be63459eSAndrew Boyer void
70be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
71598f6726SAlfredo Cardigliano {
72a0a99f21SAndrew Boyer 	uint32_t i;
73a0a99f21SAndrew Boyer 
74be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
75598f6726SAlfredo Cardigliano 
76be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
77a0a99f21SAndrew Boyer 
78a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
79be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
80a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
81a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
82a0a99f21SAndrew Boyer 	}
83a0a99f21SAndrew Boyer 
84a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
85be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
86a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
87a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
88a0a99f21SAndrew Boyer 	}
89598f6726SAlfredo Cardigliano }
90598f6726SAlfredo Cardigliano 
91598f6726SAlfredo Cardigliano void
92598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
93598f6726SAlfredo Cardigliano {
94598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
9575f96902SAndrew Boyer 	int err;
96598f6726SAlfredo Cardigliano 
97598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
98598f6726SAlfredo Cardigliano 
9900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
10075f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
10175f96902SAndrew Boyer 	if (err)
1024ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
103598f6726SAlfredo Cardigliano }
104598f6726SAlfredo Cardigliano 
1053cdfd905SAlfredo Cardigliano static void
1063cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
1073cdfd905SAlfredo Cardigliano {
1083cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
1093cdfd905SAlfredo Cardigliano 	uint32_t i;
1103cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
1113cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1123cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
1133cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1143cdfd905SAlfredo Cardigliano 
1153cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1163cdfd905SAlfredo Cardigliano 
1173cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1183cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1193cdfd905SAlfredo Cardigliano 			lif->port_id);
1203cdfd905SAlfredo Cardigliano 		return;
1213cdfd905SAlfredo Cardigliano 	}
1223cdfd905SAlfredo Cardigliano 
1233cdfd905SAlfredo Cardigliano 	/* RX */
1243cdfd905SAlfredo Cardigliano 
1253cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1263cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1273cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1283cdfd905SAlfredo Cardigliano 
1293cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1303cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1313cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1323cdfd905SAlfredo Cardigliano 
1333cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
134be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
13526cc5dc2SAndrew Boyer 		stats->ierrors +=
1363cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1373cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1383cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1393cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1403cdfd905SAlfredo Cardigliano 	}
1413cdfd905SAlfredo Cardigliano 
1423cdfd905SAlfredo Cardigliano 	stats->imissed +=
1433cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1443cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1453cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1463cdfd905SAlfredo Cardigliano 
14726cc5dc2SAndrew Boyer 	stats->ierrors +=
1483cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1493cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1503cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1513cdfd905SAlfredo Cardigliano 
1523cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
153be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1543cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1553cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1563cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1573cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1583cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1593cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1603cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1613cdfd905SAlfredo Cardigliano 	}
1623cdfd905SAlfredo Cardigliano 
1633cdfd905SAlfredo Cardigliano 	/* TX */
1643cdfd905SAlfredo Cardigliano 
1653cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1663cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1673cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1683cdfd905SAlfredo Cardigliano 
1693cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1703cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1713cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1723cdfd905SAlfredo Cardigliano 
1733cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
174be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1753cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1763cdfd905SAlfredo Cardigliano 	}
1773cdfd905SAlfredo Cardigliano 
1783cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1793cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1803cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1813cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1823cdfd905SAlfredo Cardigliano 
1833cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1843cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1853cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1863cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1873cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1883cdfd905SAlfredo Cardigliano 
1893cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
190be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1913cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1923cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1933cdfd905SAlfredo Cardigliano 	}
1943cdfd905SAlfredo Cardigliano }
1953cdfd905SAlfredo Cardigliano 
1963cdfd905SAlfredo Cardigliano void
1973cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1983cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1993cdfd905SAlfredo Cardigliano {
2003cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
2013cdfd905SAlfredo Cardigliano 
2023cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
2033cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
2043cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
2053cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
2063cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
2073cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
2083cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
2093cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
2103cdfd905SAlfredo Cardigliano }
2113cdfd905SAlfredo Cardigliano 
2123cdfd905SAlfredo Cardigliano void
2133cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2143cdfd905SAlfredo Cardigliano {
2153cdfd905SAlfredo Cardigliano 	uint32_t i;
2163cdfd905SAlfredo Cardigliano 
2173cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
218be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
2193cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
220be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
2213cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2223cdfd905SAlfredo Cardigliano 	}
2233cdfd905SAlfredo Cardigliano 
2243cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2253cdfd905SAlfredo Cardigliano }
2263cdfd905SAlfredo Cardigliano 
2273cdfd905SAlfredo Cardigliano void
2283cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2293cdfd905SAlfredo Cardigliano {
2303cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2313cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2323cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2333cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2343cdfd905SAlfredo Cardigliano 
2353cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2363cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2373cdfd905SAlfredo Cardigliano }
2383cdfd905SAlfredo Cardigliano 
2393cdfd905SAlfredo Cardigliano void
2403cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2413cdfd905SAlfredo Cardigliano {
2423cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2433cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2443cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2453cdfd905SAlfredo Cardigliano 
2463cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2473cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2483cdfd905SAlfredo Cardigliano }
2493cdfd905SAlfredo Cardigliano 
250598f6726SAlfredo Cardigliano static int
25154fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
252598f6726SAlfredo Cardigliano {
25354fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25454fe083fSAlfredo Cardigliano 		.pending_work = true,
25554fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
25654fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
25709f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
25854fe083fSAlfredo Cardigliano 		},
25954fe083fSAlfredo Cardigliano 	};
26054fe083fSAlfredo Cardigliano 	int err;
26154fe083fSAlfredo Cardigliano 
26254fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
26554fe083fSAlfredo Cardigliano 	if (err)
26654fe083fSAlfredo Cardigliano 		return err;
26754fe083fSAlfredo Cardigliano 
26854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
26909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
27054fe083fSAlfredo Cardigliano 
27154fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
27254fe083fSAlfredo Cardigliano }
27354fe083fSAlfredo Cardigliano 
27454fe083fSAlfredo Cardigliano static int
27554fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
27654fe083fSAlfredo Cardigliano {
27754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
27854fe083fSAlfredo Cardigliano 		.pending_work = true,
27954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
28054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
28154fe083fSAlfredo Cardigliano 		},
28254fe083fSAlfredo Cardigliano 	};
28354fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
28454fe083fSAlfredo Cardigliano 	int err;
28554fe083fSAlfredo Cardigliano 
28654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
28754fe083fSAlfredo Cardigliano 
28854fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
28954fe083fSAlfredo Cardigliano 
29054fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
29154fe083fSAlfredo Cardigliano 	if (!f) {
29254fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
29354fe083fSAlfredo Cardigliano 		return -ENOENT;
29454fe083fSAlfredo Cardigliano 	}
29554fe083fSAlfredo Cardigliano 
29609f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
29754fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
29854fe083fSAlfredo Cardigliano 
29954fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
30054fe083fSAlfredo Cardigliano 
30154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
30254fe083fSAlfredo Cardigliano 	if (err)
30354fe083fSAlfredo Cardigliano 		return err;
30454fe083fSAlfredo Cardigliano 
30554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
30609f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
307598f6726SAlfredo Cardigliano 
308598f6726SAlfredo Cardigliano 	return 0;
309598f6726SAlfredo Cardigliano }
310598f6726SAlfredo Cardigliano 
31154fe083fSAlfredo Cardigliano int
31254fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
31354fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
31454fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
315598f6726SAlfredo Cardigliano {
31654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31754fe083fSAlfredo Cardigliano 
31854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31954fe083fSAlfredo Cardigliano 
32054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
32154fe083fSAlfredo Cardigliano }
32254fe083fSAlfredo Cardigliano 
32354fe083fSAlfredo Cardigliano void
32475f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
32554fe083fSAlfredo Cardigliano {
32654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32754fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
32875f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
32954fe083fSAlfredo Cardigliano 
33054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
33354fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
33454fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
33554fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
33654fe083fSAlfredo Cardigliano 		return;
33754fe083fSAlfredo Cardigliano 	}
33854fe083fSAlfredo Cardigliano 
33975f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
34075f96902SAndrew Boyer 
34175f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
34254fe083fSAlfredo Cardigliano 		return;
34354fe083fSAlfredo Cardigliano 
34475f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
34554fe083fSAlfredo Cardigliano }
34654fe083fSAlfredo Cardigliano 
34754fe083fSAlfredo Cardigliano int
34854fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
34954fe083fSAlfredo Cardigliano {
35054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
35154fe083fSAlfredo Cardigliano 
35254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
35354fe083fSAlfredo Cardigliano 
35454fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
35554fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
35654fe083fSAlfredo Cardigliano 		return -1;
35754fe083fSAlfredo Cardigliano 	}
35854fe083fSAlfredo Cardigliano 
35954fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
36054fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
36154fe083fSAlfredo Cardigliano 			lif->mac_addr);
36254fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
36354fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
36454fe083fSAlfredo Cardigliano 	}
36554fe083fSAlfredo Cardigliano 
36654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
36954fe083fSAlfredo Cardigliano 
37054fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
37154fe083fSAlfredo Cardigliano }
37254fe083fSAlfredo Cardigliano 
37354fe083fSAlfredo Cardigliano static int
37454fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
37554fe083fSAlfredo Cardigliano {
37654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37754fe083fSAlfredo Cardigliano 		.pending_work = true,
37854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
37954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
38009f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
38109f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
38254fe083fSAlfredo Cardigliano 		},
38354fe083fSAlfredo Cardigliano 	};
38454fe083fSAlfredo Cardigliano 	int err;
38554fe083fSAlfredo Cardigliano 
38654fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
38754fe083fSAlfredo Cardigliano 	if (err)
38854fe083fSAlfredo Cardigliano 		return err;
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
39109f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
39254fe083fSAlfredo Cardigliano 
39354fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
39454fe083fSAlfredo Cardigliano }
39554fe083fSAlfredo Cardigliano 
39654fe083fSAlfredo Cardigliano static int
39754fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
39854fe083fSAlfredo Cardigliano {
39954fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
40054fe083fSAlfredo Cardigliano 		.pending_work = true,
40154fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
40254fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
40354fe083fSAlfredo Cardigliano 		},
40454fe083fSAlfredo Cardigliano 	};
40554fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
40654fe083fSAlfredo Cardigliano 	int err;
40754fe083fSAlfredo Cardigliano 
40854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
40954fe083fSAlfredo Cardigliano 
41054fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
41154fe083fSAlfredo Cardigliano 
41254fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
41354fe083fSAlfredo Cardigliano 	if (!f) {
41454fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
41554fe083fSAlfredo Cardigliano 		return -ENOENT;
41654fe083fSAlfredo Cardigliano 	}
41754fe083fSAlfredo Cardigliano 
41809f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
41954fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
42054fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
42154fe083fSAlfredo Cardigliano 
42254fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
42354fe083fSAlfredo Cardigliano 	if (err)
42454fe083fSAlfredo Cardigliano 		return err;
42554fe083fSAlfredo Cardigliano 
42654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
42709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
428598f6726SAlfredo Cardigliano 
429598f6726SAlfredo Cardigliano 	return 0;
430598f6726SAlfredo Cardigliano }
431598f6726SAlfredo Cardigliano 
43254fe083fSAlfredo Cardigliano int
43354fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
43454fe083fSAlfredo Cardigliano 		int on)
43554fe083fSAlfredo Cardigliano {
43654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
43754fe083fSAlfredo Cardigliano 	int err;
43854fe083fSAlfredo Cardigliano 
43954fe083fSAlfredo Cardigliano 	if (on)
44054fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
44154fe083fSAlfredo Cardigliano 	else
44254fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
44354fe083fSAlfredo Cardigliano 
44454fe083fSAlfredo Cardigliano 	return err;
44554fe083fSAlfredo Cardigliano }
44654fe083fSAlfredo Cardigliano 
447598f6726SAlfredo Cardigliano static void
448598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
449598f6726SAlfredo Cardigliano {
450598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
451598f6726SAlfredo Cardigliano 		.pending_work = true,
452598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
453598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
45409f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
455598f6726SAlfredo Cardigliano 		},
456598f6726SAlfredo Cardigliano 	};
457598f6726SAlfredo Cardigliano 	int err;
458598f6726SAlfredo Cardigliano 
459598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
460598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
461598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
462598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
463598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
464598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
465598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
466598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
467598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
468598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
469598f6726SAlfredo Cardigliano 
470598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
471598f6726SAlfredo Cardigliano 	if (err)
472598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
473598f6726SAlfredo Cardigliano }
474598f6726SAlfredo Cardigliano 
475598f6726SAlfredo Cardigliano static void
476598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
477598f6726SAlfredo Cardigliano {
478598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
479598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
480598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
481598f6726SAlfredo Cardigliano 	}
482598f6726SAlfredo Cardigliano }
483598f6726SAlfredo Cardigliano 
48454fe083fSAlfredo Cardigliano int
48554fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
48654fe083fSAlfredo Cardigliano {
48754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
49354fe083fSAlfredo Cardigliano 
49454fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	return 0;
49754fe083fSAlfredo Cardigliano }
49854fe083fSAlfredo Cardigliano 
49954fe083fSAlfredo Cardigliano int
50054fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
50154fe083fSAlfredo Cardigliano {
50254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50354fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
50654fe083fSAlfredo Cardigliano 
50754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	return 0;
51054fe083fSAlfredo Cardigliano }
51154fe083fSAlfredo Cardigliano 
51254fe083fSAlfredo Cardigliano int
51354fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
51454fe083fSAlfredo Cardigliano {
51554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
51954fe083fSAlfredo Cardigliano 
52054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52154fe083fSAlfredo Cardigliano 
52254fe083fSAlfredo Cardigliano 	return 0;
52354fe083fSAlfredo Cardigliano }
52454fe083fSAlfredo Cardigliano 
52554fe083fSAlfredo Cardigliano int
52654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
52754fe083fSAlfredo Cardigliano {
52854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
52954fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
53054fe083fSAlfredo Cardigliano 
53154fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
53254fe083fSAlfredo Cardigliano 
53354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
53454fe083fSAlfredo Cardigliano 
53554fe083fSAlfredo Cardigliano 	return 0;
53654fe083fSAlfredo Cardigliano }
537598f6726SAlfredo Cardigliano 
538598f6726SAlfredo Cardigliano int
539598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
540598f6726SAlfredo Cardigliano {
541598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
542598f6726SAlfredo Cardigliano 		.pending_work = true,
543598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
544598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
545598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
54609f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
547598f6726SAlfredo Cardigliano 		},
548598f6726SAlfredo Cardigliano 	};
549598f6726SAlfredo Cardigliano 	int err;
550598f6726SAlfredo Cardigliano 
551598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
552598f6726SAlfredo Cardigliano 	if (err)
553598f6726SAlfredo Cardigliano 		return err;
554598f6726SAlfredo Cardigliano 
555598f6726SAlfredo Cardigliano 	return 0;
556598f6726SAlfredo Cardigliano }
557598f6726SAlfredo Cardigliano 
558598f6726SAlfredo Cardigliano int
55901a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
56001a6c311SAlfredo Cardigliano {
56101a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
56201a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
56301a6c311SAlfredo Cardigliano 	unsigned long index;
56401a6c311SAlfredo Cardigliano 
56501a6c311SAlfredo Cardigliano 	/*
56601a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
56701a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5684ae96cb8SAndrew Boyer 	 * which has index = 0)
56901a6c311SAlfredo Cardigliano 	 */
57001a6c311SAlfredo Cardigliano 
57101a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
57201a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
57301a6c311SAlfredo Cardigliano 			break;
57401a6c311SAlfredo Cardigliano 
57501a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
57601a6c311SAlfredo Cardigliano 		return -ENOSPC;
57701a6c311SAlfredo Cardigliano 
57801a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
57901a6c311SAlfredo Cardigliano 
58001a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
58101a6c311SAlfredo Cardigliano 
58201a6c311SAlfredo Cardigliano 	return 0;
58301a6c311SAlfredo Cardigliano }
58401a6c311SAlfredo Cardigliano 
58501a6c311SAlfredo Cardigliano static int
5864ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5874ad56b7aSAndrew Boyer 		uint8_t type,
588be39f75cSAndrew Boyer 		size_t struct_size,
5898ec5ad7fSAndrew Boyer 		uint32_t socket_id,
59001a6c311SAlfredo Cardigliano 		uint32_t index,
5914ad56b7aSAndrew Boyer 		const char *type_name,
5924ad56b7aSAndrew Boyer 		uint16_t flags,
5934ad56b7aSAndrew Boyer 		uint16_t num_descs,
5944ad56b7aSAndrew Boyer 		uint16_t desc_size,
5954ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5964ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5971abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
59801a6c311SAlfredo Cardigliano {
59901a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
60001a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
60101a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
60201a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
60301a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
60401a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
60501a6c311SAlfredo Cardigliano 	int err;
60601a6c311SAlfredo Cardigliano 
60701a6c311SAlfredo Cardigliano 	*qcq = NULL;
60801a6c311SAlfredo Cardigliano 
60901a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
61001a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
61101a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
61201a6c311SAlfredo Cardigliano 
613924e6b76SThomas Monjalon 	total_size = RTE_ALIGN(q_size, rte_mem_page_size()) +
614924e6b76SThomas Monjalon 			RTE_ALIGN(cq_size, rte_mem_page_size());
61501a6c311SAlfredo Cardigliano 	/*
61601a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61701a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
618924e6b76SThomas Monjalon 	 * Adding rte_mem_page_size().
61901a6c311SAlfredo Cardigliano 	 */
620924e6b76SThomas Monjalon 	total_size += rte_mem_page_size();
62101a6c311SAlfredo Cardigliano 
62201a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
623924e6b76SThomas Monjalon 		total_size += RTE_ALIGN(sg_size, rte_mem_page_size());
624924e6b76SThomas Monjalon 		total_size += rte_mem_page_size();
62501a6c311SAlfredo Cardigliano 	}
62601a6c311SAlfredo Cardigliano 
627be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
62801a6c311SAlfredo Cardigliano 	if (!new) {
62901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
63001a6c311SAlfredo Cardigliano 		return -ENOMEM;
63101a6c311SAlfredo Cardigliano 	}
63201a6c311SAlfredo Cardigliano 
63301a6c311SAlfredo Cardigliano 	new->lif = lif;
63401a6c311SAlfredo Cardigliano 
635be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
636be39f75cSAndrew Boyer 				num_descs, sizeof(void *),
637924e6b76SThomas Monjalon 				rte_mem_page_size(), socket_id);
63801a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6404c8f8d57SAndrew Boyer 		err = -ENOMEM;
6414c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
64401a6c311SAlfredo Cardigliano 	new->q.type = type;
64501a6c311SAlfredo Cardigliano 
6464ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
64701a6c311SAlfredo Cardigliano 	if (err) {
64801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6494c8f8d57SAndrew Boyer 		goto err_out_free_info;
65001a6c311SAlfredo Cardigliano 	}
65101a6c311SAlfredo Cardigliano 
6522aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
65301a6c311SAlfredo Cardigliano 	if (err) {
65401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6554c8f8d57SAndrew Boyer 		goto err_out_free_info;
65601a6c311SAlfredo Cardigliano 	}
65701a6c311SAlfredo Cardigliano 
65801a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6594ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
66001a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66101a6c311SAlfredo Cardigliano 
66201a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66401a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6654c8f8d57SAndrew Boyer 		goto err_out_free_info;
66601a6c311SAlfredo Cardigliano 	}
66701a6c311SAlfredo Cardigliano 
66801a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66901a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67001a6c311SAlfredo Cardigliano 
67101a6c311SAlfredo Cardigliano 	q_base = new->base;
67201a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67301a6c311SAlfredo Cardigliano 
674924e6b76SThomas Monjalon 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size,
675924e6b76SThomas Monjalon 			rte_mem_page_size());
676924e6b76SThomas Monjalon 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size,
677924e6b76SThomas Monjalon 			rte_mem_page_size());
67801a6c311SAlfredo Cardigliano 
67901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
68001a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
681924e6b76SThomas Monjalon 				rte_mem_page_size());
682924e6b76SThomas Monjalon 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size,
683924e6b76SThomas Monjalon 				rte_mem_page_size());
68401a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68501a6c311SAlfredo Cardigliano 	}
68601a6c311SAlfredo Cardigliano 
6874ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6884ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68901a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
69001a6c311SAlfredo Cardigliano 
69101a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69201a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	*qcq = new;
69501a6c311SAlfredo Cardigliano 
69601a6c311SAlfredo Cardigliano 	return 0;
69701a6c311SAlfredo Cardigliano 
6984c8f8d57SAndrew Boyer err_out_free_info:
6994c8f8d57SAndrew Boyer 	rte_free(new->q.info);
7004c8f8d57SAndrew Boyer err_out_free_qcq:
7014c8f8d57SAndrew Boyer 	rte_free(new);
70201a6c311SAlfredo Cardigliano 
70301a6c311SAlfredo Cardigliano 	return err;
70401a6c311SAlfredo Cardigliano }
70501a6c311SAlfredo Cardigliano 
70601a6c311SAlfredo Cardigliano void
70701a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70801a6c311SAlfredo Cardigliano {
70901a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
71001a6c311SAlfredo Cardigliano 		qcq->base = NULL;
71101a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71201a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71301a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71401a6c311SAlfredo Cardigliano 	}
71501a6c311SAlfredo Cardigliano 
71601a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71701a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71801a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71901a6c311SAlfredo Cardigliano 	}
72001a6c311SAlfredo Cardigliano 
72101a6c311SAlfredo Cardigliano 	rte_free(qcq);
72201a6c311SAlfredo Cardigliano }
72301a6c311SAlfredo Cardigliano 
724a27d9013SAlfredo Cardigliano int
7258ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
726be39f75cSAndrew Boyer 		uint16_t nrxq_descs, struct ionic_rx_qcq **rxq_out)
727a27d9013SAlfredo Cardigliano {
728be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
729be39f75cSAndrew Boyer 	uint16_t flags;
730be39f75cSAndrew Boyer 	int err;
731a27d9013SAlfredo Cardigliano 
732a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
7334ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7344ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
735be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7368ec5ad7fSAndrew Boyer 		socket_id,
7374ad56b7aSAndrew Boyer 		index,
7384ad56b7aSAndrew Boyer 		"rx",
7394ad56b7aSAndrew Boyer 		flags,
740a27d9013SAlfredo Cardigliano 		nrxq_descs,
741a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
742a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
743a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
744be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
745a27d9013SAlfredo Cardigliano 	if (err)
746a27d9013SAlfredo Cardigliano 		return err;
747a27d9013SAlfredo Cardigliano 
748be39f75cSAndrew Boyer 	rxq->flags = flags;
749be39f75cSAndrew Boyer 
750be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
751be39f75cSAndrew Boyer 	*rxq_out = rxq;
752a27d9013SAlfredo Cardigliano 
753a27d9013SAlfredo Cardigliano 	return 0;
754a27d9013SAlfredo Cardigliano }
755a27d9013SAlfredo Cardigliano 
756a27d9013SAlfredo Cardigliano int
7578ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
758be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
759a27d9013SAlfredo Cardigliano {
760be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
761e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
762be39f75cSAndrew Boyer 	int err;
763a27d9013SAlfredo Cardigliano 
764a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
765e19eea1eSAndrew Boyer 
766e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
767e19eea1eSAndrew Boyer 
7684ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7694ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
770be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
7718ec5ad7fSAndrew Boyer 		socket_id,
7724ad56b7aSAndrew Boyer 		index,
7734ad56b7aSAndrew Boyer 		"tx",
7744ad56b7aSAndrew Boyer 		flags,
775a27d9013SAlfredo Cardigliano 		ntxq_descs,
776a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
777a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
77856117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
779be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
780a27d9013SAlfredo Cardigliano 	if (err)
781a27d9013SAlfredo Cardigliano 		return err;
782a27d9013SAlfredo Cardigliano 
783be39f75cSAndrew Boyer 	txq->flags = flags;
784e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
785be39f75cSAndrew Boyer 
786be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
787be39f75cSAndrew Boyer 	*txq_out = txq;
788a27d9013SAlfredo Cardigliano 
789a27d9013SAlfredo Cardigliano 	return 0;
790a27d9013SAlfredo Cardigliano }
791a27d9013SAlfredo Cardigliano 
79201a6c311SAlfredo Cardigliano static int
79301a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
79401a6c311SAlfredo Cardigliano {
795be39f75cSAndrew Boyer 	uint16_t flags = 0;
796be39f75cSAndrew Boyer 	int err;
79701a6c311SAlfredo Cardigliano 
7984ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7994ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
800be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8018ec5ad7fSAndrew Boyer 		rte_socket_id(),
8024ad56b7aSAndrew Boyer 		0,
8034ad56b7aSAndrew Boyer 		"admin",
8044ad56b7aSAndrew Boyer 		flags,
80501a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
80601a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
80701a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
80801a6c311SAlfredo Cardigliano 		0,
809be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
81027b942c8SAlfredo Cardigliano 	if (err)
81127b942c8SAlfredo Cardigliano 		return err;
81201a6c311SAlfredo Cardigliano 
81327b942c8SAlfredo Cardigliano 	return 0;
81427b942c8SAlfredo Cardigliano }
81527b942c8SAlfredo Cardigliano 
81627b942c8SAlfredo Cardigliano static int
81727b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
81827b942c8SAlfredo Cardigliano {
819be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8204c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
821be39f75cSAndrew Boyer 	uint16_t flags = 0;
822be39f75cSAndrew Boyer 	int err;
82327b942c8SAlfredo Cardigliano 
8244ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8254ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
826be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8278ec5ad7fSAndrew Boyer 		rte_socket_id(),
8284ad56b7aSAndrew Boyer 		0,
8294ad56b7aSAndrew Boyer 		"notify",
83027b942c8SAlfredo Cardigliano 		flags,
83127b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
83227b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
83327b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
83427b942c8SAlfredo Cardigliano 		0,
835be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
83601a6c311SAlfredo Cardigliano 	if (err)
83701a6c311SAlfredo Cardigliano 		return err;
83801a6c311SAlfredo Cardigliano 
8394c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8404c8f8d57SAndrew Boyer 	if (err) {
841be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
8424c8f8d57SAndrew Boyer 		return err;
8434c8f8d57SAndrew Boyer 	}
8444c8f8d57SAndrew Boyer 
8454c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8464c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8474c8f8d57SAndrew Boyer 
8484c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8494c8f8d57SAndrew Boyer 
85001a6c311SAlfredo Cardigliano 	return 0;
85101a6c311SAlfredo Cardigliano }
85201a6c311SAlfredo Cardigliano 
853c67719e1SAlfredo Cardigliano static void *
854c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
855c67719e1SAlfredo Cardigliano {
856c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
857c67719e1SAlfredo Cardigliano 
858c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
859c67719e1SAlfredo Cardigliano 		return NULL;
860c67719e1SAlfredo Cardigliano 
861c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
862c67719e1SAlfredo Cardigliano }
863c67719e1SAlfredo Cardigliano 
864c5d15850SAndrew Boyer static void
865c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
866c5d15850SAndrew Boyer {
867c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
868c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
869c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
870c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
871c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
872c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
873c5d15850SAndrew Boyer 	int err;
874c5d15850SAndrew Boyer 
875c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
876c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
877c5d15850SAndrew Boyer 
878c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
879c5d15850SAndrew Boyer 		switch (qtype) {
880c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
881c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
882c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
883c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
884c5d15850SAndrew Boyer 			break;
885c5d15850SAndrew Boyer 		default:
886c5d15850SAndrew Boyer 			continue;
887c5d15850SAndrew Boyer 		}
888c5d15850SAndrew Boyer 
889c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
890c5d15850SAndrew Boyer 
891c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
892c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
893c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
894c5d15850SAndrew Boyer 		if (err == -EINVAL) {
895c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
896c5d15850SAndrew Boyer 			continue;
897c5d15850SAndrew Boyer 		} else if (err == -EIO) {
898c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
899c5d15850SAndrew Boyer 			return;
900c5d15850SAndrew Boyer 		} else if (err) {
901c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
902c5d15850SAndrew Boyer 				qtype, err);
903c5d15850SAndrew Boyer 			return;
904c5d15850SAndrew Boyer 		}
905c5d15850SAndrew Boyer 
906c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
907c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
908c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
909c5d15850SAndrew Boyer 
910c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
911c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
912c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
913c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
914c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
915c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
916c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
917c5d15850SAndrew Boyer 		qti->sg_desc_stride =
918c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
919c5d15850SAndrew Boyer 
920c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
921c5d15850SAndrew Boyer 			qtype, qti->version);
922c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
923c5d15850SAndrew Boyer 			qtype, qti->supported);
924c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
925c5d15850SAndrew Boyer 			qtype, qti->features);
926c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
927c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
928c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
929c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
930c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
931c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
932c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
933c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
934c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
935c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
936c5d15850SAndrew Boyer 	}
937c5d15850SAndrew Boyer }
938c5d15850SAndrew Boyer 
939669c8de6SAlfredo Cardigliano int
940669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
941669c8de6SAlfredo Cardigliano {
942c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
943669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
94401a6c311SAlfredo Cardigliano 	int err;
945669c8de6SAlfredo Cardigliano 
9464ae96cb8SAndrew Boyer 	/*
9474ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9484ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9494ae96cb8SAndrew Boyer 	 */
9504ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9514ae96cb8SAndrew Boyer 
9524ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
953669c8de6SAlfredo Cardigliano 
954c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
955c5d15850SAndrew Boyer 
95656117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
95756117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
95856117636SAndrew Boyer 		return -ENXIO;
95956117636SAndrew Boyer 	}
96056117636SAndrew Boyer 
961669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
962669c8de6SAlfredo Cardigliano 
96301a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
96401a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
96501a6c311SAlfredo Cardigliano 
96600b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
967c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
968c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
969c67719e1SAlfredo Cardigliano 		return -ENOMEM;
970c67719e1SAlfredo Cardigliano 	}
971c67719e1SAlfredo Cardigliano 
972a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
973a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
974a27d9013SAlfredo Cardigliano 
975a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
976a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
977a27d9013SAlfredo Cardigliano 		return -ENOMEM;
978a27d9013SAlfredo Cardigliano 	}
979a27d9013SAlfredo Cardigliano 
980a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
981a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
982a27d9013SAlfredo Cardigliano 
983a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
984a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
985a27d9013SAlfredo Cardigliano 		return -ENOMEM;
986a27d9013SAlfredo Cardigliano 	}
987a27d9013SAlfredo Cardigliano 
98827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
98927b942c8SAlfredo Cardigliano 
99027b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
99127b942c8SAlfredo Cardigliano 	if (err) {
99227b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
99327b942c8SAlfredo Cardigliano 		return err;
99427b942c8SAlfredo Cardigliano 	}
99527b942c8SAlfredo Cardigliano 
99627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
99727b942c8SAlfredo Cardigliano 
99801a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
99901a6c311SAlfredo Cardigliano 	if (err) {
100001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
100101a6c311SAlfredo Cardigliano 		return err;
100201a6c311SAlfredo Cardigliano 	}
100301a6c311SAlfredo Cardigliano 
100401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
100501a6c311SAlfredo Cardigliano 
1006924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1007669c8de6SAlfredo Cardigliano 
1008669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1009669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1010669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1011669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1012669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1013669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1014669c8de6SAlfredo Cardigliano 	}
1015669c8de6SAlfredo Cardigliano 
1016669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1017669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1018669c8de6SAlfredo Cardigliano 
1019669c8de6SAlfredo Cardigliano 	return 0;
1020669c8de6SAlfredo Cardigliano }
1021669c8de6SAlfredo Cardigliano 
1022669c8de6SAlfredo Cardigliano void
1023669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1024669c8de6SAlfredo Cardigliano {
102527b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1026be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
102727b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
102827b942c8SAlfredo Cardigliano 	}
102927b942c8SAlfredo Cardigliano 
103001a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1031be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
103201a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
103301a6c311SAlfredo Cardigliano 	}
103401a6c311SAlfredo Cardigliano 
1035a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1036a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1037a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1038a27d9013SAlfredo Cardigliano 	}
1039a27d9013SAlfredo Cardigliano 
1040a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1041a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1042a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1043a27d9013SAlfredo Cardigliano 	}
1044a27d9013SAlfredo Cardigliano 
1045669c8de6SAlfredo Cardigliano 	if (lif->info) {
1046669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1047669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1048669c8de6SAlfredo Cardigliano 	}
1049669c8de6SAlfredo Cardigliano }
1050669c8de6SAlfredo Cardigliano 
1051175e4e7eSAndrew Boyer void
1052175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1053175e4e7eSAndrew Boyer {
1054175e4e7eSAndrew Boyer 	uint32_t i;
1055175e4e7eSAndrew Boyer 
1056175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
10577483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1058175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1059175e4e7eSAndrew Boyer 	}
1060175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
10617483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1062175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1063175e4e7eSAndrew Boyer 	}
1064175e4e7eSAndrew Boyer }
1065175e4e7eSAndrew Boyer 
106622e7171bSAlfredo Cardigliano int
106722e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
106822e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
106922e7171bSAlfredo Cardigliano {
107009f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
107122e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
107222e7171bSAlfredo Cardigliano 		.pending_work = true,
107322e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
107422e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
107522e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
107609f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
107709f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
107822e7171bSAlfredo Cardigliano 		},
107922e7171bSAlfredo Cardigliano 	};
108022e7171bSAlfredo Cardigliano 	unsigned int i;
108109f806e9SAndrew Boyer 	uint16_t tbl_sz =
108209f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
108322e7171bSAlfredo Cardigliano 
108422e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
108522e7171bSAlfredo Cardigliano 
108622e7171bSAlfredo Cardigliano 	lif->rss_types = types;
108722e7171bSAlfredo Cardigliano 
108822e7171bSAlfredo Cardigliano 	if (key)
108922e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
109022e7171bSAlfredo Cardigliano 
109122e7171bSAlfredo Cardigliano 	if (indir)
109209f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
109322e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
109422e7171bSAlfredo Cardigliano 
109522e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
109622e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
109722e7171bSAlfredo Cardigliano 
109822e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
109922e7171bSAlfredo Cardigliano }
110022e7171bSAlfredo Cardigliano 
110122e7171bSAlfredo Cardigliano static int
110222e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
110322e7171bSAlfredo Cardigliano {
110409f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
110522e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
110622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
110922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
111022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
111122e7171bSAlfredo Cardigliano 	};
111222e7171bSAlfredo Cardigliano 	uint32_t i;
111309f806e9SAndrew Boyer 	uint16_t tbl_sz =
111409f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
111522e7171bSAlfredo Cardigliano 
111622e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
111722e7171bSAlfredo Cardigliano 
11183d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
111922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11203d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11213d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11223d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
112322e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
112422e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
112522e7171bSAlfredo Cardigliano 			return -ENOMEM;
112622e7171bSAlfredo Cardigliano 		}
112722e7171bSAlfredo Cardigliano 
112822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
112922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11303d845eddSAndrew Boyer 	}
11313d845eddSAndrew Boyer 
11323d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11333d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
113422e7171bSAlfredo Cardigliano 
113522e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11363d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
113722e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11383d845eddSAndrew Boyer 	}
113922e7171bSAlfredo Cardigliano 
11403d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
114122e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
114222e7171bSAlfredo Cardigliano }
114322e7171bSAlfredo Cardigliano 
114422e7171bSAlfredo Cardigliano static void
114522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
114622e7171bSAlfredo Cardigliano {
114722e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
114822e7171bSAlfredo Cardigliano 		return;
114922e7171bSAlfredo Cardigliano 
115022e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
115122e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
115222e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
115322e7171bSAlfredo Cardigliano 
115422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
115522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
115622e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
115722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
115822e7171bSAlfredo Cardigliano 	}
115922e7171bSAlfredo Cardigliano }
116022e7171bSAlfredo Cardigliano 
1161be39f75cSAndrew Boyer void
1162be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1163be39f75cSAndrew Boyer {
1164be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1165be39f75cSAndrew Boyer }
1166be39f75cSAndrew Boyer 
1167be39f75cSAndrew Boyer void
1168be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1169be39f75cSAndrew Boyer {
1170be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1171be39f75cSAndrew Boyer }
1172be39f75cSAndrew Boyer 
117301a6c311SAlfredo Cardigliano static void
1174be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
117501a6c311SAlfredo Cardigliano {
1176be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
11774c8f8d57SAndrew Boyer }
11784c8f8d57SAndrew Boyer 
11794c8f8d57SAndrew Boyer static void
11804c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
11814c8f8d57SAndrew Boyer {
1182be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
11834c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
11844c8f8d57SAndrew Boyer 
11854c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
11864c8f8d57SAndrew Boyer 		return;
11874c8f8d57SAndrew Boyer 
11884c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
11894c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
11904c8f8d57SAndrew Boyer 
11914c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1192a27d9013SAlfredo Cardigliano }
1193a27d9013SAlfredo Cardigliano 
119401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
119501a6c311SAlfredo Cardigliano int
119601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
119701a6c311SAlfredo Cardigliano 		void *cb_arg)
119801a6c311SAlfredo Cardigliano {
119901a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
120001a6c311SAlfredo Cardigliano 	uint32_t work_done;
120101a6c311SAlfredo Cardigliano 
120201a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
120301a6c311SAlfredo Cardigliano 
120401a6c311SAlfredo Cardigliano 	return work_done;
120501a6c311SAlfredo Cardigliano }
120601a6c311SAlfredo Cardigliano 
120727b942c8SAlfredo Cardigliano static void
120827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
120927b942c8SAlfredo Cardigliano {
121027b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
121127b942c8SAlfredo Cardigliano 	bool link_up;
121227b942c8SAlfredo Cardigliano 
121327b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
121427b942c8SAlfredo Cardigliano 
121527b942c8SAlfredo Cardigliano 	if (!lif->info)
121627b942c8SAlfredo Cardigliano 		return;
121727b942c8SAlfredo Cardigliano 
121827b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
121927b942c8SAlfredo Cardigliano 
122027b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
122127b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
122227b942c8SAlfredo Cardigliano 		return;
122327b942c8SAlfredo Cardigliano 
122427b942c8SAlfredo Cardigliano 	if (link_up) {
122509f806e9SAndrew Boyer 		adapter->link_speed =
122609f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1227be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1228be63459eSAndrew Boyer 			adapter->link_speed);
122927b942c8SAlfredo Cardigliano 	} else {
123027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
123127b942c8SAlfredo Cardigliano 	}
123227b942c8SAlfredo Cardigliano 
123327b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1234be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1235be63459eSAndrew Boyer }
1236be63459eSAndrew Boyer 
1237be63459eSAndrew Boyer static void
1238be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1239be63459eSAndrew Boyer {
1240be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1241be63459eSAndrew Boyer 		return;
1242be63459eSAndrew Boyer 
1243be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1244be63459eSAndrew Boyer 
1245be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1246be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1247be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1248be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1249be63459eSAndrew Boyer 	}
1250be63459eSAndrew Boyer 
1251be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
125227b942c8SAlfredo Cardigliano }
125327b942c8SAlfredo Cardigliano 
125427b942c8SAlfredo Cardigliano static bool
12554ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
125627b942c8SAlfredo Cardigliano {
125727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
125827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
125927b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
126027b942c8SAlfredo Cardigliano 
126127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
126227b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
126327b942c8SAlfredo Cardigliano 
126427b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
126527b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
126627b942c8SAlfredo Cardigliano 		return false;
126727b942c8SAlfredo Cardigliano 
126827b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
126927b942c8SAlfredo Cardigliano 
127027b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
127127b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
127227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1273be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1274be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1275be63459eSAndrew Boyer 			lif->name,
127627b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
127727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
127827b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
127927b942c8SAlfredo Cardigliano 
128027b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
128127b942c8SAlfredo Cardigliano 		break;
1282be63459eSAndrew Boyer 
1283be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1284be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1285be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1286be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1287be63459eSAndrew Boyer 			lif->name,
1288be63459eSAndrew Boyer 			cq_desc->event.eid,
1289be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1290be63459eSAndrew Boyer 			cq_desc->reset.state);
1291be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1292be63459eSAndrew Boyer 		break;
1293be63459eSAndrew Boyer 
129427b942c8SAlfredo Cardigliano 	default:
129527b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
129627b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
129727b942c8SAlfredo Cardigliano 		break;
129827b942c8SAlfredo Cardigliano 	}
129927b942c8SAlfredo Cardigliano 
130027b942c8SAlfredo Cardigliano 	return true;
130127b942c8SAlfredo Cardigliano }
130227b942c8SAlfredo Cardigliano 
130327b942c8SAlfredo Cardigliano int
130427b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
130527b942c8SAlfredo Cardigliano {
130627b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1307be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
130827b942c8SAlfredo Cardigliano 	uint32_t work_done;
130927b942c8SAlfredo Cardigliano 
1310be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
131127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
131227b942c8SAlfredo Cardigliano 		return -1;
131327b942c8SAlfredo Cardigliano 	}
131427b942c8SAlfredo Cardigliano 
1315be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
131627b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
131727b942c8SAlfredo Cardigliano 
1318be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1319be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
132027b942c8SAlfredo Cardigliano 
132127b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
132227b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
132327b942c8SAlfredo Cardigliano 
1324be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
132527b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
132627b942c8SAlfredo Cardigliano 
1327be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
132827b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
132927b942c8SAlfredo Cardigliano 
133027b942c8SAlfredo Cardigliano 	return 0;
133127b942c8SAlfredo Cardigliano }
133227b942c8SAlfredo Cardigliano 
133301a6c311SAlfredo Cardigliano static int
133401a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
133501a6c311SAlfredo Cardigliano {
133601a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1337be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1338be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
133901a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
134001a6c311SAlfredo Cardigliano 	int err;
134101a6c311SAlfredo Cardigliano 
1342be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
134301a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
134401a6c311SAlfredo Cardigliano 	if (err)
134501a6c311SAlfredo Cardigliano 		return err;
134601a6c311SAlfredo Cardigliano 
134701a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
134801a6c311SAlfredo Cardigliano 
134901a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
135009f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
135101a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
135201a6c311SAlfredo Cardigliano 
135301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
135401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
135501a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
135601a6c311SAlfredo Cardigliano 
1357be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
135801a6c311SAlfredo Cardigliano 
135901a6c311SAlfredo Cardigliano 	return 0;
136001a6c311SAlfredo Cardigliano }
136101a6c311SAlfredo Cardigliano 
136227b942c8SAlfredo Cardigliano static int
136327b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
136427b942c8SAlfredo Cardigliano {
136527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1366be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1367be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
136827b942c8SAlfredo Cardigliano 	int err;
136927b942c8SAlfredo Cardigliano 
137027b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
137127b942c8SAlfredo Cardigliano 		.pending_work = true,
137227b942c8SAlfredo Cardigliano 		.cmd.q_init = {
137327b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
137427b942c8SAlfredo Cardigliano 			.type = q->type,
1375c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
137609f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1377be39f75cSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(nqcq->intr.index),
137809f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ |
137909f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
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 
138509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
138609f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
138727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
138827b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13894ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
139027b942c8SAlfredo Cardigliano 
139127b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
139227b942c8SAlfredo Cardigliano 	if (err)
139327b942c8SAlfredo Cardigliano 		return err;
139427b942c8SAlfredo Cardigliano 
139527b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
139609f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
139727b942c8SAlfredo Cardigliano 	q->db = NULL;
139827b942c8SAlfredo Cardigliano 
139927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
140027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
140127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
140227b942c8SAlfredo Cardigliano 
1403be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
140427b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
140527b942c8SAlfredo Cardigliano 
1406be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
140727b942c8SAlfredo Cardigliano 
140827b942c8SAlfredo Cardigliano 	return 0;
140927b942c8SAlfredo Cardigliano }
141027b942c8SAlfredo Cardigliano 
1411669c8de6SAlfredo Cardigliano int
1412598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1413598f6726SAlfredo Cardigliano {
1414598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1415598f6726SAlfredo Cardigliano 		.pending_work = true,
1416598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1417598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1418598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
141909f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1420598f6726SAlfredo Cardigliano 		},
1421598f6726SAlfredo Cardigliano 	};
1422598f6726SAlfredo Cardigliano 	int err;
1423598f6726SAlfredo Cardigliano 
1424598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1425598f6726SAlfredo Cardigliano 	if (err)
1426598f6726SAlfredo Cardigliano 		return err;
1427598f6726SAlfredo Cardigliano 
142809f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1429598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1430598f6726SAlfredo Cardigliano 
1431598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1432598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1433598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1434598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1435598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1436598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1437598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1438598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1439598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1440598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1441598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1442598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1443598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1444598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1445598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1446598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1447598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1448598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1449598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1450598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1451598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1452598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1453598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1454598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1455598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1456598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1457598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1458598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1459598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1460598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1461598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1462598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1463598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1464598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1465598f6726SAlfredo Cardigliano 
1466598f6726SAlfredo Cardigliano 	return 0;
1467598f6726SAlfredo Cardigliano }
1468598f6726SAlfredo Cardigliano 
1469a27d9013SAlfredo Cardigliano int
1470be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1471a27d9013SAlfredo Cardigliano {
1472be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1473a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1474a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1475a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1476a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1477a27d9013SAlfredo Cardigliano 		.pending_work = true,
1478a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1479a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1480a27d9013SAlfredo Cardigliano 			.type = q->type,
1481c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
148209f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
148309f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
148409f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
148509f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1486a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
148709f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
148809f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
148909f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1490a27d9013SAlfredo Cardigliano 		},
1491a27d9013SAlfredo Cardigliano 	};
1492a27d9013SAlfredo Cardigliano 	int err;
1493a27d9013SAlfredo Cardigliano 
149409f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
149509f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1496a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1497a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14984ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1499a27d9013SAlfredo Cardigliano 
1500be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1501a27d9013SAlfredo Cardigliano 	if (err)
1502a27d9013SAlfredo Cardigliano 		return err;
1503a27d9013SAlfredo Cardigliano 
1504a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
150509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1506a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1507a27d9013SAlfredo Cardigliano 
1508a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1509a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1510a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1511a27d9013SAlfredo Cardigliano 
1512be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1513a27d9013SAlfredo Cardigliano 
1514a27d9013SAlfredo Cardigliano 	return 0;
1515a27d9013SAlfredo Cardigliano }
1516a27d9013SAlfredo Cardigliano 
1517a27d9013SAlfredo Cardigliano int
1518be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1519a27d9013SAlfredo Cardigliano {
1520be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1521a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1522a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1523a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1524a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1525a27d9013SAlfredo Cardigliano 		.pending_work = true,
1526a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1527a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1528a27d9013SAlfredo Cardigliano 			.type = q->type,
1529c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
153009f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
153109f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
153209f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
153309f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1534a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
153509f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
153609f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
153709f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1538a27d9013SAlfredo Cardigliano 		},
1539a27d9013SAlfredo Cardigliano 	};
1540a27d9013SAlfredo Cardigliano 	int err;
1541a27d9013SAlfredo Cardigliano 
154209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
154309f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1544a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1545a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15464ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1547a27d9013SAlfredo Cardigliano 
1548be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1549a27d9013SAlfredo Cardigliano 	if (err)
1550a27d9013SAlfredo Cardigliano 		return err;
1551a27d9013SAlfredo Cardigliano 
1552a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
155309f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1554a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1555a27d9013SAlfredo Cardigliano 
1556be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1557a27d9013SAlfredo Cardigliano 
1558a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1559a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1560a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1561a27d9013SAlfredo Cardigliano 
1562a27d9013SAlfredo Cardigliano 	return 0;
1563a27d9013SAlfredo Cardigliano }
1564a27d9013SAlfredo Cardigliano 
1565598f6726SAlfredo Cardigliano static int
1566598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1567598f6726SAlfredo Cardigliano {
1568598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1569598f6726SAlfredo Cardigliano 		.pending_work = true,
1570598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1571598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1572598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1573598f6726SAlfredo Cardigliano 		},
1574598f6726SAlfredo Cardigliano 	};
1575598f6726SAlfredo Cardigliano 	int err;
1576598f6726SAlfredo Cardigliano 
1577598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1578598f6726SAlfredo Cardigliano 
1579598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1580598f6726SAlfredo Cardigliano 	if (err)
1581598f6726SAlfredo Cardigliano 		return err;
1582598f6726SAlfredo Cardigliano 
1583598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1584598f6726SAlfredo Cardigliano 
1585598f6726SAlfredo Cardigliano 	return 0;
1586598f6726SAlfredo Cardigliano }
1587598f6726SAlfredo Cardigliano 
1588598f6726SAlfredo Cardigliano static void
1589598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1590598f6726SAlfredo Cardigliano {
1591598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1592598f6726SAlfredo Cardigliano 		.pending_work = true,
1593598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1594598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1595598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1596598f6726SAlfredo Cardigliano 		},
1597598f6726SAlfredo Cardigliano 	};
1598598f6726SAlfredo Cardigliano 
15994ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
16004ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1601598f6726SAlfredo Cardigliano 
1602598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1603598f6726SAlfredo Cardigliano }
1604598f6726SAlfredo Cardigliano 
1605598f6726SAlfredo Cardigliano int
1606669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1607669c8de6SAlfredo Cardigliano {
1608669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1609656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
1610669c8de6SAlfredo Cardigliano 	int err;
1611669c8de6SAlfredo Cardigliano 
16123cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
16133cdfd905SAlfredo Cardigliano 
161400b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1615669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1616669c8de6SAlfredo Cardigliano 	if (err)
1617669c8de6SAlfredo Cardigliano 		return err;
1618669c8de6SAlfredo Cardigliano 
1619656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1620656bfc9aSAndrew Boyer 
162109f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1622669c8de6SAlfredo Cardigliano 
162301a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
162401a6c311SAlfredo Cardigliano 	if (err)
162501a6c311SAlfredo Cardigliano 		return err;
162601a6c311SAlfredo Cardigliano 
162727b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
162827b942c8SAlfredo Cardigliano 	if (err)
162927b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
163027b942c8SAlfredo Cardigliano 
163118a44465SAndrew Boyer 	/*
163218a44465SAndrew Boyer 	 * Configure initial feature set
163318a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
163418a44465SAndrew Boyer 	 */
163518a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1636598f6726SAlfredo Cardigliano 
1637598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1638598f6726SAlfredo Cardigliano 	if (err)
1639598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1640598f6726SAlfredo Cardigliano 
164154fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1642598f6726SAlfredo Cardigliano 	if (err)
1643598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1644598f6726SAlfredo Cardigliano 
164554fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
164654fe083fSAlfredo Cardigliano 	if (err)
164754fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
164854fe083fSAlfredo Cardigliano 
1649598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1650598f6726SAlfredo Cardigliano 
1651669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1652669c8de6SAlfredo Cardigliano 
1653669c8de6SAlfredo Cardigliano 	return 0;
165427b942c8SAlfredo Cardigliano 
165554fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
165654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
165754fe083fSAlfredo Cardigliano 
1658598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
16594c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1660598f6726SAlfredo Cardigliano 
166127b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1662be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
166327b942c8SAlfredo Cardigliano 
166427b942c8SAlfredo Cardigliano 	return err;
1665669c8de6SAlfredo Cardigliano }
1666669c8de6SAlfredo Cardigliano 
1667669c8de6SAlfredo Cardigliano void
1668669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1669669c8de6SAlfredo Cardigliano {
1670669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1671669c8de6SAlfredo Cardigliano 		return;
1672669c8de6SAlfredo Cardigliano 
167354fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
167422e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
16754c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1676be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
167701a6c311SAlfredo Cardigliano 
1678669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1679669c8de6SAlfredo Cardigliano }
1680669c8de6SAlfredo Cardigliano 
168118a44465SAndrew Boyer void
168218a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
168318a44465SAndrew Boyer {
168418a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
168518a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
168618a44465SAndrew Boyer 
168718a44465SAndrew Boyer 	/*
168818a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1689295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
169018a44465SAndrew Boyer 	 */
1691295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
169218a44465SAndrew Boyer 
1693295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1694295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
169518a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
169618a44465SAndrew Boyer 		else
169718a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
169818a44465SAndrew Boyer 	}
169918a44465SAndrew Boyer }
170018a44465SAndrew Boyer 
170118a44465SAndrew Boyer void
1702598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1703598f6726SAlfredo Cardigliano {
170418a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
170518a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
170622e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
170709f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
170822e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
170909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
171022e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
171109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
171222e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
171322e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
171422e7171bSAlfredo Cardigliano 
1715598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1716598f6726SAlfredo Cardigliano 
171722e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
171822e7171bSAlfredo Cardigliano 		lif->port_id);
171922e7171bSAlfredo Cardigliano 
172022e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
172122e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
172222e7171bSAlfredo Cardigliano 
172322e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
172422e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
172522e7171bSAlfredo Cardigliano 
172622e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
172722e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1728a27d9013SAlfredo Cardigliano 
172918a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
173018a44465SAndrew Boyer 
173118a44465SAndrew Boyer 	/*
173218a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
173318a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1734295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
173518a44465SAndrew Boyer 	 */
173618a44465SAndrew Boyer 
173718a44465SAndrew Boyer 	/* RX per-port */
173818a44465SAndrew Boyer 
1739295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1740295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1741295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
174218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
174318a44465SAndrew Boyer 	else
174418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
174518a44465SAndrew Boyer 
1746295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
174718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
174818a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
174918a44465SAndrew Boyer 	} else {
175018a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
175118a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
175218a44465SAndrew Boyer 	}
175318a44465SAndrew Boyer 
175418a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1755295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
175618a44465SAndrew Boyer 
175718a44465SAndrew Boyer 	/* TX per-port */
175818a44465SAndrew Boyer 
1759295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1760295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1761295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1762295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1763295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
176418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
176518a44465SAndrew Boyer 	else
176618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
176718a44465SAndrew Boyer 
1768295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
176918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
177018a44465SAndrew Boyer 	else
177118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
177218a44465SAndrew Boyer 
1773295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
177418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
177518a44465SAndrew Boyer 	else
177618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
177718a44465SAndrew Boyer 
1778295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
177918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
178018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
178118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
178218a44465SAndrew Boyer 	} else {
178318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
178418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
178518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
178618a44465SAndrew Boyer 	}
1787598f6726SAlfredo Cardigliano }
1788598f6726SAlfredo Cardigliano 
1789598f6726SAlfredo Cardigliano int
1790598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1791598f6726SAlfredo Cardigliano {
17920578335aSAndrew Boyer 	uint32_t rx_mode;
1793a27d9013SAlfredo Cardigliano 	uint32_t i;
1794a27d9013SAlfredo Cardigliano 	int err;
1795598f6726SAlfredo Cardigliano 
179622e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
179722e7171bSAlfredo Cardigliano 	if (err)
179822e7171bSAlfredo Cardigliano 		return err;
179922e7171bSAlfredo Cardigliano 
18000578335aSAndrew Boyer 	if (!lif->rx_mode) {
18010578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
18020578335aSAndrew Boyer 			lif->name);
1803598f6726SAlfredo Cardigliano 
18040578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1805598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1806598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1807598f6726SAlfredo Cardigliano 
1808598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18090578335aSAndrew Boyer 	}
1810598f6726SAlfredo Cardigliano 
1811a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1812a27d9013SAlfredo Cardigliano 		"on port %u",
1813a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1814a27d9013SAlfredo Cardigliano 
1815a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1816be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
181702eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1818a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1819a27d9013SAlfredo Cardigliano 
1820a27d9013SAlfredo Cardigliano 			if (err)
1821a27d9013SAlfredo Cardigliano 				return err;
1822a27d9013SAlfredo Cardigliano 		}
1823a27d9013SAlfredo Cardigliano 	}
1824a27d9013SAlfredo Cardigliano 
1825a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1826be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
182702eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1828a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1829a27d9013SAlfredo Cardigliano 
1830a27d9013SAlfredo Cardigliano 			if (err)
1831a27d9013SAlfredo Cardigliano 				return err;
1832a27d9013SAlfredo Cardigliano 		}
1833a27d9013SAlfredo Cardigliano 	}
1834a27d9013SAlfredo Cardigliano 
1835598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1836be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1837be63459eSAndrew Boyer 
1838be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1839598f6726SAlfredo Cardigliano 
1840598f6726SAlfredo Cardigliano 	return 0;
1841598f6726SAlfredo Cardigliano }
1842598f6726SAlfredo Cardigliano 
1843598f6726SAlfredo Cardigliano int
1844669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1845669c8de6SAlfredo Cardigliano {
1846669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1847669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
184809f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
184976276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
185076276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
185176276d71SAndrew Boyer 	uint32_t i, nwords;
1852669c8de6SAlfredo Cardigliano 	int err;
1853669c8de6SAlfredo Cardigliano 
1854669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1855669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1856669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1857669c8de6SAlfredo Cardigliano 	if (err)
1858669c8de6SAlfredo Cardigliano 		return (err);
1859669c8de6SAlfredo Cardigliano 
1860669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1861669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1862669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1863669c8de6SAlfredo Cardigliano 
1864669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
186509f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1866669c8de6SAlfredo Cardigliano 
1867669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
186809f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1869669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
187009f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1871669c8de6SAlfredo Cardigliano 
1872669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
187309f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1874669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
187509f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1876669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
187709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1878669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
187909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1880669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
188109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1882669c8de6SAlfredo Cardigliano 
1883669c8de6SAlfredo Cardigliano 	return 0;
1884669c8de6SAlfredo Cardigliano }
1885669c8de6SAlfredo Cardigliano 
1886669c8de6SAlfredo Cardigliano int
1887669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1888669c8de6SAlfredo Cardigliano {
1889669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
189009f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
189109f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1892669c8de6SAlfredo Cardigliano 
1893669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
189409f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1895669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
189609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1897669c8de6SAlfredo Cardigliano 
189800b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1899669c8de6SAlfredo Cardigliano 
1900669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
19014ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
19024ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1903669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1904669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1905669c8de6SAlfredo Cardigliano 	}
1906669c8de6SAlfredo Cardigliano 
1907669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1908669c8de6SAlfredo Cardigliano 
1909669c8de6SAlfredo Cardigliano 	return 0;
1910669c8de6SAlfredo Cardigliano }
1911