xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision b4beb84af9f15b4d78d55f6b3504fa835b420166)
176668754SAndrew Boyer /* SPDX-License-Identifier: BSD-3-Clause
2a5205992SAndrew Boyer  * Copyright 2018-2022 Advanced Micro Devices, Inc.
3669c8de6SAlfredo Cardigliano  */
4669c8de6SAlfredo Cardigliano 
5669c8de6SAlfredo Cardigliano #include <rte_malloc.h>
6df96fd0dSBruce Richardson #include <ethdev_driver.h>
7669c8de6SAlfredo Cardigliano 
8669c8de6SAlfredo Cardigliano #include "ionic.h"
9669c8de6SAlfredo Cardigliano #include "ionic_logs.h"
10669c8de6SAlfredo Cardigliano #include "ionic_lif.h"
11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h"
1254fe083fSAlfredo Cardigliano #include "ionic_rx_filter.h"
13a27d9013SAlfredo Cardigliano #include "ionic_rxtx.h"
14669c8de6SAlfredo Cardigliano 
15c5d15850SAndrew Boyer /* queuetype support level */
16c5d15850SAndrew Boyer static const uint8_t ionic_qtype_vers[IONIC_QTYPE_MAX] = {
17c5d15850SAndrew Boyer 	[IONIC_QTYPE_ADMINQ]  = 0,   /* 0 = Base version with CQ support */
18c5d15850SAndrew Boyer 	[IONIC_QTYPE_NOTIFYQ] = 0,   /* 0 = Base version */
19c5d15850SAndrew Boyer 	[IONIC_QTYPE_RXQ]     = 2,   /* 0 = Base version with CQ+SG support
20c5d15850SAndrew Boyer 				      * 1 =       ... with EQ
21c5d15850SAndrew Boyer 				      * 2 =       ... with CMB
22c5d15850SAndrew Boyer 				      */
23c5d15850SAndrew Boyer 	[IONIC_QTYPE_TXQ]     = 3,   /* 0 = Base version with CQ+SG support
24c5d15850SAndrew Boyer 				      * 1 =   ... with Tx SG version 1
25c5d15850SAndrew Boyer 				      * 2 =       ... with EQ
26c5d15850SAndrew Boyer 				      * 3 =       ... with CMB
27c5d15850SAndrew Boyer 				      */
28c5d15850SAndrew Boyer };
29c5d15850SAndrew Boyer 
30598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
31598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
32598f6726SAlfredo Cardigliano 
33e7222f94SAndrew Boyer static int
3401a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
3501a6c311SAlfredo Cardigliano {
3601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
374ad56b7aSAndrew Boyer 	struct ionic_lif *lif = qcq->lif;
3801a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
3901a6c311SAlfredo Cardigliano 		.pending_work = true,
4001a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4101a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4201a6c311SAlfredo Cardigliano 			.type = q->type,
4309f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4401a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
4501a6c311SAlfredo Cardigliano 		},
4601a6c311SAlfredo Cardigliano 	};
4701a6c311SAlfredo Cardigliano 
4801a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4901a6c311SAlfredo Cardigliano }
5001a6c311SAlfredo Cardigliano 
51be63459eSAndrew Boyer void
52be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
53598f6726SAlfredo Cardigliano {
54a0a99f21SAndrew Boyer 	uint32_t i;
55a0a99f21SAndrew Boyer 
56be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
57598f6726SAlfredo Cardigliano 
58be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
59a0a99f21SAndrew Boyer 
60a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
61be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
62a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
63a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
64a0a99f21SAndrew Boyer 	}
65a0a99f21SAndrew Boyer 
66a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
67be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
68a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
69a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
70a0a99f21SAndrew Boyer 	}
71598f6726SAlfredo Cardigliano }
72598f6726SAlfredo Cardigliano 
73598f6726SAlfredo Cardigliano void
74598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
75598f6726SAlfredo Cardigliano {
76598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
7775f96902SAndrew Boyer 	int err;
78598f6726SAlfredo Cardigliano 
79598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
80598f6726SAlfredo Cardigliano 
8100b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
8275f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
8375f96902SAndrew Boyer 	if (err)
844ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
85598f6726SAlfredo Cardigliano }
86598f6726SAlfredo Cardigliano 
873cdfd905SAlfredo Cardigliano static void
883cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
893cdfd905SAlfredo Cardigliano {
903cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
913cdfd905SAlfredo Cardigliano 	uint32_t i;
923cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
933cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
943cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
953cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
963cdfd905SAlfredo Cardigliano 
973cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
983cdfd905SAlfredo Cardigliano 
993cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1003cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1013cdfd905SAlfredo Cardigliano 			lif->port_id);
1023cdfd905SAlfredo Cardigliano 		return;
1033cdfd905SAlfredo Cardigliano 	}
1043cdfd905SAlfredo Cardigliano 
1053cdfd905SAlfredo Cardigliano 	/* RX */
1063cdfd905SAlfredo Cardigliano 
1073cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1083cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1093cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1103cdfd905SAlfredo Cardigliano 
1113cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1123cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1133cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1143cdfd905SAlfredo Cardigliano 
1153cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
116be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
11726cc5dc2SAndrew Boyer 		stats->ierrors +=
1183cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1193cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1203cdfd905SAlfredo Cardigliano 	}
1213cdfd905SAlfredo Cardigliano 
1223cdfd905SAlfredo Cardigliano 	stats->imissed +=
1233cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1243cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1253cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1263cdfd905SAlfredo Cardigliano 
12726cc5dc2SAndrew Boyer 	stats->ierrors +=
1283cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1293cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1303cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1313cdfd905SAlfredo Cardigliano 
1323cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
133be39f75cSAndrew Boyer 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats;
1343cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1353cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1363cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1373cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1383cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1393cdfd905SAlfredo Cardigliano 	}
1403cdfd905SAlfredo Cardigliano 
1413cdfd905SAlfredo Cardigliano 	/* TX */
1423cdfd905SAlfredo Cardigliano 
1433cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1443cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1453cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1463cdfd905SAlfredo Cardigliano 
1473cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1483cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1493cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1503cdfd905SAlfredo Cardigliano 
1513cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
152be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1533cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1543cdfd905SAlfredo Cardigliano 	}
1553cdfd905SAlfredo Cardigliano 
1563cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1573cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1583cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1593cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1603cdfd905SAlfredo Cardigliano 
1613cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1623cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1633cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1643cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1653cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1663cdfd905SAlfredo Cardigliano 
1673cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
168be39f75cSAndrew Boyer 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats;
1693cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1703cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1713cdfd905SAlfredo Cardigliano 	}
1723cdfd905SAlfredo Cardigliano }
1733cdfd905SAlfredo Cardigliano 
1743cdfd905SAlfredo Cardigliano void
1753cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1763cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1773cdfd905SAlfredo Cardigliano {
1783cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1793cdfd905SAlfredo Cardigliano 
1803cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1813cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1823cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1833cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1843cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1853cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1863cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1873cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1883cdfd905SAlfredo Cardigliano }
1893cdfd905SAlfredo Cardigliano 
1903cdfd905SAlfredo Cardigliano void
1913cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
1923cdfd905SAlfredo Cardigliano {
1933cdfd905SAlfredo Cardigliano 	uint32_t i;
1943cdfd905SAlfredo Cardigliano 
1953cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
196be39f75cSAndrew Boyer 		memset(&lif->rxqcqs[i]->stats, 0,
1973cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
198be39f75cSAndrew Boyer 		memset(&lif->txqcqs[i]->stats, 0,
1993cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2003cdfd905SAlfredo Cardigliano 	}
2013cdfd905SAlfredo Cardigliano 
2023cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2033cdfd905SAlfredo Cardigliano }
2043cdfd905SAlfredo Cardigliano 
2053cdfd905SAlfredo Cardigliano void
2063cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2073cdfd905SAlfredo Cardigliano {
2083cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2093cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2103cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2113cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2123cdfd905SAlfredo Cardigliano 
2133cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2143cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2153cdfd905SAlfredo Cardigliano }
2163cdfd905SAlfredo Cardigliano 
2173cdfd905SAlfredo Cardigliano void
2183cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2193cdfd905SAlfredo Cardigliano {
2203cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2213cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2223cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2233cdfd905SAlfredo Cardigliano 
2243cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2253cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2263cdfd905SAlfredo Cardigliano }
2273cdfd905SAlfredo Cardigliano 
228598f6726SAlfredo Cardigliano static int
22954fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
230598f6726SAlfredo Cardigliano {
23154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
23254fe083fSAlfredo Cardigliano 		.pending_work = true,
23354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
23454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
23509f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
23654fe083fSAlfredo Cardigliano 		},
23754fe083fSAlfredo Cardigliano 	};
23854fe083fSAlfredo Cardigliano 	int err;
23954fe083fSAlfredo Cardigliano 
24054fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
24154fe083fSAlfredo Cardigliano 
24254fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
24354fe083fSAlfredo Cardigliano 	if (err)
24454fe083fSAlfredo Cardigliano 		return err;
24554fe083fSAlfredo Cardigliano 
24654fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
24709f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
24854fe083fSAlfredo Cardigliano 
24954fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25054fe083fSAlfredo Cardigliano }
25154fe083fSAlfredo Cardigliano 
25254fe083fSAlfredo Cardigliano static int
25354fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
25454fe083fSAlfredo Cardigliano {
25554fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25654fe083fSAlfredo Cardigliano 		.pending_work = true,
25754fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
25854fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
25954fe083fSAlfredo Cardigliano 		},
26054fe083fSAlfredo Cardigliano 	};
26154fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
26254fe083fSAlfredo Cardigliano 	int err;
26354fe083fSAlfredo Cardigliano 
26454fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
26554fe083fSAlfredo Cardigliano 
26654fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
26754fe083fSAlfredo Cardigliano 
26854fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
26954fe083fSAlfredo Cardigliano 	if (!f) {
27054fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
27154fe083fSAlfredo Cardigliano 		return -ENOENT;
27254fe083fSAlfredo Cardigliano 	}
27354fe083fSAlfredo Cardigliano 
27409f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
27554fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
27654fe083fSAlfredo Cardigliano 
27754fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
27854fe083fSAlfredo Cardigliano 
27954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28054fe083fSAlfredo Cardigliano 	if (err)
28154fe083fSAlfredo Cardigliano 		return err;
28254fe083fSAlfredo Cardigliano 
28354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
28409f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
285598f6726SAlfredo Cardigliano 
286598f6726SAlfredo Cardigliano 	return 0;
287598f6726SAlfredo Cardigliano }
288598f6726SAlfredo Cardigliano 
28954fe083fSAlfredo Cardigliano int
29054fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
29154fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
29254fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
293598f6726SAlfredo Cardigliano {
29454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
29554fe083fSAlfredo Cardigliano 
29654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
29754fe083fSAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
29954fe083fSAlfredo Cardigliano }
30054fe083fSAlfredo Cardigliano 
30154fe083fSAlfredo Cardigliano void
30275f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
30354fe083fSAlfredo Cardigliano {
30454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30554fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
30675f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
30754fe083fSAlfredo Cardigliano 
30854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30954fe083fSAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
31154fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
31254fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
31354fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
31454fe083fSAlfredo Cardigliano 		return;
31554fe083fSAlfredo Cardigliano 	}
31654fe083fSAlfredo Cardigliano 
31775f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
31875f96902SAndrew Boyer 
31975f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32054fe083fSAlfredo Cardigliano 		return;
32154fe083fSAlfredo Cardigliano 
32275f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
32354fe083fSAlfredo Cardigliano }
32454fe083fSAlfredo Cardigliano 
32554fe083fSAlfredo Cardigliano int
32654fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
32754fe083fSAlfredo Cardigliano {
32854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32954fe083fSAlfredo Cardigliano 
33054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
33354fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
33454fe083fSAlfredo Cardigliano 		return -1;
33554fe083fSAlfredo Cardigliano 	}
33654fe083fSAlfredo Cardigliano 
33754fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
33854fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
33954fe083fSAlfredo Cardigliano 			lif->mac_addr);
34054fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
34154fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
34254fe083fSAlfredo Cardigliano 	}
34354fe083fSAlfredo Cardigliano 
34454fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
34754fe083fSAlfredo Cardigliano 
34854fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
34954fe083fSAlfredo Cardigliano }
35054fe083fSAlfredo Cardigliano 
35154fe083fSAlfredo Cardigliano static int
35254fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
35354fe083fSAlfredo Cardigliano {
35454fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
35554fe083fSAlfredo Cardigliano 		.pending_work = true,
35654fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
35754fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
35809f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
35909f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
36054fe083fSAlfredo Cardigliano 		},
36154fe083fSAlfredo Cardigliano 	};
36254fe083fSAlfredo Cardigliano 	int err;
36354fe083fSAlfredo Cardigliano 
36454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
36554fe083fSAlfredo Cardigliano 	if (err)
36654fe083fSAlfredo Cardigliano 		return err;
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
36909f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
37054fe083fSAlfredo Cardigliano 
37154fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
37254fe083fSAlfredo Cardigliano }
37354fe083fSAlfredo Cardigliano 
37454fe083fSAlfredo Cardigliano static int
37554fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
37654fe083fSAlfredo Cardigliano {
37754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37854fe083fSAlfredo Cardigliano 		.pending_work = true,
37954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
38154fe083fSAlfredo Cardigliano 		},
38254fe083fSAlfredo Cardigliano 	};
38354fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
38454fe083fSAlfredo Cardigliano 	int err;
38554fe083fSAlfredo Cardigliano 
38654fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
38754fe083fSAlfredo Cardigliano 
38854fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
39154fe083fSAlfredo Cardigliano 	if (!f) {
39254fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
39354fe083fSAlfredo Cardigliano 		return -ENOENT;
39454fe083fSAlfredo Cardigliano 	}
39554fe083fSAlfredo Cardigliano 
39609f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
39754fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
39854fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
39954fe083fSAlfredo Cardigliano 
40054fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
40154fe083fSAlfredo Cardigliano 	if (err)
40254fe083fSAlfredo Cardigliano 		return err;
40354fe083fSAlfredo Cardigliano 
40454fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
40509f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
406598f6726SAlfredo Cardigliano 
407598f6726SAlfredo Cardigliano 	return 0;
408598f6726SAlfredo Cardigliano }
409598f6726SAlfredo Cardigliano 
41054fe083fSAlfredo Cardigliano int
41154fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
41254fe083fSAlfredo Cardigliano 		int on)
41354fe083fSAlfredo Cardigliano {
41454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
41554fe083fSAlfredo Cardigliano 	int err;
41654fe083fSAlfredo Cardigliano 
41754fe083fSAlfredo Cardigliano 	if (on)
41854fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
41954fe083fSAlfredo Cardigliano 	else
42054fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
42154fe083fSAlfredo Cardigliano 
42254fe083fSAlfredo Cardigliano 	return err;
42354fe083fSAlfredo Cardigliano }
42454fe083fSAlfredo Cardigliano 
425598f6726SAlfredo Cardigliano static void
426598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
427598f6726SAlfredo Cardigliano {
428598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
429598f6726SAlfredo Cardigliano 		.pending_work = true,
430598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
431598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
43209f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
433598f6726SAlfredo Cardigliano 		},
434598f6726SAlfredo Cardigliano 	};
435598f6726SAlfredo Cardigliano 	int err;
436598f6726SAlfredo Cardigliano 
437598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
438598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
439598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
440598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
441598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
442598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
443598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
444598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
445598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
446598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
447598f6726SAlfredo Cardigliano 
448598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
449598f6726SAlfredo Cardigliano 	if (err)
450598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
451598f6726SAlfredo Cardigliano }
452598f6726SAlfredo Cardigliano 
453598f6726SAlfredo Cardigliano static void
454598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
455598f6726SAlfredo Cardigliano {
456598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
457598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
458598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
459598f6726SAlfredo Cardigliano 	}
460598f6726SAlfredo Cardigliano }
461598f6726SAlfredo Cardigliano 
46254fe083fSAlfredo Cardigliano int
46354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
46454fe083fSAlfredo Cardigliano {
46554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
46654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
46754fe083fSAlfredo Cardigliano 
46854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
46954fe083fSAlfredo Cardigliano 
47054fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
47154fe083fSAlfredo Cardigliano 
47254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
47354fe083fSAlfredo Cardigliano 
47454fe083fSAlfredo Cardigliano 	return 0;
47554fe083fSAlfredo Cardigliano }
47654fe083fSAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano int
47854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
47954fe083fSAlfredo Cardigliano {
48054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48254fe083fSAlfredo Cardigliano 
48354fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
48454fe083fSAlfredo Cardigliano 
48554fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48654fe083fSAlfredo Cardigliano 
48754fe083fSAlfredo Cardigliano 	return 0;
48854fe083fSAlfredo Cardigliano }
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano int
49154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
49254fe083fSAlfredo Cardigliano {
49354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49454fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49954fe083fSAlfredo Cardigliano 
50054fe083fSAlfredo Cardigliano 	return 0;
50154fe083fSAlfredo Cardigliano }
50254fe083fSAlfredo Cardigliano 
50354fe083fSAlfredo Cardigliano int
50454fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
50554fe083fSAlfredo Cardigliano {
50654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50754fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51254fe083fSAlfredo Cardigliano 
51354fe083fSAlfredo Cardigliano 	return 0;
51454fe083fSAlfredo Cardigliano }
515598f6726SAlfredo Cardigliano 
516598f6726SAlfredo Cardigliano int
517b671e69aSAndrew Boyer ionic_lif_change_mtu(struct ionic_lif *lif, uint32_t new_mtu)
518598f6726SAlfredo Cardigliano {
519598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
520598f6726SAlfredo Cardigliano 		.pending_work = true,
521598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
522598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
523598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
52409f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
525598f6726SAlfredo Cardigliano 		},
526598f6726SAlfredo Cardigliano 	};
527598f6726SAlfredo Cardigliano 
528b671e69aSAndrew Boyer 	return ionic_adminq_post_wait(lif, &ctx);
529598f6726SAlfredo Cardigliano }
530598f6726SAlfredo Cardigliano 
531598f6726SAlfredo Cardigliano int
53201a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
53301a6c311SAlfredo Cardigliano {
53401a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
53501a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
53601a6c311SAlfredo Cardigliano 	unsigned long index;
53701a6c311SAlfredo Cardigliano 
53801a6c311SAlfredo Cardigliano 	/*
53901a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
54001a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5414ae96cb8SAndrew Boyer 	 * which has index = 0)
54201a6c311SAlfredo Cardigliano 	 */
54301a6c311SAlfredo Cardigliano 
54401a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
54501a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
54601a6c311SAlfredo Cardigliano 			break;
54701a6c311SAlfredo Cardigliano 
54801a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
54901a6c311SAlfredo Cardigliano 		return -ENOSPC;
55001a6c311SAlfredo Cardigliano 
55101a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
55201a6c311SAlfredo Cardigliano 
55301a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
55401a6c311SAlfredo Cardigliano 
55501a6c311SAlfredo Cardigliano 	return 0;
55601a6c311SAlfredo Cardigliano }
55701a6c311SAlfredo Cardigliano 
55801a6c311SAlfredo Cardigliano static int
5594ad56b7aSAndrew Boyer ionic_qcq_alloc(struct ionic_lif *lif,
5604ad56b7aSAndrew Boyer 		uint8_t type,
561be39f75cSAndrew Boyer 		size_t struct_size,
5628ec5ad7fSAndrew Boyer 		uint32_t socket_id,
56301a6c311SAlfredo Cardigliano 		uint32_t index,
5644ad56b7aSAndrew Boyer 		const char *type_name,
5654ad56b7aSAndrew Boyer 		uint16_t flags,
5664ad56b7aSAndrew Boyer 		uint16_t num_descs,
567d5850081SAndrew Boyer 		uint16_t num_segs,
5684ad56b7aSAndrew Boyer 		uint16_t desc_size,
5694ad56b7aSAndrew Boyer 		uint16_t cq_desc_size,
5704ad56b7aSAndrew Boyer 		uint16_t sg_desc_size,
5711abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
57201a6c311SAlfredo Cardigliano {
57301a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
57401a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
57501a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
57601a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
57701a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
57801a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
57901a6c311SAlfredo Cardigliano 	int err;
58001a6c311SAlfredo Cardigliano 
58101a6c311SAlfredo Cardigliano 	*qcq = NULL;
58201a6c311SAlfredo Cardigliano 
58301a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
58401a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
58501a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
58601a6c311SAlfredo Cardigliano 
587924e6b76SThomas Monjalon 	total_size = RTE_ALIGN(q_size, rte_mem_page_size()) +
588924e6b76SThomas Monjalon 			RTE_ALIGN(cq_size, rte_mem_page_size());
58901a6c311SAlfredo Cardigliano 	/*
59001a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
59101a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
592924e6b76SThomas Monjalon 	 * Adding rte_mem_page_size().
59301a6c311SAlfredo Cardigliano 	 */
594924e6b76SThomas Monjalon 	total_size += rte_mem_page_size();
59501a6c311SAlfredo Cardigliano 
59601a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
597924e6b76SThomas Monjalon 		total_size += RTE_ALIGN(sg_size, rte_mem_page_size());
598924e6b76SThomas Monjalon 		total_size += rte_mem_page_size();
59901a6c311SAlfredo Cardigliano 	}
60001a6c311SAlfredo Cardigliano 
601be39f75cSAndrew Boyer 	new = rte_zmalloc("ionic", struct_size, 0);
60201a6c311SAlfredo Cardigliano 	if (!new) {
60301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
60401a6c311SAlfredo Cardigliano 		return -ENOMEM;
60501a6c311SAlfredo Cardigliano 	}
60601a6c311SAlfredo Cardigliano 
60701a6c311SAlfredo Cardigliano 	new->lif = lif;
60801a6c311SAlfredo Cardigliano 
6097b20fc2fSAndrew Boyer 	/* Most queue types will store 1 ptr per descriptor */
610be39f75cSAndrew Boyer 	new->q.info = rte_calloc_socket("ionic",
6117b20fc2fSAndrew Boyer 				num_descs * num_segs, sizeof(void *),
612924e6b76SThomas Monjalon 				rte_mem_page_size(), socket_id);
61301a6c311SAlfredo Cardigliano 	if (!new->q.info) {
61401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6154c8f8d57SAndrew Boyer 		err = -ENOMEM;
6164c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
61701a6c311SAlfredo Cardigliano 	}
61801a6c311SAlfredo Cardigliano 
619d5850081SAndrew Boyer 	new->q.num_segs = num_segs;
62001a6c311SAlfredo Cardigliano 	new->q.type = type;
62101a6c311SAlfredo Cardigliano 
6224ad56b7aSAndrew Boyer 	err = ionic_q_init(&new->q, index, num_descs);
62301a6c311SAlfredo Cardigliano 	if (err) {
62401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6254c8f8d57SAndrew Boyer 		goto err_out_free_info;
62601a6c311SAlfredo Cardigliano 	}
62701a6c311SAlfredo Cardigliano 
6282aed9865SAndrew Boyer 	err = ionic_cq_init(&new->cq, num_descs);
62901a6c311SAlfredo Cardigliano 	if (err) {
63001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6314c8f8d57SAndrew Boyer 		goto err_out_free_info;
63201a6c311SAlfredo Cardigliano 	}
63301a6c311SAlfredo Cardigliano 
63401a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
6354ad56b7aSAndrew Boyer 		type_name, index /* queue_idx */,
63601a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
63701a6c311SAlfredo Cardigliano 
63801a6c311SAlfredo Cardigliano 	if (!new->base_z) {
63901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
64001a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6414c8f8d57SAndrew Boyer 		goto err_out_free_info;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
64401a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
64501a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
64601a6c311SAlfredo Cardigliano 
64701a6c311SAlfredo Cardigliano 	q_base = new->base;
64801a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
64901a6c311SAlfredo Cardigliano 
650924e6b76SThomas Monjalon 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size,
651924e6b76SThomas Monjalon 			rte_mem_page_size());
652924e6b76SThomas Monjalon 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size,
653924e6b76SThomas Monjalon 			rte_mem_page_size());
65401a6c311SAlfredo Cardigliano 
65501a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
65601a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
657924e6b76SThomas Monjalon 				rte_mem_page_size());
658924e6b76SThomas Monjalon 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size,
659924e6b76SThomas Monjalon 				rte_mem_page_size());
66001a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
66101a6c311SAlfredo Cardigliano 	}
66201a6c311SAlfredo Cardigliano 
6634ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6644ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
66501a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
66601a6c311SAlfredo Cardigliano 
66701a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
66801a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
66901a6c311SAlfredo Cardigliano 
67001a6c311SAlfredo Cardigliano 	*qcq = new;
67101a6c311SAlfredo Cardigliano 
67201a6c311SAlfredo Cardigliano 	return 0;
67301a6c311SAlfredo Cardigliano 
6744c8f8d57SAndrew Boyer err_out_free_info:
6754c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6764c8f8d57SAndrew Boyer err_out_free_qcq:
6774c8f8d57SAndrew Boyer 	rte_free(new);
67801a6c311SAlfredo Cardigliano 
67901a6c311SAlfredo Cardigliano 	return err;
68001a6c311SAlfredo Cardigliano }
68101a6c311SAlfredo Cardigliano 
68201a6c311SAlfredo Cardigliano void
68301a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
68401a6c311SAlfredo Cardigliano {
68501a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
68601a6c311SAlfredo Cardigliano 		qcq->base = NULL;
68701a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
68801a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
68901a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
69001a6c311SAlfredo Cardigliano 	}
69101a6c311SAlfredo Cardigliano 
69201a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
69301a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
69401a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
69501a6c311SAlfredo Cardigliano 	}
69601a6c311SAlfredo Cardigliano 
69701a6c311SAlfredo Cardigliano 	rte_free(qcq);
69801a6c311SAlfredo Cardigliano }
69901a6c311SAlfredo Cardigliano 
7007b20fc2fSAndrew Boyer static uint64_t
7017b20fc2fSAndrew Boyer ionic_rx_rearm_data(struct ionic_lif *lif)
7027b20fc2fSAndrew Boyer {
7037b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7047b20fc2fSAndrew Boyer 
7057b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7067b20fc2fSAndrew Boyer 
7077b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7087b20fc2fSAndrew Boyer 	rxm.data_off = RTE_PKTMBUF_HEADROOM;
7097b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7107b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7117b20fc2fSAndrew Boyer 
7127b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7137b20fc2fSAndrew Boyer 
7147b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7157b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7167b20fc2fSAndrew Boyer }
7177b20fc2fSAndrew Boyer 
7187b20fc2fSAndrew Boyer static uint64_t
7197b20fc2fSAndrew Boyer ionic_rx_seg_rearm_data(struct ionic_lif *lif)
7207b20fc2fSAndrew Boyer {
7217b20fc2fSAndrew Boyer 	struct rte_mbuf rxm;
7227b20fc2fSAndrew Boyer 
7237b20fc2fSAndrew Boyer 	memset(&rxm, 0, sizeof(rxm));
7247b20fc2fSAndrew Boyer 
7257b20fc2fSAndrew Boyer 	rte_mbuf_refcnt_set(&rxm, 1);
7267b20fc2fSAndrew Boyer 	rxm.data_off = 0;  /* no headroom */
7277b20fc2fSAndrew Boyer 	rxm.nb_segs = 1;
7287b20fc2fSAndrew Boyer 	rxm.port = lif->port_id;
7297b20fc2fSAndrew Boyer 
7307b20fc2fSAndrew Boyer 	rte_compiler_barrier();
7317b20fc2fSAndrew Boyer 
7327b20fc2fSAndrew Boyer 	RTE_BUILD_BUG_ON(sizeof(rxm.rearm_data[0]) != sizeof(uint64_t));
7337b20fc2fSAndrew Boyer 	return rxm.rearm_data[0];
7347b20fc2fSAndrew Boyer }
7357b20fc2fSAndrew Boyer 
736a27d9013SAlfredo Cardigliano int
7378ec5ad7fSAndrew Boyer ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
738d5850081SAndrew Boyer 		uint16_t nrxq_descs, struct rte_mempool *mb_pool,
739d5850081SAndrew Boyer 		struct ionic_rx_qcq **rxq_out)
740a27d9013SAlfredo Cardigliano {
741be39f75cSAndrew Boyer 	struct ionic_rx_qcq *rxq;
742d5850081SAndrew Boyer 	uint16_t flags, seg_size, hdr_seg_size, max_segs, max_segs_fw;
743d5850081SAndrew Boyer 	uint32_t max_mtu;
744be39f75cSAndrew Boyer 	int err;
745a27d9013SAlfredo Cardigliano 
746a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
747b671e69aSAndrew Boyer 
748d5850081SAndrew Boyer 	seg_size = rte_pktmbuf_data_room_size(mb_pool);
749d5850081SAndrew Boyer 
750d5850081SAndrew Boyer 	/* The first mbuf needs to leave headroom */
751d5850081SAndrew Boyer 	hdr_seg_size = seg_size - RTE_PKTMBUF_HEADROOM;
752d5850081SAndrew Boyer 
753d5850081SAndrew Boyer 	max_mtu = rte_le_to_cpu_32(lif->adapter->ident.lif.eth.max_mtu);
754d5850081SAndrew Boyer 
755d5850081SAndrew Boyer 	max_segs_fw = IONIC_RX_MAX_SG_ELEMS + 1;
756d5850081SAndrew Boyer 
757d5850081SAndrew Boyer 	/*
758d5850081SAndrew Boyer 	 * Calculate how many fragment pointers might be stored in queue.
7597b20fc2fSAndrew Boyer 	 * This is the worst-case number, so that there's enough room in
7607b20fc2fSAndrew Boyer 	 * the info array.
761d5850081SAndrew Boyer 	 */
762d5850081SAndrew Boyer 	max_segs = 1 + (max_mtu + RTE_PKTMBUF_HEADROOM - 1) / seg_size;
763d5850081SAndrew Boyer 
7647b20fc2fSAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq %u max_mtu %u seg_size %u max_segs %u",
7657b20fc2fSAndrew Boyer 		index, max_mtu, seg_size, max_segs);
766d5850081SAndrew Boyer 	if (max_segs > max_segs_fw) {
767d5850081SAndrew Boyer 		IONIC_PRINT(ERR, "Rx mbuf size insufficient (%d > %d avail)",
768d5850081SAndrew Boyer 			max_segs, max_segs_fw);
769d5850081SAndrew Boyer 		return -EINVAL;
770d5850081SAndrew Boyer 	}
771d5850081SAndrew Boyer 
7724ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
7734ad56b7aSAndrew Boyer 		IONIC_QTYPE_RXQ,
774be39f75cSAndrew Boyer 		sizeof(struct ionic_rx_qcq),
7758ec5ad7fSAndrew Boyer 		socket_id,
7764ad56b7aSAndrew Boyer 		index,
7774ad56b7aSAndrew Boyer 		"rx",
7784ad56b7aSAndrew Boyer 		flags,
779a27d9013SAlfredo Cardigliano 		nrxq_descs,
780d5850081SAndrew Boyer 		max_segs,
781a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
782a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
783a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
784be39f75cSAndrew Boyer 		(struct ionic_qcq **)&rxq);
785a27d9013SAlfredo Cardigliano 	if (err)
786a27d9013SAlfredo Cardigliano 		return err;
787a27d9013SAlfredo Cardigliano 
788be39f75cSAndrew Boyer 	rxq->flags = flags;
789d5850081SAndrew Boyer 	rxq->seg_size = seg_size;
790d5850081SAndrew Boyer 	rxq->hdr_seg_size = hdr_seg_size;
7917b20fc2fSAndrew Boyer 	rxq->rearm_data = ionic_rx_rearm_data(lif);
7927b20fc2fSAndrew Boyer 	rxq->rearm_seg_data = ionic_rx_seg_rearm_data(lif);
793be39f75cSAndrew Boyer 
794be39f75cSAndrew Boyer 	lif->rxqcqs[index] = rxq;
795be39f75cSAndrew Boyer 	*rxq_out = rxq;
796a27d9013SAlfredo Cardigliano 
797a27d9013SAlfredo Cardigliano 	return 0;
798a27d9013SAlfredo Cardigliano }
799a27d9013SAlfredo Cardigliano 
800a27d9013SAlfredo Cardigliano int
8018ec5ad7fSAndrew Boyer ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t socket_id, uint32_t index,
802be39f75cSAndrew Boyer 		uint16_t ntxq_descs, struct ionic_tx_qcq **txq_out)
803a27d9013SAlfredo Cardigliano {
804be39f75cSAndrew Boyer 	struct ionic_tx_qcq *txq;
805e19eea1eSAndrew Boyer 	uint16_t flags, num_segs_fw;
806be39f75cSAndrew Boyer 	int err;
807a27d9013SAlfredo Cardigliano 
808a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
809e19eea1eSAndrew Boyer 
810e19eea1eSAndrew Boyer 	num_segs_fw = IONIC_TX_MAX_SG_ELEMS_V1 + 1;
811e19eea1eSAndrew Boyer 
8124ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8134ad56b7aSAndrew Boyer 		IONIC_QTYPE_TXQ,
814be39f75cSAndrew Boyer 		sizeof(struct ionic_tx_qcq),
8158ec5ad7fSAndrew Boyer 		socket_id,
8164ad56b7aSAndrew Boyer 		index,
8174ad56b7aSAndrew Boyer 		"tx",
8184ad56b7aSAndrew Boyer 		flags,
819a27d9013SAlfredo Cardigliano 		ntxq_descs,
820*b4beb84aSAndrew Boyer 		num_segs_fw,
821a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
822a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
82356117636SAndrew Boyer 		sizeof(struct ionic_txq_sg_desc_v1),
824be39f75cSAndrew Boyer 		(struct ionic_qcq **)&txq);
825a27d9013SAlfredo Cardigliano 	if (err)
826a27d9013SAlfredo Cardigliano 		return err;
827a27d9013SAlfredo Cardigliano 
828be39f75cSAndrew Boyer 	txq->flags = flags;
829e19eea1eSAndrew Boyer 	txq->num_segs_fw = num_segs_fw;
830be39f75cSAndrew Boyer 
831be39f75cSAndrew Boyer 	lif->txqcqs[index] = txq;
832be39f75cSAndrew Boyer 	*txq_out = txq;
833a27d9013SAlfredo Cardigliano 
834a27d9013SAlfredo Cardigliano 	return 0;
835a27d9013SAlfredo Cardigliano }
836a27d9013SAlfredo Cardigliano 
83701a6c311SAlfredo Cardigliano static int
83801a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
83901a6c311SAlfredo Cardigliano {
840be39f75cSAndrew Boyer 	uint16_t flags = 0;
841be39f75cSAndrew Boyer 	int err;
84201a6c311SAlfredo Cardigliano 
8434ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8444ad56b7aSAndrew Boyer 		IONIC_QTYPE_ADMINQ,
845be39f75cSAndrew Boyer 		sizeof(struct ionic_admin_qcq),
8468ec5ad7fSAndrew Boyer 		rte_socket_id(),
8474ad56b7aSAndrew Boyer 		0,
8484ad56b7aSAndrew Boyer 		"admin",
8494ad56b7aSAndrew Boyer 		flags,
85001a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
851d5850081SAndrew Boyer 		1,
85201a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
85301a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
85401a6c311SAlfredo Cardigliano 		0,
855be39f75cSAndrew Boyer 		(struct ionic_qcq **)&lif->adminqcq);
85627b942c8SAlfredo Cardigliano 	if (err)
85727b942c8SAlfredo Cardigliano 		return err;
85801a6c311SAlfredo Cardigliano 
85927b942c8SAlfredo Cardigliano 	return 0;
86027b942c8SAlfredo Cardigliano }
86127b942c8SAlfredo Cardigliano 
86227b942c8SAlfredo Cardigliano static int
86327b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
86427b942c8SAlfredo Cardigliano {
865be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq;
8664c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
867be39f75cSAndrew Boyer 	uint16_t flags = 0;
868be39f75cSAndrew Boyer 	int err;
86927b942c8SAlfredo Cardigliano 
8704ad56b7aSAndrew Boyer 	err = ionic_qcq_alloc(lif,
8714ad56b7aSAndrew Boyer 		IONIC_QTYPE_NOTIFYQ,
872be39f75cSAndrew Boyer 		sizeof(struct ionic_notify_qcq),
8738ec5ad7fSAndrew Boyer 		rte_socket_id(),
8744ad56b7aSAndrew Boyer 		0,
8754ad56b7aSAndrew Boyer 		"notify",
87627b942c8SAlfredo Cardigliano 		flags,
87727b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
878d5850081SAndrew Boyer 		1,
87927b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
88027b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
88127b942c8SAlfredo Cardigliano 		0,
882be39f75cSAndrew Boyer 		(struct ionic_qcq **)&nqcq);
88301a6c311SAlfredo Cardigliano 	if (err)
88401a6c311SAlfredo Cardigliano 		return err;
88501a6c311SAlfredo Cardigliano 
8864c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
8874c8f8d57SAndrew Boyer 	if (err) {
888be39f75cSAndrew Boyer 		ionic_qcq_free(&nqcq->qcq);
8894c8f8d57SAndrew Boyer 		return err;
8904c8f8d57SAndrew Boyer 	}
8914c8f8d57SAndrew Boyer 
8924c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8934c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8944c8f8d57SAndrew Boyer 
8954c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8964c8f8d57SAndrew Boyer 
89701a6c311SAlfredo Cardigliano 	return 0;
89801a6c311SAlfredo Cardigliano }
89901a6c311SAlfredo Cardigliano 
900c5d15850SAndrew Boyer static void
901c5d15850SAndrew Boyer ionic_lif_queue_identify(struct ionic_lif *lif)
902c5d15850SAndrew Boyer {
903c5d15850SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
904c5d15850SAndrew Boyer 	struct ionic_dev *idev = &adapter->idev;
905c5d15850SAndrew Boyer 	union ionic_q_identity *q_ident = &adapter->ident.txq;
906c5d15850SAndrew Boyer 	uint32_t q_words = RTE_DIM(q_ident->words);
907c5d15850SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
908c5d15850SAndrew Boyer 	uint32_t i, nwords, qtype;
909c5d15850SAndrew Boyer 	int err;
910c5d15850SAndrew Boyer 
911c5d15850SAndrew Boyer 	for (qtype = 0; qtype < RTE_DIM(ionic_qtype_vers); qtype++) {
912c5d15850SAndrew Boyer 		struct ionic_qtype_info *qti = &lif->qtype_info[qtype];
913c5d15850SAndrew Boyer 
914c5d15850SAndrew Boyer 		/* Filter out the types this driver knows about */
915c5d15850SAndrew Boyer 		switch (qtype) {
916c5d15850SAndrew Boyer 		case IONIC_QTYPE_ADMINQ:
917c5d15850SAndrew Boyer 		case IONIC_QTYPE_NOTIFYQ:
918c5d15850SAndrew Boyer 		case IONIC_QTYPE_RXQ:
919c5d15850SAndrew Boyer 		case IONIC_QTYPE_TXQ:
920c5d15850SAndrew Boyer 			break;
921c5d15850SAndrew Boyer 		default:
922c5d15850SAndrew Boyer 			continue;
923c5d15850SAndrew Boyer 		}
924c5d15850SAndrew Boyer 
925c5d15850SAndrew Boyer 		memset(qti, 0, sizeof(*qti));
926c5d15850SAndrew Boyer 
927c5d15850SAndrew Boyer 		ionic_dev_cmd_queue_identify(idev, IONIC_LIF_TYPE_CLASSIC,
928c5d15850SAndrew Boyer 			qtype, ionic_qtype_vers[qtype]);
929c5d15850SAndrew Boyer 		err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
930c5d15850SAndrew Boyer 		if (err == -EINVAL) {
931c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "qtype %d not supported\n", qtype);
932c5d15850SAndrew Boyer 			continue;
933c5d15850SAndrew Boyer 		} else if (err == -EIO) {
934c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, older FW\n");
935c5d15850SAndrew Boyer 			return;
936c5d15850SAndrew Boyer 		} else if (err) {
937c5d15850SAndrew Boyer 			IONIC_PRINT(ERR, "q_ident failed, qtype %d: %d\n",
938c5d15850SAndrew Boyer 				qtype, err);
939c5d15850SAndrew Boyer 			return;
940c5d15850SAndrew Boyer 		}
941c5d15850SAndrew Boyer 
942c5d15850SAndrew Boyer 		nwords = RTE_MIN(q_words, cmd_words);
943c5d15850SAndrew Boyer 		for (i = 0; i < nwords; i++)
944c5d15850SAndrew Boyer 			q_ident->words[i] = ioread32(&idev->dev_cmd->data[i]);
945c5d15850SAndrew Boyer 
946c5d15850SAndrew Boyer 		qti->version   = q_ident->version;
947c5d15850SAndrew Boyer 		qti->supported = q_ident->supported;
948c5d15850SAndrew Boyer 		qti->features  = rte_le_to_cpu_64(q_ident->features);
949c5d15850SAndrew Boyer 		qti->desc_sz   = rte_le_to_cpu_16(q_ident->desc_sz);
950c5d15850SAndrew Boyer 		qti->comp_sz   = rte_le_to_cpu_16(q_ident->comp_sz);
951c5d15850SAndrew Boyer 		qti->sg_desc_sz   = rte_le_to_cpu_16(q_ident->sg_desc_sz);
952c5d15850SAndrew Boyer 		qti->max_sg_elems = rte_le_to_cpu_16(q_ident->max_sg_elems);
953c5d15850SAndrew Boyer 		qti->sg_desc_stride =
954c5d15850SAndrew Boyer 			rte_le_to_cpu_16(q_ident->sg_desc_stride);
955c5d15850SAndrew Boyer 
956c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].version = %d",
957c5d15850SAndrew Boyer 			qtype, qti->version);
958c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].supported = %#x",
959c5d15850SAndrew Boyer 			qtype, qti->supported);
960c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].features = %#jx",
961c5d15850SAndrew Boyer 			qtype, qti->features);
962c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].desc_sz = %d",
963c5d15850SAndrew Boyer 			qtype, qti->desc_sz);
964c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].comp_sz = %d",
965c5d15850SAndrew Boyer 			qtype, qti->comp_sz);
966c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_sz = %d",
967c5d15850SAndrew Boyer 			qtype, qti->sg_desc_sz);
968c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].max_sg_elems = %d",
969c5d15850SAndrew Boyer 			qtype, qti->max_sg_elems);
970c5d15850SAndrew Boyer 		IONIC_PRINT(DEBUG, " qtype[%d].sg_desc_stride = %d",
971c5d15850SAndrew Boyer 			qtype, qti->sg_desc_stride);
972c5d15850SAndrew Boyer 	}
973c5d15850SAndrew Boyer }
974c5d15850SAndrew Boyer 
975669c8de6SAlfredo Cardigliano int
976669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
977669c8de6SAlfredo Cardigliano {
978c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
979669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
98001a6c311SAlfredo Cardigliano 	int err;
981669c8de6SAlfredo Cardigliano 
9824ae96cb8SAndrew Boyer 	/*
9834ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
9844ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
9854ae96cb8SAndrew Boyer 	 */
9864ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
9874ae96cb8SAndrew Boyer 
9884ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
989669c8de6SAlfredo Cardigliano 
990c5d15850SAndrew Boyer 	ionic_lif_queue_identify(lif);
991c5d15850SAndrew Boyer 
99256117636SAndrew Boyer 	if (lif->qtype_info[IONIC_QTYPE_TXQ].version < 1) {
99356117636SAndrew Boyer 		IONIC_PRINT(ERR, "FW too old, please upgrade");
99456117636SAndrew Boyer 		return -ENXIO;
99556117636SAndrew Boyer 	}
99656117636SAndrew Boyer 
997669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
998669c8de6SAlfredo Cardigliano 
99901a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
100001a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
100101a6c311SAlfredo Cardigliano 
100284cf25bdSAndrew Boyer 	lif->kern_dbpage = adapter->idev.db_pages;
1003c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
1004c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
1005c67719e1SAlfredo Cardigliano 		return -ENOMEM;
1006c67719e1SAlfredo Cardigliano 	}
1007c67719e1SAlfredo Cardigliano 
1008a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
1009a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
1010a27d9013SAlfredo Cardigliano 
1011a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
1012a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
1013a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1014a27d9013SAlfredo Cardigliano 	}
1015a27d9013SAlfredo Cardigliano 
1016a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
1017a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
1018a27d9013SAlfredo Cardigliano 
1019a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
1020a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
1021a27d9013SAlfredo Cardigliano 		return -ENOMEM;
1022a27d9013SAlfredo Cardigliano 	}
1023a27d9013SAlfredo Cardigliano 
102427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
102527b942c8SAlfredo Cardigliano 
102627b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
102727b942c8SAlfredo Cardigliano 	if (err) {
102827b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
102927b942c8SAlfredo Cardigliano 		return err;
103027b942c8SAlfredo Cardigliano 	}
103127b942c8SAlfredo Cardigliano 
103227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
103327b942c8SAlfredo Cardigliano 
103401a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
103501a6c311SAlfredo Cardigliano 	if (err) {
103601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
103701a6c311SAlfredo Cardigliano 		return err;
103801a6c311SAlfredo Cardigliano 	}
103901a6c311SAlfredo Cardigliano 
104001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
104101a6c311SAlfredo Cardigliano 
1042924e6b76SThomas Monjalon 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), rte_mem_page_size());
1043669c8de6SAlfredo Cardigliano 
1044669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
1045669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
1046669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
1047669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
1048669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
1049669c8de6SAlfredo Cardigliano 		return -ENOMEM;
1050669c8de6SAlfredo Cardigliano 	}
1051669c8de6SAlfredo Cardigliano 
1052669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
1053669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
1054669c8de6SAlfredo Cardigliano 
1055669c8de6SAlfredo Cardigliano 	return 0;
1056669c8de6SAlfredo Cardigliano }
1057669c8de6SAlfredo Cardigliano 
1058669c8de6SAlfredo Cardigliano void
1059669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
1060669c8de6SAlfredo Cardigliano {
106127b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
1062be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->notifyqcq->qcq);
106327b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
106427b942c8SAlfredo Cardigliano 	}
106527b942c8SAlfredo Cardigliano 
106601a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
1067be39f75cSAndrew Boyer 		ionic_qcq_free(&lif->adminqcq->qcq);
106801a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
106901a6c311SAlfredo Cardigliano 	}
107001a6c311SAlfredo Cardigliano 
1071a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
1072a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
1073a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
1074a27d9013SAlfredo Cardigliano 	}
1075a27d9013SAlfredo Cardigliano 
1076a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
1077a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
1078a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
1079a27d9013SAlfredo Cardigliano 	}
1080a27d9013SAlfredo Cardigliano 
1081669c8de6SAlfredo Cardigliano 	if (lif->info) {
1082669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
1083669c8de6SAlfredo Cardigliano 		lif->info = NULL;
1084669c8de6SAlfredo Cardigliano 	}
1085669c8de6SAlfredo Cardigliano }
1086669c8de6SAlfredo Cardigliano 
1087175e4e7eSAndrew Boyer void
1088175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
1089175e4e7eSAndrew Boyer {
1090175e4e7eSAndrew Boyer 	uint32_t i;
1091175e4e7eSAndrew Boyer 
1092175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
10937483341aSXueming Li 		ionic_dev_tx_queue_release(lif->eth_dev, i);
1094175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
1095175e4e7eSAndrew Boyer 	}
1096175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
10977483341aSXueming Li 		ionic_dev_rx_queue_release(lif->eth_dev, i);
1098175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
1099175e4e7eSAndrew Boyer 	}
1100175e4e7eSAndrew Boyer }
1101175e4e7eSAndrew Boyer 
110222e7171bSAlfredo Cardigliano int
110322e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
110422e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
110522e7171bSAlfredo Cardigliano {
110609f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
110722e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
110822e7171bSAlfredo Cardigliano 		.pending_work = true,
110922e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
111022e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
111122e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
111209f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
111309f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
111422e7171bSAlfredo Cardigliano 		},
111522e7171bSAlfredo Cardigliano 	};
111622e7171bSAlfredo Cardigliano 	unsigned int i;
111709f806e9SAndrew Boyer 	uint16_t tbl_sz =
111809f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
111922e7171bSAlfredo Cardigliano 
112022e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
112122e7171bSAlfredo Cardigliano 
112222e7171bSAlfredo Cardigliano 	lif->rss_types = types;
112322e7171bSAlfredo Cardigliano 
112422e7171bSAlfredo Cardigliano 	if (key)
112522e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
112622e7171bSAlfredo Cardigliano 
112722e7171bSAlfredo Cardigliano 	if (indir)
112809f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
112922e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
113022e7171bSAlfredo Cardigliano 
113122e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
113222e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
113322e7171bSAlfredo Cardigliano 
113422e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
113522e7171bSAlfredo Cardigliano }
113622e7171bSAlfredo Cardigliano 
113722e7171bSAlfredo Cardigliano static int
113822e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
113922e7171bSAlfredo Cardigliano {
114009f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
114122e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
114222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
114322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
114422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
114522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
114622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
114722e7171bSAlfredo Cardigliano 	};
114822e7171bSAlfredo Cardigliano 	uint32_t i;
114909f806e9SAndrew Boyer 	uint16_t tbl_sz =
115009f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
115122e7171bSAlfredo Cardigliano 
115222e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
115322e7171bSAlfredo Cardigliano 
11543d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
115522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
11563d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
11573d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
11583d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
115922e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
116022e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
116122e7171bSAlfredo Cardigliano 			return -ENOMEM;
116222e7171bSAlfredo Cardigliano 		}
116322e7171bSAlfredo Cardigliano 
116422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
116522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
11663d845eddSAndrew Boyer 	}
11673d845eddSAndrew Boyer 
11683d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
11693d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
117022e7171bSAlfredo Cardigliano 
117122e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
11723d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
117322e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
11743d845eddSAndrew Boyer 	}
117522e7171bSAlfredo Cardigliano 
11763d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
117722e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
117822e7171bSAlfredo Cardigliano }
117922e7171bSAlfredo Cardigliano 
118022e7171bSAlfredo Cardigliano static void
118122e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
118222e7171bSAlfredo Cardigliano {
118322e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
118422e7171bSAlfredo Cardigliano 		return;
118522e7171bSAlfredo Cardigliano 
118622e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
118722e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
118822e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
118922e7171bSAlfredo Cardigliano 
119022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
119122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
119222e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
119322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
119422e7171bSAlfredo Cardigliano 	}
119522e7171bSAlfredo Cardigliano }
119622e7171bSAlfredo Cardigliano 
1197be39f75cSAndrew Boyer void
1198be39f75cSAndrew Boyer ionic_lif_txq_deinit(struct ionic_tx_qcq *txq)
1199be39f75cSAndrew Boyer {
1200e7222f94SAndrew Boyer 	ionic_qcq_disable(&txq->qcq);
1201e7222f94SAndrew Boyer 
1202be39f75cSAndrew Boyer 	txq->flags &= ~IONIC_QCQ_F_INITED;
1203be39f75cSAndrew Boyer }
1204be39f75cSAndrew Boyer 
1205be39f75cSAndrew Boyer void
1206be39f75cSAndrew Boyer ionic_lif_rxq_deinit(struct ionic_rx_qcq *rxq)
1207be39f75cSAndrew Boyer {
1208e7222f94SAndrew Boyer 	ionic_qcq_disable(&rxq->qcq);
1209e7222f94SAndrew Boyer 
1210be39f75cSAndrew Boyer 	rxq->flags &= ~IONIC_QCQ_F_INITED;
1211be39f75cSAndrew Boyer }
1212be39f75cSAndrew Boyer 
121301a6c311SAlfredo Cardigliano static void
1214be39f75cSAndrew Boyer ionic_lif_adminq_deinit(struct ionic_lif *lif)
121501a6c311SAlfredo Cardigliano {
1216be39f75cSAndrew Boyer 	lif->adminqcq->flags &= ~IONIC_QCQ_F_INITED;
12174c8f8d57SAndrew Boyer }
12184c8f8d57SAndrew Boyer 
12194c8f8d57SAndrew Boyer static void
12204c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
12214c8f8d57SAndrew Boyer {
1222be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
12234c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
12244c8f8d57SAndrew Boyer 
12254c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
12264c8f8d57SAndrew Boyer 		return;
12274c8f8d57SAndrew Boyer 
12284c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
12294c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
12304c8f8d57SAndrew Boyer 
12314c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1232a27d9013SAlfredo Cardigliano }
1233a27d9013SAlfredo Cardigliano 
123401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
123501a6c311SAlfredo Cardigliano int
123601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
123701a6c311SAlfredo Cardigliano 		void *cb_arg)
123801a6c311SAlfredo Cardigliano {
123901a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
124001a6c311SAlfredo Cardigliano 	uint32_t work_done;
124101a6c311SAlfredo Cardigliano 
124201a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
124301a6c311SAlfredo Cardigliano 
124401a6c311SAlfredo Cardigliano 	return work_done;
124501a6c311SAlfredo Cardigliano }
124601a6c311SAlfredo Cardigliano 
124727b942c8SAlfredo Cardigliano static void
124827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
124927b942c8SAlfredo Cardigliano {
125027b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
125127b942c8SAlfredo Cardigliano 	bool link_up;
125227b942c8SAlfredo Cardigliano 
125327b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
125427b942c8SAlfredo Cardigliano 
125527b942c8SAlfredo Cardigliano 	if (!lif->info)
125627b942c8SAlfredo Cardigliano 		return;
125727b942c8SAlfredo Cardigliano 
125827b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
125927b942c8SAlfredo Cardigliano 
126027b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
126127b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
126227b942c8SAlfredo Cardigliano 		return;
126327b942c8SAlfredo Cardigliano 
126427b942c8SAlfredo Cardigliano 	if (link_up) {
126509f806e9SAndrew Boyer 		adapter->link_speed =
126609f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1267be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1268be63459eSAndrew Boyer 			adapter->link_speed);
126927b942c8SAlfredo Cardigliano 	} else {
127027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
127127b942c8SAlfredo Cardigliano 	}
127227b942c8SAlfredo Cardigliano 
127327b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1274be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1275be63459eSAndrew Boyer }
1276be63459eSAndrew Boyer 
1277be63459eSAndrew Boyer static void
1278be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1279be63459eSAndrew Boyer {
1280be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1281be63459eSAndrew Boyer 		return;
1282be63459eSAndrew Boyer 
1283be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1284be63459eSAndrew Boyer 
1285be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1286be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1287be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1288be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1289be63459eSAndrew Boyer 	}
1290be63459eSAndrew Boyer 
1291be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
129227b942c8SAlfredo Cardigliano }
129327b942c8SAlfredo Cardigliano 
129427b942c8SAlfredo Cardigliano static bool
12954ad56b7aSAndrew Boyer ionic_notifyq_cb(struct ionic_cq *cq, uint16_t cq_desc_index, void *cb_arg)
129627b942c8SAlfredo Cardigliano {
129727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
129827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
129927b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
130027b942c8SAlfredo Cardigliano 
130127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
130227b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
130327b942c8SAlfredo Cardigliano 
130427b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
130527b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
130627b942c8SAlfredo Cardigliano 		return false;
130727b942c8SAlfredo Cardigliano 
130827b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
130927b942c8SAlfredo Cardigliano 
131027b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
131127b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
131227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1313be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1314be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1315be63459eSAndrew Boyer 			lif->name,
131627b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
131727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
131827b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
131927b942c8SAlfredo Cardigliano 
132027b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
132127b942c8SAlfredo Cardigliano 		break;
1322be63459eSAndrew Boyer 
1323be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1324be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1325be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1326be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1327be63459eSAndrew Boyer 			lif->name,
1328be63459eSAndrew Boyer 			cq_desc->event.eid,
1329be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1330be63459eSAndrew Boyer 			cq_desc->reset.state);
1331be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1332be63459eSAndrew Boyer 		break;
1333be63459eSAndrew Boyer 
133427b942c8SAlfredo Cardigliano 	default:
133527b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
133627b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
133727b942c8SAlfredo Cardigliano 		break;
133827b942c8SAlfredo Cardigliano 	}
133927b942c8SAlfredo Cardigliano 
134027b942c8SAlfredo Cardigliano 	return true;
134127b942c8SAlfredo Cardigliano }
134227b942c8SAlfredo Cardigliano 
134327b942c8SAlfredo Cardigliano int
134427b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
134527b942c8SAlfredo Cardigliano {
134627b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1347be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
134827b942c8SAlfredo Cardigliano 	uint32_t work_done;
134927b942c8SAlfredo Cardigliano 
1350be39f75cSAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED)) {
135127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
135227b942c8SAlfredo Cardigliano 		return -1;
135327b942c8SAlfredo Cardigliano 	}
135427b942c8SAlfredo Cardigliano 
1355be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
135627b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
135727b942c8SAlfredo Cardigliano 
1358be39f75cSAndrew Boyer 	work_done = ionic_qcq_service(&nqcq->qcq, budget,
1359be39f75cSAndrew Boyer 				ionic_notifyq_cb, lif);
136027b942c8SAlfredo Cardigliano 
136127b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
136227b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
136327b942c8SAlfredo Cardigliano 
1364be39f75cSAndrew Boyer 	ionic_intr_credits(idev->intr_ctrl, nqcq->intr.index,
136527b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
136627b942c8SAlfredo Cardigliano 
1367be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
136827b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
136927b942c8SAlfredo Cardigliano 
137027b942c8SAlfredo Cardigliano 	return 0;
137127b942c8SAlfredo Cardigliano }
137227b942c8SAlfredo Cardigliano 
137301a6c311SAlfredo Cardigliano static int
137401a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
137501a6c311SAlfredo Cardigliano {
137601a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1377be39f75cSAndrew Boyer 	struct ionic_admin_qcq *aqcq = lif->adminqcq;
1378be39f75cSAndrew Boyer 	struct ionic_queue *q = &aqcq->qcq.q;
137901a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
138001a6c311SAlfredo Cardigliano 	int err;
138101a6c311SAlfredo Cardigliano 
1382be39f75cSAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, &aqcq->qcq);
138301a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
138401a6c311SAlfredo Cardigliano 	if (err)
138501a6c311SAlfredo Cardigliano 		return err;
138601a6c311SAlfredo Cardigliano 
138701a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
138801a6c311SAlfredo Cardigliano 
138901a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
139009f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
139101a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
139201a6c311SAlfredo Cardigliano 
139301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
139401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
139501a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
139601a6c311SAlfredo Cardigliano 
1397be39f75cSAndrew Boyer 	aqcq->flags |= IONIC_QCQ_F_INITED;
139801a6c311SAlfredo Cardigliano 
139901a6c311SAlfredo Cardigliano 	return 0;
140001a6c311SAlfredo Cardigliano }
140101a6c311SAlfredo Cardigliano 
140227b942c8SAlfredo Cardigliano static int
140327b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
140427b942c8SAlfredo Cardigliano {
140527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1406be39f75cSAndrew Boyer 	struct ionic_notify_qcq *nqcq = lif->notifyqcq;
1407be39f75cSAndrew Boyer 	struct ionic_queue *q = &nqcq->qcq.q;
14080a00bdafSAndrew Boyer 	uint16_t flags = IONIC_QINIT_F_ENA;
140927b942c8SAlfredo Cardigliano 	int err;
141027b942c8SAlfredo Cardigliano 
141127b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
141227b942c8SAlfredo Cardigliano 		.pending_work = true,
141327b942c8SAlfredo Cardigliano 		.cmd.q_init = {
141427b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
141527b942c8SAlfredo Cardigliano 			.type = q->type,
1416c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
141709f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
14180a00bdafSAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
141927b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
142009f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
142127b942c8SAlfredo Cardigliano 		}
142227b942c8SAlfredo Cardigliano 	};
142327b942c8SAlfredo Cardigliano 
14240a00bdafSAndrew Boyer 	/* Only enable an interrupt if the device supports them */
14250a00bdafSAndrew Boyer 	if (lif->adapter->intf->configure_intr != NULL) {
14260a00bdafSAndrew Boyer 		flags |= IONIC_QINIT_F_IRQ;
14270a00bdafSAndrew Boyer 		ctx.cmd.q_init.intr_index = rte_cpu_to_le_16(nqcq->intr.index);
14280a00bdafSAndrew Boyer 	}
14290a00bdafSAndrew Boyer 	ctx.cmd.q_init.flags = rte_cpu_to_le_16(flags);
14300a00bdafSAndrew Boyer 
143109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
143209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
143327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
143427b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14354ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
143627b942c8SAlfredo Cardigliano 
143727b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
143827b942c8SAlfredo Cardigliano 	if (err)
143927b942c8SAlfredo Cardigliano 		return err;
144027b942c8SAlfredo Cardigliano 
144127b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
144209f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
144327b942c8SAlfredo Cardigliano 	q->db = NULL;
144427b942c8SAlfredo Cardigliano 
144527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
144627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
144727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
144827b942c8SAlfredo Cardigliano 
1449be39f75cSAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
145027b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
145127b942c8SAlfredo Cardigliano 
1452be39f75cSAndrew Boyer 	nqcq->flags |= IONIC_QCQ_F_INITED;
145327b942c8SAlfredo Cardigliano 
145427b942c8SAlfredo Cardigliano 	return 0;
145527b942c8SAlfredo Cardigliano }
145627b942c8SAlfredo Cardigliano 
1457669c8de6SAlfredo Cardigliano int
1458598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1459598f6726SAlfredo Cardigliano {
1460598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1461598f6726SAlfredo Cardigliano 		.pending_work = true,
1462598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1463598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1464598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
146509f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1466598f6726SAlfredo Cardigliano 		},
1467598f6726SAlfredo Cardigliano 	};
1468598f6726SAlfredo Cardigliano 	int err;
1469598f6726SAlfredo Cardigliano 
1470598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1471598f6726SAlfredo Cardigliano 	if (err)
1472598f6726SAlfredo Cardigliano 		return err;
1473598f6726SAlfredo Cardigliano 
147409f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1475598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1476598f6726SAlfredo Cardigliano 
1477598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1478598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1479598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1480598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1481598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1482598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1483598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1484598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1485598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1486598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1487598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1488598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1489598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1490598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1491598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1492598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1493598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1494598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1495598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1496598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1497598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1498598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1499598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1500598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1501598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1502598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1503598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1504598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1505598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1506598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1507598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1508598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1509598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1510598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1511598f6726SAlfredo Cardigliano 
1512598f6726SAlfredo Cardigliano 	return 0;
1513598f6726SAlfredo Cardigliano }
1514598f6726SAlfredo Cardigliano 
1515a27d9013SAlfredo Cardigliano int
1516be39f75cSAndrew Boyer ionic_lif_txq_init(struct ionic_tx_qcq *txq)
1517a27d9013SAlfredo Cardigliano {
1518be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &txq->qcq;
1519a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1520a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1521a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1522a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1523a27d9013SAlfredo Cardigliano 		.pending_work = true,
1524a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1525a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1526a27d9013SAlfredo Cardigliano 			.type = q->type,
1527c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
152809f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
152909f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
153009f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
153109f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1532a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
153309f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
153409f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
153509f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1536a27d9013SAlfredo Cardigliano 		},
1537a27d9013SAlfredo Cardigliano 	};
1538a27d9013SAlfredo Cardigliano 	int err;
1539a27d9013SAlfredo Cardigliano 
154009f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
154109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1542a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1543a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15444ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1545a27d9013SAlfredo Cardigliano 
1546e7222f94SAndrew Boyer 	ionic_q_reset(q);
1547e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1548e7222f94SAndrew Boyer 
1549be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1550a27d9013SAlfredo Cardigliano 	if (err)
1551a27d9013SAlfredo Cardigliano 		return err;
1552a27d9013SAlfredo Cardigliano 
1553a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
155409f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1555a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1556a27d9013SAlfredo Cardigliano 
1557a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1558a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1559a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1560a27d9013SAlfredo Cardigliano 
1561be39f75cSAndrew Boyer 	txq->flags |= IONIC_QCQ_F_INITED;
1562a27d9013SAlfredo Cardigliano 
1563a27d9013SAlfredo Cardigliano 	return 0;
1564a27d9013SAlfredo Cardigliano }
1565a27d9013SAlfredo Cardigliano 
1566a27d9013SAlfredo Cardigliano int
1567be39f75cSAndrew Boyer ionic_lif_rxq_init(struct ionic_rx_qcq *rxq)
1568a27d9013SAlfredo Cardigliano {
1569be39f75cSAndrew Boyer 	struct ionic_qcq *qcq = &rxq->qcq;
1570a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1571a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1572a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1573a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1574a27d9013SAlfredo Cardigliano 		.pending_work = true,
1575a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1576a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1577a27d9013SAlfredo Cardigliano 			.type = q->type,
1578c5d15850SAndrew Boyer 			.ver = lif->qtype_info[q->type].version,
157909f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
158009f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
158109f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
158209f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1583a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
158409f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
158509f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
158609f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1587a27d9013SAlfredo Cardigliano 		},
1588a27d9013SAlfredo Cardigliano 	};
1589a27d9013SAlfredo Cardigliano 	int err;
1590a27d9013SAlfredo Cardigliano 
159109f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
159209f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1593a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1594a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
15954ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1596a27d9013SAlfredo Cardigliano 
1597e7222f94SAndrew Boyer 	ionic_q_reset(q);
1598e7222f94SAndrew Boyer 	ionic_cq_reset(cq);
1599e7222f94SAndrew Boyer 
1600be39f75cSAndrew Boyer 	err = ionic_adminq_post_wait(lif, &ctx);
1601a27d9013SAlfredo Cardigliano 	if (err)
1602a27d9013SAlfredo Cardigliano 		return err;
1603a27d9013SAlfredo Cardigliano 
1604a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
160509f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1606a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1607a27d9013SAlfredo Cardigliano 
1608be39f75cSAndrew Boyer 	rxq->flags |= IONIC_QCQ_F_INITED;
1609a27d9013SAlfredo Cardigliano 
1610a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1611a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1612a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1613a27d9013SAlfredo Cardigliano 
1614a27d9013SAlfredo Cardigliano 	return 0;
1615a27d9013SAlfredo Cardigliano }
1616a27d9013SAlfredo Cardigliano 
1617598f6726SAlfredo Cardigliano static int
1618598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1619598f6726SAlfredo Cardigliano {
1620598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1621598f6726SAlfredo Cardigliano 		.pending_work = true,
1622598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1623598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1624598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1625598f6726SAlfredo Cardigliano 		},
1626598f6726SAlfredo Cardigliano 	};
1627598f6726SAlfredo Cardigliano 	int err;
1628598f6726SAlfredo Cardigliano 
1629598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1630598f6726SAlfredo Cardigliano 
1631598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1632598f6726SAlfredo Cardigliano 	if (err)
1633598f6726SAlfredo Cardigliano 		return err;
1634598f6726SAlfredo Cardigliano 
1635598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1636598f6726SAlfredo Cardigliano 
1637598f6726SAlfredo Cardigliano 	return 0;
1638598f6726SAlfredo Cardigliano }
1639598f6726SAlfredo Cardigliano 
1640598f6726SAlfredo Cardigliano static void
1641598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1642598f6726SAlfredo Cardigliano {
1643598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1644598f6726SAlfredo Cardigliano 		.pending_work = true,
1645598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1646598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1647598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1648598f6726SAlfredo Cardigliano 		},
1649598f6726SAlfredo Cardigliano 	};
1650598f6726SAlfredo Cardigliano 
16514ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
16524ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1653598f6726SAlfredo Cardigliano 
1654598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1655598f6726SAlfredo Cardigliano }
1656598f6726SAlfredo Cardigliano 
1657598f6726SAlfredo Cardigliano int
1658669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1659669c8de6SAlfredo Cardigliano {
1660669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1661656bfc9aSAndrew Boyer 	struct ionic_lif_init_comp comp;
1662669c8de6SAlfredo Cardigliano 	int err;
1663669c8de6SAlfredo Cardigliano 
16643cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
16653cdfd905SAlfredo Cardigliano 
166600b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1667669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1668669c8de6SAlfredo Cardigliano 	if (err)
1669669c8de6SAlfredo Cardigliano 		return err;
1670669c8de6SAlfredo Cardigliano 
1671656bfc9aSAndrew Boyer 	ionic_dev_cmd_comp(idev, &comp);
1672656bfc9aSAndrew Boyer 
167309f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1674669c8de6SAlfredo Cardigliano 
167501a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
167601a6c311SAlfredo Cardigliano 	if (err)
167701a6c311SAlfredo Cardigliano 		return err;
167801a6c311SAlfredo Cardigliano 
167927b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
168027b942c8SAlfredo Cardigliano 	if (err)
168127b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
168227b942c8SAlfredo Cardigliano 
168318a44465SAndrew Boyer 	/*
168418a44465SAndrew Boyer 	 * Configure initial feature set
168518a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
168618a44465SAndrew Boyer 	 */
168718a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1688598f6726SAlfredo Cardigliano 
1689598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1690598f6726SAlfredo Cardigliano 	if (err)
1691598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1692598f6726SAlfredo Cardigliano 
169354fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1694598f6726SAlfredo Cardigliano 	if (err)
1695598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1696598f6726SAlfredo Cardigliano 
169754fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
169854fe083fSAlfredo Cardigliano 	if (err)
169954fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
170054fe083fSAlfredo Cardigliano 
1701598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1702598f6726SAlfredo Cardigliano 
1703669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1704669c8de6SAlfredo Cardigliano 
1705669c8de6SAlfredo Cardigliano 	return 0;
170627b942c8SAlfredo Cardigliano 
170754fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
170854fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
170954fe083fSAlfredo Cardigliano 
1710598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
17114c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1712598f6726SAlfredo Cardigliano 
171327b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1714be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
171527b942c8SAlfredo Cardigliano 
171627b942c8SAlfredo Cardigliano 	return err;
1717669c8de6SAlfredo Cardigliano }
1718669c8de6SAlfredo Cardigliano 
1719669c8de6SAlfredo Cardigliano void
1720669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1721669c8de6SAlfredo Cardigliano {
1722669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1723669c8de6SAlfredo Cardigliano 		return;
1724669c8de6SAlfredo Cardigliano 
172554fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
172622e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
17274c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1728be39f75cSAndrew Boyer 	ionic_lif_adminq_deinit(lif);
172901a6c311SAlfredo Cardigliano 
1730669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1731669c8de6SAlfredo Cardigliano }
1732669c8de6SAlfredo Cardigliano 
173318a44465SAndrew Boyer void
173418a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
173518a44465SAndrew Boyer {
173618a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
173718a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
173818a44465SAndrew Boyer 
173918a44465SAndrew Boyer 	/*
174018a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
1741295968d1SFerruh Yigit 	 * set RTE_ETH_RX_OFFLOAD_VLAN_FILTER and ignore RTE_ETH_VLAN_FILTER_MASK
174218a44465SAndrew Boyer 	 */
1743295968d1SFerruh Yigit 	rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
174418a44465SAndrew Boyer 
1745295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1746295968d1SFerruh Yigit 		if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
174718a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
174818a44465SAndrew Boyer 		else
174918a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
175018a44465SAndrew Boyer 	}
175118a44465SAndrew Boyer }
175218a44465SAndrew Boyer 
175318a44465SAndrew Boyer void
1754598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1755598f6726SAlfredo Cardigliano {
175618a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
175718a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
175822e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
175909f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
176022e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
176109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
176222e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
176309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
176422e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
176522e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
176622e7171bSAlfredo Cardigliano 
1767598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1768598f6726SAlfredo Cardigliano 
176922e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
177022e7171bSAlfredo Cardigliano 		lif->port_id);
177122e7171bSAlfredo Cardigliano 
177222e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
177322e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
177422e7171bSAlfredo Cardigliano 
177522e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
177622e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
177722e7171bSAlfredo Cardigliano 
177822e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
177922e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1780a27d9013SAlfredo Cardigliano 
178118a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
178218a44465SAndrew Boyer 
178318a44465SAndrew Boyer 	/*
178418a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
178518a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
1786295968d1SFerruh Yigit 	 * rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
178718a44465SAndrew Boyer 	 */
178818a44465SAndrew Boyer 
178918a44465SAndrew Boyer 	/* RX per-port */
179018a44465SAndrew Boyer 
1791295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM ||
1792295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_UDP_CKSUM ||
1793295968d1SFerruh Yigit 	    rxmode->offloads & RTE_ETH_RX_OFFLOAD_TCP_CKSUM)
179418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
179518a44465SAndrew Boyer 	else
179618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
179718a44465SAndrew Boyer 
1798295968d1SFerruh Yigit 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER) {
179918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
180018a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
180118a44465SAndrew Boyer 	} else {
180218a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
180318a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
180418a44465SAndrew Boyer 	}
180518a44465SAndrew Boyer 
180618a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
1807295968d1SFerruh Yigit 	ionic_lif_configure_vlan_offload(lif, RTE_ETH_VLAN_STRIP_MASK);
180818a44465SAndrew Boyer 
180918a44465SAndrew Boyer 	/* TX per-port */
181018a44465SAndrew Boyer 
1811295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM ||
1812295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_UDP_CKSUM ||
1813295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_CKSUM ||
1814295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
1815295968d1SFerruh Yigit 	    txmode->offloads & RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
181618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
181718a44465SAndrew Boyer 	else
181818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
181918a44465SAndrew Boyer 
1820295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_VLAN_INSERT)
182118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
182218a44465SAndrew Boyer 	else
182318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
182418a44465SAndrew Boyer 
1825295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
182618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
182718a44465SAndrew Boyer 	else
182818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
182918a44465SAndrew Boyer 
1830295968d1SFerruh Yigit 	if (txmode->offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO) {
183118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
183218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
183318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
183418a44465SAndrew Boyer 	} else {
183518a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
183618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
183718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
183818a44465SAndrew Boyer 	}
1839598f6726SAlfredo Cardigliano }
1840598f6726SAlfredo Cardigliano 
1841598f6726SAlfredo Cardigliano int
1842598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1843598f6726SAlfredo Cardigliano {
18440578335aSAndrew Boyer 	uint32_t rx_mode;
1845a27d9013SAlfredo Cardigliano 	uint32_t i;
1846a27d9013SAlfredo Cardigliano 	int err;
1847598f6726SAlfredo Cardigliano 
184822e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
184922e7171bSAlfredo Cardigliano 	if (err)
185022e7171bSAlfredo Cardigliano 		return err;
185122e7171bSAlfredo Cardigliano 
18520578335aSAndrew Boyer 	if (!lif->rx_mode) {
18530578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
18540578335aSAndrew Boyer 			lif->name);
1855598f6726SAlfredo Cardigliano 
18560578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1857598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1858598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1859598f6726SAlfredo Cardigliano 
1860598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
18610578335aSAndrew Boyer 	}
1862598f6726SAlfredo Cardigliano 
1863a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1864a27d9013SAlfredo Cardigliano 		"on port %u",
1865a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1866a27d9013SAlfredo Cardigliano 
1867a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1868be39f75cSAndrew Boyer 		struct ionic_rx_qcq *rxq = lif->rxqcqs[i];
186902eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1870a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1871a27d9013SAlfredo Cardigliano 
1872a27d9013SAlfredo Cardigliano 			if (err)
1873a27d9013SAlfredo Cardigliano 				return err;
1874a27d9013SAlfredo Cardigliano 		}
1875a27d9013SAlfredo Cardigliano 	}
1876a27d9013SAlfredo Cardigliano 
1877a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1878be39f75cSAndrew Boyer 		struct ionic_tx_qcq *txq = lif->txqcqs[i];
187902eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1880a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1881a27d9013SAlfredo Cardigliano 
1882a27d9013SAlfredo Cardigliano 			if (err)
1883a27d9013SAlfredo Cardigliano 				return err;
1884a27d9013SAlfredo Cardigliano 		}
1885a27d9013SAlfredo Cardigliano 	}
1886a27d9013SAlfredo Cardigliano 
1887598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1888be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1889be63459eSAndrew Boyer 
1890be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1891598f6726SAlfredo Cardigliano 
1892598f6726SAlfredo Cardigliano 	return 0;
1893598f6726SAlfredo Cardigliano }
1894598f6726SAlfredo Cardigliano 
1895598f6726SAlfredo Cardigliano int
1896669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1897669c8de6SAlfredo Cardigliano {
1898669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1899669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
190009f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
190176276d71SAndrew Boyer 	uint32_t lif_words = RTE_DIM(ident->lif.words);
190276276d71SAndrew Boyer 	uint32_t cmd_words = RTE_DIM(idev->dev_cmd->data);
190376276d71SAndrew Boyer 	uint32_t i, nwords;
1904669c8de6SAlfredo Cardigliano 	int err;
1905669c8de6SAlfredo Cardigliano 
1906669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1907669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1908669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1909669c8de6SAlfredo Cardigliano 	if (err)
1910669c8de6SAlfredo Cardigliano 		return (err);
1911669c8de6SAlfredo Cardigliano 
1912669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1913669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1914669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1915669c8de6SAlfredo Cardigliano 
1916669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
191709f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1918669c8de6SAlfredo Cardigliano 
1919669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
192009f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1921669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
192209f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1923669c8de6SAlfredo Cardigliano 
1924669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
192509f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1926669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
192709f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1928669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
192909f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1930669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
193109f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1932669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
193309f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1934669c8de6SAlfredo Cardigliano 
1935669c8de6SAlfredo Cardigliano 	return 0;
1936669c8de6SAlfredo Cardigliano }
1937669c8de6SAlfredo Cardigliano 
1938669c8de6SAlfredo Cardigliano int
1939669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1940669c8de6SAlfredo Cardigliano {
1941669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
194209f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
194309f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1944669c8de6SAlfredo Cardigliano 
1945669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
194609f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1947669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
194809f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1949669c8de6SAlfredo Cardigliano 
195000b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1951669c8de6SAlfredo Cardigliano 
1952669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
19534ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
19544ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1955669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1956669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1957669c8de6SAlfredo Cardigliano 	}
1958669c8de6SAlfredo Cardigliano 
1959669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1960669c8de6SAlfredo Cardigliano 
1961669c8de6SAlfredo Cardigliano 	return 0;
1962669c8de6SAlfredo Cardigliano }
1963