xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 09f806e95d8141460bca9fe24f7809b854a013b3)
1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2669c8de6SAlfredo Cardigliano  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
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 
15598f6726SAlfredo Cardigliano static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
16598f6726SAlfredo Cardigliano static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
17598f6726SAlfredo Cardigliano 
1801a6c311SAlfredo Cardigliano int
1901a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq)
2001a6c311SAlfredo Cardigliano {
2101a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
2201a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
2301a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
2401a6c311SAlfredo Cardigliano 		.pending_work = true,
2501a6c311SAlfredo Cardigliano 		.cmd.q_control = {
2601a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
2701a6c311SAlfredo Cardigliano 			.type = q->type,
28*09f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
2901a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
3001a6c311SAlfredo Cardigliano 		},
3101a6c311SAlfredo Cardigliano 	};
3201a6c311SAlfredo Cardigliano 
3301a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
3401a6c311SAlfredo Cardigliano }
3501a6c311SAlfredo Cardigliano 
3601a6c311SAlfredo Cardigliano int
3701a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
3801a6c311SAlfredo Cardigliano {
3901a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
4001a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
4101a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
4201a6c311SAlfredo Cardigliano 		.pending_work = true,
4301a6c311SAlfredo Cardigliano 		.cmd.q_control = {
4401a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
4501a6c311SAlfredo Cardigliano 			.type = q->type,
46*09f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
4701a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
4801a6c311SAlfredo Cardigliano 		},
4901a6c311SAlfredo Cardigliano 	};
5001a6c311SAlfredo Cardigliano 
5101a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
5201a6c311SAlfredo Cardigliano }
5301a6c311SAlfredo Cardigliano 
54be63459eSAndrew Boyer void
55be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
56598f6726SAlfredo Cardigliano {
57a0a99f21SAndrew Boyer 	uint32_t i;
58a0a99f21SAndrew Boyer 
59be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
60598f6726SAlfredo Cardigliano 
61be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
62a0a99f21SAndrew Boyer 
63a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
64a0a99f21SAndrew Boyer 		struct ionic_qcq *rxq = lif->rxqcqs[i];
65a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
66a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
67a0a99f21SAndrew Boyer 	}
68a0a99f21SAndrew Boyer 
69a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
70a0a99f21SAndrew Boyer 		struct ionic_qcq *txq = lif->txqcqs[i];
71a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
72a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
73a0a99f21SAndrew Boyer 	}
74598f6726SAlfredo Cardigliano }
75598f6726SAlfredo Cardigliano 
76598f6726SAlfredo Cardigliano void
77598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
78598f6726SAlfredo Cardigliano {
79598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
8075f96902SAndrew Boyer 	int err;
81598f6726SAlfredo Cardigliano 
82598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
83598f6726SAlfredo Cardigliano 
8400b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
8575f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
8675f96902SAndrew Boyer 	if (err)
874ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
88598f6726SAlfredo Cardigliano }
89598f6726SAlfredo Cardigliano 
903cdfd905SAlfredo Cardigliano static void
913cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
923cdfd905SAlfredo Cardigliano {
933cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
943cdfd905SAlfredo Cardigliano 	uint32_t i;
953cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
963cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
973cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
983cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
993cdfd905SAlfredo Cardigliano 
1003cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1013cdfd905SAlfredo Cardigliano 
1023cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1033cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1043cdfd905SAlfredo Cardigliano 			lif->port_id);
1053cdfd905SAlfredo Cardigliano 		return;
1063cdfd905SAlfredo Cardigliano 	}
1073cdfd905SAlfredo Cardigliano 
1083cdfd905SAlfredo Cardigliano 	/* RX */
1093cdfd905SAlfredo Cardigliano 
1103cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1113cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1123cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1133cdfd905SAlfredo Cardigliano 
1143cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1153cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1163cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1173cdfd905SAlfredo Cardigliano 
1183cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1193cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1203cdfd905SAlfredo Cardigliano 		stats->imissed +=
1213cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1223cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1233cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1243cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1253cdfd905SAlfredo Cardigliano 	}
1263cdfd905SAlfredo Cardigliano 
1273cdfd905SAlfredo Cardigliano 	stats->imissed +=
1283cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1293cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1303cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1313cdfd905SAlfredo Cardigliano 
1323cdfd905SAlfredo Cardigliano 	stats->imissed +=
1333cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
1343cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1353cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
1363cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1373cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1383cdfd905SAlfredo Cardigliano 
1393cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
1403cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1413cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1423cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1433cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1443cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1453cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1463cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1473cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1483cdfd905SAlfredo Cardigliano 	}
1493cdfd905SAlfredo Cardigliano 
1503cdfd905SAlfredo Cardigliano 	/* TX */
1513cdfd905SAlfredo Cardigliano 
1523cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1533cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1543cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1553cdfd905SAlfredo Cardigliano 
1563cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1573cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1583cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1593cdfd905SAlfredo Cardigliano 
1603cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1613cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1623cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1633cdfd905SAlfredo Cardigliano 	}
1643cdfd905SAlfredo Cardigliano 
1653cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1663cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1673cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1683cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1693cdfd905SAlfredo Cardigliano 
1703cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1713cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1723cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1733cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1743cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1753cdfd905SAlfredo Cardigliano 
1763cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
1773cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1783cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1793cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1803cdfd905SAlfredo Cardigliano 	}
1813cdfd905SAlfredo Cardigliano }
1823cdfd905SAlfredo Cardigliano 
1833cdfd905SAlfredo Cardigliano void
1843cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1853cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1863cdfd905SAlfredo Cardigliano {
1873cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1883cdfd905SAlfredo Cardigliano 
1893cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1903cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1913cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1923cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1933cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1943cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1953cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1963cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1973cdfd905SAlfredo Cardigliano }
1983cdfd905SAlfredo Cardigliano 
1993cdfd905SAlfredo Cardigliano void
2003cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2013cdfd905SAlfredo Cardigliano {
2023cdfd905SAlfredo Cardigliano 	uint32_t i;
2033cdfd905SAlfredo Cardigliano 
2043cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
2053cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
2063cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
2073cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 0,
2083cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2093cdfd905SAlfredo Cardigliano 	}
2103cdfd905SAlfredo Cardigliano 
2113cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2123cdfd905SAlfredo Cardigliano }
2133cdfd905SAlfredo Cardigliano 
2143cdfd905SAlfredo Cardigliano void
2153cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2163cdfd905SAlfredo Cardigliano {
2173cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2183cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2193cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2203cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2213cdfd905SAlfredo Cardigliano 
2223cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2233cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2243cdfd905SAlfredo Cardigliano }
2253cdfd905SAlfredo Cardigliano 
2263cdfd905SAlfredo Cardigliano void
2273cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2283cdfd905SAlfredo Cardigliano {
2293cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2303cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2313cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2323cdfd905SAlfredo Cardigliano 
2333cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2343cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2353cdfd905SAlfredo Cardigliano }
2363cdfd905SAlfredo Cardigliano 
237598f6726SAlfredo Cardigliano static int
23854fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
239598f6726SAlfredo Cardigliano {
24054fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
24154fe083fSAlfredo Cardigliano 		.pending_work = true,
24254fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
24354fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
244*09f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_MAC),
24554fe083fSAlfredo Cardigliano 		},
24654fe083fSAlfredo Cardigliano 	};
24754fe083fSAlfredo Cardigliano 	int err;
24854fe083fSAlfredo Cardigliano 
24954fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
25054fe083fSAlfredo Cardigliano 
25154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
25254fe083fSAlfredo Cardigliano 	if (err)
25354fe083fSAlfredo Cardigliano 		return err;
25454fe083fSAlfredo Cardigliano 
25554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
256*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
25754fe083fSAlfredo Cardigliano 
25854fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25954fe083fSAlfredo Cardigliano }
26054fe083fSAlfredo Cardigliano 
26154fe083fSAlfredo Cardigliano static int
26254fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
26354fe083fSAlfredo Cardigliano {
26454fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
26554fe083fSAlfredo Cardigliano 		.pending_work = true,
26654fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
26754fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
26854fe083fSAlfredo Cardigliano 		},
26954fe083fSAlfredo Cardigliano 	};
27054fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
27154fe083fSAlfredo Cardigliano 	int err;
27254fe083fSAlfredo Cardigliano 
27354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
27454fe083fSAlfredo Cardigliano 
27554fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
27654fe083fSAlfredo Cardigliano 
27754fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
27854fe083fSAlfredo Cardigliano 	if (!f) {
27954fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
28054fe083fSAlfredo Cardigliano 		return -ENOENT;
28154fe083fSAlfredo Cardigliano 	}
28254fe083fSAlfredo Cardigliano 
283*09f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
28454fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
28554fe083fSAlfredo Cardigliano 
28654fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
28754fe083fSAlfredo Cardigliano 
28854fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28954fe083fSAlfredo Cardigliano 	if (err)
29054fe083fSAlfredo Cardigliano 		return err;
29154fe083fSAlfredo Cardigliano 
29254fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
293*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
294598f6726SAlfredo Cardigliano 
295598f6726SAlfredo Cardigliano 	return 0;
296598f6726SAlfredo Cardigliano }
297598f6726SAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano int
29954fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
30054fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
30154fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
302598f6726SAlfredo Cardigliano {
30354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30454fe083fSAlfredo Cardigliano 
30554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30654fe083fSAlfredo Cardigliano 
30754fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
30854fe083fSAlfredo Cardigliano }
30954fe083fSAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano void
31175f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
31254fe083fSAlfredo Cardigliano {
31354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31454fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
31575f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
31654fe083fSAlfredo Cardigliano 
31754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31854fe083fSAlfredo Cardigliano 
31954fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
32054fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
32154fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
32254fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
32354fe083fSAlfredo Cardigliano 		return;
32454fe083fSAlfredo Cardigliano 	}
32554fe083fSAlfredo Cardigliano 
32675f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
32775f96902SAndrew Boyer 
32875f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32954fe083fSAlfredo Cardigliano 		return;
33054fe083fSAlfredo Cardigliano 
33175f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
33254fe083fSAlfredo Cardigliano }
33354fe083fSAlfredo Cardigliano 
33454fe083fSAlfredo Cardigliano int
33554fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
33654fe083fSAlfredo Cardigliano {
33754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
33854fe083fSAlfredo Cardigliano 
33954fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
34054fe083fSAlfredo Cardigliano 
34154fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
34254fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
34354fe083fSAlfredo Cardigliano 		return -1;
34454fe083fSAlfredo Cardigliano 	}
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
34754fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
34854fe083fSAlfredo Cardigliano 			lif->mac_addr);
34954fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
35054fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
35154fe083fSAlfredo Cardigliano 	}
35254fe083fSAlfredo Cardigliano 
35354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
35454fe083fSAlfredo Cardigliano 
35554fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
35654fe083fSAlfredo Cardigliano 
35754fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
35854fe083fSAlfredo Cardigliano }
35954fe083fSAlfredo Cardigliano 
36054fe083fSAlfredo Cardigliano static int
36154fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
36254fe083fSAlfredo Cardigliano {
36354fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
36454fe083fSAlfredo Cardigliano 		.pending_work = true,
36554fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
36654fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
367*09f806e9SAndrew Boyer 			.match = rte_cpu_to_le_16(IONIC_RX_FILTER_MATCH_VLAN),
368*09f806e9SAndrew Boyer 			.vlan.vlan = rte_cpu_to_le_16(vid),
36954fe083fSAlfredo Cardigliano 		},
37054fe083fSAlfredo Cardigliano 	};
37154fe083fSAlfredo Cardigliano 	int err;
37254fe083fSAlfredo Cardigliano 
37354fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
37454fe083fSAlfredo Cardigliano 	if (err)
37554fe083fSAlfredo Cardigliano 		return err;
37654fe083fSAlfredo Cardigliano 
37754fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
378*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.comp.rx_filter_add.filter_id));
37954fe083fSAlfredo Cardigliano 
38054fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
38154fe083fSAlfredo Cardigliano }
38254fe083fSAlfredo Cardigliano 
38354fe083fSAlfredo Cardigliano static int
38454fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
38554fe083fSAlfredo Cardigliano {
38654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
38754fe083fSAlfredo Cardigliano 		.pending_work = true,
38854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
39054fe083fSAlfredo Cardigliano 		},
39154fe083fSAlfredo Cardigliano 	};
39254fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
39354fe083fSAlfredo Cardigliano 	int err;
39454fe083fSAlfredo Cardigliano 
39554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
39654fe083fSAlfredo Cardigliano 
39754fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
39854fe083fSAlfredo Cardigliano 
39954fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
40054fe083fSAlfredo Cardigliano 	if (!f) {
40154fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
40254fe083fSAlfredo Cardigliano 		return -ENOENT;
40354fe083fSAlfredo Cardigliano 	}
40454fe083fSAlfredo Cardigliano 
405*09f806e9SAndrew Boyer 	ctx.cmd.rx_filter_del.filter_id = rte_cpu_to_le_32(f->filter_id);
40654fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
40754fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
40854fe083fSAlfredo Cardigliano 
40954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
41054fe083fSAlfredo Cardigliano 	if (err)
41154fe083fSAlfredo Cardigliano 		return err;
41254fe083fSAlfredo Cardigliano 
41354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
414*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ctx.cmd.rx_filter_del.filter_id));
415598f6726SAlfredo Cardigliano 
416598f6726SAlfredo Cardigliano 	return 0;
417598f6726SAlfredo Cardigliano }
418598f6726SAlfredo Cardigliano 
41954fe083fSAlfredo Cardigliano int
42054fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
42154fe083fSAlfredo Cardigliano 		int on)
42254fe083fSAlfredo Cardigliano {
42354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
42454fe083fSAlfredo Cardigliano 	int err;
42554fe083fSAlfredo Cardigliano 
42654fe083fSAlfredo Cardigliano 	if (on)
42754fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
42854fe083fSAlfredo Cardigliano 	else
42954fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
43054fe083fSAlfredo Cardigliano 
43154fe083fSAlfredo Cardigliano 	return err;
43254fe083fSAlfredo Cardigliano }
43354fe083fSAlfredo Cardigliano 
434598f6726SAlfredo Cardigliano static void
435598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
436598f6726SAlfredo Cardigliano {
437598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
438598f6726SAlfredo Cardigliano 		.pending_work = true,
439598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
440598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
441*09f806e9SAndrew Boyer 			.rx_mode = rte_cpu_to_le_16(rx_mode),
442598f6726SAlfredo Cardigliano 		},
443598f6726SAlfredo Cardigliano 	};
444598f6726SAlfredo Cardigliano 	int err;
445598f6726SAlfredo Cardigliano 
446598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
448598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
450598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
452598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
454598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
455598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
456598f6726SAlfredo Cardigliano 
457598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
458598f6726SAlfredo Cardigliano 	if (err)
459598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
460598f6726SAlfredo Cardigliano }
461598f6726SAlfredo Cardigliano 
462598f6726SAlfredo Cardigliano static void
463598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
464598f6726SAlfredo Cardigliano {
465598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
466598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
467598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
468598f6726SAlfredo Cardigliano 	}
469598f6726SAlfredo Cardigliano }
470598f6726SAlfredo Cardigliano 
47154fe083fSAlfredo Cardigliano int
47254fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
47354fe083fSAlfredo Cardigliano {
47454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
47554fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
47654fe083fSAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
47854fe083fSAlfredo Cardigliano 
47954fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
48054fe083fSAlfredo Cardigliano 
48154fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48254fe083fSAlfredo Cardigliano 
48354fe083fSAlfredo Cardigliano 	return 0;
48454fe083fSAlfredo Cardigliano }
48554fe083fSAlfredo Cardigliano 
48654fe083fSAlfredo Cardigliano int
48754fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
48854fe083fSAlfredo Cardigliano {
48954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49054fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
49354fe083fSAlfredo Cardigliano 
49454fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49554fe083fSAlfredo Cardigliano 
49654fe083fSAlfredo Cardigliano 	return 0;
49754fe083fSAlfredo Cardigliano }
49854fe083fSAlfredo Cardigliano 
49954fe083fSAlfredo Cardigliano int
50054fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
50154fe083fSAlfredo Cardigliano {
50254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50354fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
50654fe083fSAlfredo Cardigliano 
50754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50854fe083fSAlfredo Cardigliano 
50954fe083fSAlfredo Cardigliano 	return 0;
51054fe083fSAlfredo Cardigliano }
51154fe083fSAlfredo Cardigliano 
51254fe083fSAlfredo Cardigliano int
51354fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
51454fe083fSAlfredo Cardigliano {
51554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51954fe083fSAlfredo Cardigliano 
52054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52154fe083fSAlfredo Cardigliano 
52254fe083fSAlfredo Cardigliano 	return 0;
52354fe083fSAlfredo Cardigliano }
524598f6726SAlfredo Cardigliano 
525598f6726SAlfredo Cardigliano int
526598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
527598f6726SAlfredo Cardigliano {
528598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
529598f6726SAlfredo Cardigliano 		.pending_work = true,
530598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
531598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
532598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
533*09f806e9SAndrew Boyer 			.mtu = rte_cpu_to_le_32(new_mtu),
534598f6726SAlfredo Cardigliano 		},
535598f6726SAlfredo Cardigliano 	};
536598f6726SAlfredo Cardigliano 	int err;
537598f6726SAlfredo Cardigliano 
538598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
539598f6726SAlfredo Cardigliano 	if (err)
540598f6726SAlfredo Cardigliano 		return err;
541598f6726SAlfredo Cardigliano 
542598f6726SAlfredo Cardigliano 	return 0;
543598f6726SAlfredo Cardigliano }
544598f6726SAlfredo Cardigliano 
545598f6726SAlfredo Cardigliano int
54601a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
54701a6c311SAlfredo Cardigliano {
54801a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
54901a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
55001a6c311SAlfredo Cardigliano 	unsigned long index;
55101a6c311SAlfredo Cardigliano 
55201a6c311SAlfredo Cardigliano 	/*
55301a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55401a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5554ae96cb8SAndrew Boyer 	 * which has index = 0)
55601a6c311SAlfredo Cardigliano 	 */
55701a6c311SAlfredo Cardigliano 
55801a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
55901a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
56001a6c311SAlfredo Cardigliano 			break;
56101a6c311SAlfredo Cardigliano 
56201a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56301a6c311SAlfredo Cardigliano 		return -ENOSPC;
56401a6c311SAlfredo Cardigliano 
56501a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
56601a6c311SAlfredo Cardigliano 
56701a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
56801a6c311SAlfredo Cardigliano 
56901a6c311SAlfredo Cardigliano 	return 0;
57001a6c311SAlfredo Cardigliano }
57101a6c311SAlfredo Cardigliano 
57201a6c311SAlfredo Cardigliano void
57301a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
57401a6c311SAlfredo Cardigliano {
5754c8f8d57SAndrew Boyer 	if (intr->index != IONIC_INTR_NONE)
57601a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
57701a6c311SAlfredo Cardigliano }
57801a6c311SAlfredo Cardigliano 
57901a6c311SAlfredo Cardigliano static int
58001a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
58101a6c311SAlfredo Cardigliano 		uint32_t index,
58201a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
58301a6c311SAlfredo Cardigliano 		uint32_t num_descs,
58401a6c311SAlfredo Cardigliano 		uint32_t desc_size,
58501a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
58601a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
5871abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
58801a6c311SAlfredo Cardigliano {
58901a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
59001a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
59101a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59201a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
59301a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59401a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59501a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59601a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
59701a6c311SAlfredo Cardigliano 	int err;
59801a6c311SAlfredo Cardigliano 
59901a6c311SAlfredo Cardigliano 	*qcq = NULL;
60001a6c311SAlfredo Cardigliano 
60101a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60201a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60301a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60401a6c311SAlfredo Cardigliano 
60501a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
60601a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
60701a6c311SAlfredo Cardigliano 	/*
60801a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
60901a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
61001a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
61101a6c311SAlfredo Cardigliano 	 */
61201a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
61301a6c311SAlfredo Cardigliano 
61401a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61501a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
61601a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
61701a6c311SAlfredo Cardigliano 	}
61801a6c311SAlfredo Cardigliano 
61901a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
62001a6c311SAlfredo Cardigliano 	if (!new) {
62101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62201a6c311SAlfredo Cardigliano 		return -ENOMEM;
62301a6c311SAlfredo Cardigliano 	}
62401a6c311SAlfredo Cardigliano 
62501a6c311SAlfredo Cardigliano 	new->lif = lif;
62601a6c311SAlfredo Cardigliano 	new->flags = flags;
62701a6c311SAlfredo Cardigliano 
62801a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
62901a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
6314c8f8d57SAndrew Boyer 		err = -ENOMEM;
6324c8f8d57SAndrew Boyer 		goto err_out_free_qcq;
63301a6c311SAlfredo Cardigliano 	}
63401a6c311SAlfredo Cardigliano 
63501a6c311SAlfredo Cardigliano 	new->q.type = type;
63601a6c311SAlfredo Cardigliano 
63701a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
6381abf69fcSAndrew Boyer 		desc_size, sg_desc_size);
63901a6c311SAlfredo Cardigliano 	if (err) {
64001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
6414c8f8d57SAndrew Boyer 		goto err_out_free_info;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
6444c8f8d57SAndrew Boyer 	err = ionic_cq_init(lif, &new->cq, num_descs, cq_desc_size);
64501a6c311SAlfredo Cardigliano 	if (err) {
64601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
6474c8f8d57SAndrew Boyer 		goto err_out_free_info;
64801a6c311SAlfredo Cardigliano 	}
64901a6c311SAlfredo Cardigliano 
65001a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
65101a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
65201a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
65301a6c311SAlfredo Cardigliano 
65401a6c311SAlfredo Cardigliano 	if (!new->base_z) {
65501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
65601a6c311SAlfredo Cardigliano 		err = -ENOMEM;
6574c8f8d57SAndrew Boyer 		goto err_out_free_info;
65801a6c311SAlfredo Cardigliano 	}
65901a6c311SAlfredo Cardigliano 
66001a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
66101a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
66201a6c311SAlfredo Cardigliano 	new->total_size = total_size;
66301a6c311SAlfredo Cardigliano 
66401a6c311SAlfredo Cardigliano 	q_base = new->base;
66501a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
66601a6c311SAlfredo Cardigliano 
66701a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
66801a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
66901a6c311SAlfredo Cardigliano 
67001a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
67101a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
67201a6c311SAlfredo Cardigliano 			PAGE_SIZE);
67301a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
67401a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
67501a6c311SAlfredo Cardigliano 	}
67601a6c311SAlfredo Cardigliano 
6774ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6784ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
67901a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68001a6c311SAlfredo Cardigliano 
68101a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
68201a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
68301a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
68401a6c311SAlfredo Cardigliano 
68501a6c311SAlfredo Cardigliano 	*qcq = new;
68601a6c311SAlfredo Cardigliano 
68701a6c311SAlfredo Cardigliano 	return 0;
68801a6c311SAlfredo Cardigliano 
6894c8f8d57SAndrew Boyer err_out_free_info:
6904c8f8d57SAndrew Boyer 	rte_free(new->q.info);
6914c8f8d57SAndrew Boyer err_out_free_qcq:
6924c8f8d57SAndrew Boyer 	rte_free(new);
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	return err;
69501a6c311SAlfredo Cardigliano }
69601a6c311SAlfredo Cardigliano 
69701a6c311SAlfredo Cardigliano void
69801a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
69901a6c311SAlfredo Cardigliano {
70001a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70101a6c311SAlfredo Cardigliano 		qcq->base = NULL;
70201a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
70301a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
70401a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
70501a6c311SAlfredo Cardigliano 	}
70601a6c311SAlfredo Cardigliano 
70701a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
70801a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
70901a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71001a6c311SAlfredo Cardigliano 	}
71101a6c311SAlfredo Cardigliano 
71201a6c311SAlfredo Cardigliano 	rte_free(qcq);
71301a6c311SAlfredo Cardigliano }
71401a6c311SAlfredo Cardigliano 
715a27d9013SAlfredo Cardigliano int
716a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
717a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
718a27d9013SAlfredo Cardigliano {
719a27d9013SAlfredo Cardigliano 	uint32_t flags;
720a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
721a27d9013SAlfredo Cardigliano 
722a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
723a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags,
724a27d9013SAlfredo Cardigliano 		nrxq_descs,
725a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
726a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
727a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
7281abf69fcSAndrew Boyer 		&lif->rxqcqs[index]);
729a27d9013SAlfredo Cardigliano 	if (err)
730a27d9013SAlfredo Cardigliano 		return err;
731a27d9013SAlfredo Cardigliano 
732a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
733a27d9013SAlfredo Cardigliano 
734a27d9013SAlfredo Cardigliano 	return 0;
735a27d9013SAlfredo Cardigliano }
736a27d9013SAlfredo Cardigliano 
737a27d9013SAlfredo Cardigliano int
738a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
739a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
740a27d9013SAlfredo Cardigliano {
741a27d9013SAlfredo Cardigliano 	uint32_t flags;
742a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
743a27d9013SAlfredo Cardigliano 
744a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
745a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
746a27d9013SAlfredo Cardigliano 		ntxq_descs,
747a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
748a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
749a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_sg_desc),
7501abf69fcSAndrew Boyer 		&lif->txqcqs[index]);
751a27d9013SAlfredo Cardigliano 	if (err)
752a27d9013SAlfredo Cardigliano 		return err;
753a27d9013SAlfredo Cardigliano 
754a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
755a27d9013SAlfredo Cardigliano 
756a27d9013SAlfredo Cardigliano 	return 0;
757a27d9013SAlfredo Cardigliano }
758a27d9013SAlfredo Cardigliano 
75901a6c311SAlfredo Cardigliano static int
76001a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
76101a6c311SAlfredo Cardigliano {
76201a6c311SAlfredo Cardigliano 	uint32_t flags;
76301a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
76401a6c311SAlfredo Cardigliano 
76501a6c311SAlfredo Cardigliano 	flags = 0;
76601a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
76701a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
76801a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
76901a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
77001a6c311SAlfredo Cardigliano 		0,
7711abf69fcSAndrew Boyer 		&lif->adminqcq);
77227b942c8SAlfredo Cardigliano 	if (err)
77327b942c8SAlfredo Cardigliano 		return err;
77401a6c311SAlfredo Cardigliano 
77527b942c8SAlfredo Cardigliano 	return 0;
77627b942c8SAlfredo Cardigliano }
77727b942c8SAlfredo Cardigliano 
77827b942c8SAlfredo Cardigliano static int
77927b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
78027b942c8SAlfredo Cardigliano {
7814c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq;
7824c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
7834c8f8d57SAndrew Boyer 	uint32_t flags = 0;
78427b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
78527b942c8SAlfredo Cardigliano 
78627b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
78727b942c8SAlfredo Cardigliano 		flags,
78827b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
78927b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
79027b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
79127b942c8SAlfredo Cardigliano 		0,
7924c8f8d57SAndrew Boyer 		&nqcq);
79301a6c311SAlfredo Cardigliano 	if (err)
79401a6c311SAlfredo Cardigliano 		return err;
79501a6c311SAlfredo Cardigliano 
7964c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
7974c8f8d57SAndrew Boyer 	if (err) {
7984c8f8d57SAndrew Boyer 		ionic_qcq_free(nqcq);
7994c8f8d57SAndrew Boyer 		return err;
8004c8f8d57SAndrew Boyer 	}
8014c8f8d57SAndrew Boyer 
8024c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
8034c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
8044c8f8d57SAndrew Boyer 
8054c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
8064c8f8d57SAndrew Boyer 
80701a6c311SAlfredo Cardigliano 	return 0;
80801a6c311SAlfredo Cardigliano }
80901a6c311SAlfredo Cardigliano 
810c67719e1SAlfredo Cardigliano static void *
811c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
812c67719e1SAlfredo Cardigliano {
813c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
814c67719e1SAlfredo Cardigliano 
815c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
816c67719e1SAlfredo Cardigliano 		return NULL;
817c67719e1SAlfredo Cardigliano 
818c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
819c67719e1SAlfredo Cardigliano }
820c67719e1SAlfredo Cardigliano 
821669c8de6SAlfredo Cardigliano int
822669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
823669c8de6SAlfredo Cardigliano {
824c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
825669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
82601a6c311SAlfredo Cardigliano 	int err;
827669c8de6SAlfredo Cardigliano 
8284ae96cb8SAndrew Boyer 	/*
8294ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
8304ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
8314ae96cb8SAndrew Boyer 	 */
8324ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
8334ae96cb8SAndrew Boyer 
8344ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
835669c8de6SAlfredo Cardigliano 
836669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
837669c8de6SAlfredo Cardigliano 
83801a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
83901a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
84001a6c311SAlfredo Cardigliano 
84100b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
842c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
843c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
844c67719e1SAlfredo Cardigliano 		return -ENOMEM;
845c67719e1SAlfredo Cardigliano 	}
846c67719e1SAlfredo Cardigliano 
847a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
848a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
849a27d9013SAlfredo Cardigliano 
850a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
851a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
852a27d9013SAlfredo Cardigliano 		return -ENOMEM;
853a27d9013SAlfredo Cardigliano 	}
854a27d9013SAlfredo Cardigliano 
855a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
856a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
857a27d9013SAlfredo Cardigliano 
858a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
859a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
860a27d9013SAlfredo Cardigliano 		return -ENOMEM;
861a27d9013SAlfredo Cardigliano 	}
862a27d9013SAlfredo Cardigliano 
86327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
86427b942c8SAlfredo Cardigliano 
86527b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
86627b942c8SAlfredo Cardigliano 	if (err) {
86727b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
86827b942c8SAlfredo Cardigliano 		return err;
86927b942c8SAlfredo Cardigliano 	}
87027b942c8SAlfredo Cardigliano 
87127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
87227b942c8SAlfredo Cardigliano 
87301a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
87401a6c311SAlfredo Cardigliano 	if (err) {
87501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
87601a6c311SAlfredo Cardigliano 		return err;
87701a6c311SAlfredo Cardigliano 	}
87801a6c311SAlfredo Cardigliano 
87901a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
88001a6c311SAlfredo Cardigliano 
881669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
882669c8de6SAlfredo Cardigliano 
883669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
884669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
885669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
886669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
887669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
888669c8de6SAlfredo Cardigliano 		return -ENOMEM;
889669c8de6SAlfredo Cardigliano 	}
890669c8de6SAlfredo Cardigliano 
891669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
892669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
893669c8de6SAlfredo Cardigliano 
894669c8de6SAlfredo Cardigliano 	return 0;
895669c8de6SAlfredo Cardigliano }
896669c8de6SAlfredo Cardigliano 
897669c8de6SAlfredo Cardigliano void
898669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
899669c8de6SAlfredo Cardigliano {
90027b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
90127b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
90227b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
90327b942c8SAlfredo Cardigliano 	}
90427b942c8SAlfredo Cardigliano 
90501a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
90601a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
90701a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
90801a6c311SAlfredo Cardigliano 	}
90901a6c311SAlfredo Cardigliano 
910a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
911a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
912a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
913a27d9013SAlfredo Cardigliano 	}
914a27d9013SAlfredo Cardigliano 
915a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
916a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
917a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
918a27d9013SAlfredo Cardigliano 	}
919a27d9013SAlfredo Cardigliano 
920669c8de6SAlfredo Cardigliano 	if (lif->info) {
921669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
922669c8de6SAlfredo Cardigliano 		lif->info = NULL;
923669c8de6SAlfredo Cardigliano 	}
924669c8de6SAlfredo Cardigliano }
925669c8de6SAlfredo Cardigliano 
926175e4e7eSAndrew Boyer void
927175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
928175e4e7eSAndrew Boyer {
929175e4e7eSAndrew Boyer 	uint32_t i;
930175e4e7eSAndrew Boyer 
931175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
932175e4e7eSAndrew Boyer 		ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]);
933175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
934175e4e7eSAndrew Boyer 	}
935175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
936175e4e7eSAndrew Boyer 		ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]);
937175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
938175e4e7eSAndrew Boyer 	}
939175e4e7eSAndrew Boyer }
940175e4e7eSAndrew Boyer 
94122e7171bSAlfredo Cardigliano int
94222e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
94322e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
94422e7171bSAlfredo Cardigliano {
945*09f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
94622e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
94722e7171bSAlfredo Cardigliano 		.pending_work = true,
94822e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
94922e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
95022e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
951*09f806e9SAndrew Boyer 			.rss.types = rte_cpu_to_le_16(types),
952*09f806e9SAndrew Boyer 			.rss.addr = rte_cpu_to_le_64(lif->rss_ind_tbl_pa),
95322e7171bSAlfredo Cardigliano 		},
95422e7171bSAlfredo Cardigliano 	};
95522e7171bSAlfredo Cardigliano 	unsigned int i;
956*09f806e9SAndrew Boyer 	uint16_t tbl_sz =
957*09f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
95822e7171bSAlfredo Cardigliano 
95922e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
96022e7171bSAlfredo Cardigliano 
96122e7171bSAlfredo Cardigliano 	lif->rss_types = types;
96222e7171bSAlfredo Cardigliano 
96322e7171bSAlfredo Cardigliano 	if (key)
96422e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
96522e7171bSAlfredo Cardigliano 
96622e7171bSAlfredo Cardigliano 	if (indir)
967*09f806e9SAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
96822e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
96922e7171bSAlfredo Cardigliano 
97022e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
97122e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
97222e7171bSAlfredo Cardigliano 
97322e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
97422e7171bSAlfredo Cardigliano }
97522e7171bSAlfredo Cardigliano 
97622e7171bSAlfredo Cardigliano static int
97722e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
97822e7171bSAlfredo Cardigliano {
979*09f806e9SAndrew Boyer 	struct ionic_adapter *adapter = lif->adapter;
98022e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
98122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98622e7171bSAlfredo Cardigliano 	};
98722e7171bSAlfredo Cardigliano 	uint32_t i;
988*09f806e9SAndrew Boyer 	uint16_t tbl_sz =
989*09f806e9SAndrew Boyer 		rte_le_to_cpu_16(adapter->ident.lif.eth.rss_ind_tbl_sz);
99022e7171bSAlfredo Cardigliano 
99122e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
99222e7171bSAlfredo Cardigliano 
9933d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
99422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
9953d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
9963d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
9973d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
99822e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
99922e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
100022e7171bSAlfredo Cardigliano 			return -ENOMEM;
100122e7171bSAlfredo Cardigliano 		}
100222e7171bSAlfredo Cardigliano 
100322e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
100422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
10053d845eddSAndrew Boyer 	}
10063d845eddSAndrew Boyer 
10073d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
10083d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
100922e7171bSAlfredo Cardigliano 
101022e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
10113d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
101222e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
10133d845eddSAndrew Boyer 	}
101422e7171bSAlfredo Cardigliano 
10153d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
101622e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
101722e7171bSAlfredo Cardigliano }
101822e7171bSAlfredo Cardigliano 
101922e7171bSAlfredo Cardigliano static void
102022e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
102122e7171bSAlfredo Cardigliano {
102222e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
102322e7171bSAlfredo Cardigliano 		return;
102422e7171bSAlfredo Cardigliano 
102522e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
102622e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
102722e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
102822e7171bSAlfredo Cardigliano 
102922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
103022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
103122e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
103222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
103322e7171bSAlfredo Cardigliano 	}
103422e7171bSAlfredo Cardigliano }
103522e7171bSAlfredo Cardigliano 
103601a6c311SAlfredo Cardigliano static void
10374c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq)
103801a6c311SAlfredo Cardigliano {
103901a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
104001a6c311SAlfredo Cardigliano }
104101a6c311SAlfredo Cardigliano 
1042a27d9013SAlfredo Cardigliano void
1043a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1044a27d9013SAlfredo Cardigliano {
10454c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
1046a27d9013SAlfredo Cardigliano }
1047a27d9013SAlfredo Cardigliano 
1048a27d9013SAlfredo Cardigliano void
1049a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1050a27d9013SAlfredo Cardigliano {
10514c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
10524c8f8d57SAndrew Boyer }
10534c8f8d57SAndrew Boyer 
10544c8f8d57SAndrew Boyer static void
10554c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
10564c8f8d57SAndrew Boyer {
10574c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq = lif->notifyqcq;
10584c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
10594c8f8d57SAndrew Boyer 
10604c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
10614c8f8d57SAndrew Boyer 		return;
10624c8f8d57SAndrew Boyer 
10634c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
10644c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
10654c8f8d57SAndrew Boyer 
10664c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1067a27d9013SAlfredo Cardigliano }
1068a27d9013SAlfredo Cardigliano 
106901a6c311SAlfredo Cardigliano bool
107001a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
107101a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
107201a6c311SAlfredo Cardigliano {
107301a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
107401a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
107501a6c311SAlfredo Cardigliano 
107601a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
107701a6c311SAlfredo Cardigliano 		return false;
107801a6c311SAlfredo Cardigliano 
107901a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
108001a6c311SAlfredo Cardigliano 
108101a6c311SAlfredo Cardigliano 	return true;
108201a6c311SAlfredo Cardigliano }
108301a6c311SAlfredo Cardigliano 
108401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
108501a6c311SAlfredo Cardigliano int
108601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
108701a6c311SAlfredo Cardigliano 		void *cb_arg)
108801a6c311SAlfredo Cardigliano {
108901a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
109001a6c311SAlfredo Cardigliano 	uint32_t work_done;
109101a6c311SAlfredo Cardigliano 
109201a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
109301a6c311SAlfredo Cardigliano 
109401a6c311SAlfredo Cardigliano 	return work_done;
109501a6c311SAlfredo Cardigliano }
109601a6c311SAlfredo Cardigliano 
109727b942c8SAlfredo Cardigliano static void
109827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
109927b942c8SAlfredo Cardigliano {
110027b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
110127b942c8SAlfredo Cardigliano 	bool link_up;
110227b942c8SAlfredo Cardigliano 
110327b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
110427b942c8SAlfredo Cardigliano 
110527b942c8SAlfredo Cardigliano 	if (!lif->info)
110627b942c8SAlfredo Cardigliano 		return;
110727b942c8SAlfredo Cardigliano 
110827b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
110927b942c8SAlfredo Cardigliano 
111027b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
111127b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
111227b942c8SAlfredo Cardigliano 		return;
111327b942c8SAlfredo Cardigliano 
111427b942c8SAlfredo Cardigliano 	if (link_up) {
1115*09f806e9SAndrew Boyer 		adapter->link_speed =
1116*09f806e9SAndrew Boyer 			rte_le_to_cpu_32(lif->info->status.link_speed);
1117be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1118be63459eSAndrew Boyer 			adapter->link_speed);
111927b942c8SAlfredo Cardigliano 	} else {
112027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
112127b942c8SAlfredo Cardigliano 	}
112227b942c8SAlfredo Cardigliano 
112327b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1124be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1125be63459eSAndrew Boyer }
1126be63459eSAndrew Boyer 
1127be63459eSAndrew Boyer static void
1128be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1129be63459eSAndrew Boyer {
1130be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1131be63459eSAndrew Boyer 		return;
1132be63459eSAndrew Boyer 
1133be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1134be63459eSAndrew Boyer 
1135be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1136be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1137be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1138be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1139be63459eSAndrew Boyer 	}
1140be63459eSAndrew Boyer 
1141be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
114227b942c8SAlfredo Cardigliano }
114327b942c8SAlfredo Cardigliano 
114427b942c8SAlfredo Cardigliano static bool
114527b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
114627b942c8SAlfredo Cardigliano {
114727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
114827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
114927b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
115027b942c8SAlfredo Cardigliano 
115127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
115227b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
115327b942c8SAlfredo Cardigliano 
115427b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
115527b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
115627b942c8SAlfredo Cardigliano 		return false;
115727b942c8SAlfredo Cardigliano 
115827b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
115927b942c8SAlfredo Cardigliano 
116027b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
116127b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
116227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1163be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1164be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1165be63459eSAndrew Boyer 			lif->name,
116627b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
116727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
116827b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
116927b942c8SAlfredo Cardigliano 
117027b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
117127b942c8SAlfredo Cardigliano 		break;
1172be63459eSAndrew Boyer 
1173be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1174be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1175be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1176be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1177be63459eSAndrew Boyer 			lif->name,
1178be63459eSAndrew Boyer 			cq_desc->event.eid,
1179be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1180be63459eSAndrew Boyer 			cq_desc->reset.state);
1181be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1182be63459eSAndrew Boyer 		break;
1183be63459eSAndrew Boyer 
118427b942c8SAlfredo Cardigliano 	default:
118527b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
118627b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
118727b942c8SAlfredo Cardigliano 		break;
118827b942c8SAlfredo Cardigliano 	}
118927b942c8SAlfredo Cardigliano 
119027b942c8SAlfredo Cardigliano 	return true;
119127b942c8SAlfredo Cardigliano }
119227b942c8SAlfredo Cardigliano 
119327b942c8SAlfredo Cardigliano int
119427b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
119527b942c8SAlfredo Cardigliano {
119627b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
119727b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
119827b942c8SAlfredo Cardigliano 	uint32_t work_done;
119927b942c8SAlfredo Cardigliano 
120027b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
120127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
120227b942c8SAlfredo Cardigliano 		return -1;
120327b942c8SAlfredo Cardigliano 	}
120427b942c8SAlfredo Cardigliano 
120527b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
120627b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
120727b942c8SAlfredo Cardigliano 
120827b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
120927b942c8SAlfredo Cardigliano 
121027b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
121127b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
121227b942c8SAlfredo Cardigliano 
121327b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
121427b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
121527b942c8SAlfredo Cardigliano 
121627b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
121727b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
121827b942c8SAlfredo Cardigliano 
121927b942c8SAlfredo Cardigliano 	return 0;
122027b942c8SAlfredo Cardigliano }
122127b942c8SAlfredo Cardigliano 
122201a6c311SAlfredo Cardigliano static int
122301a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
122401a6c311SAlfredo Cardigliano {
122501a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
122601a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
122701a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
122801a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
122901a6c311SAlfredo Cardigliano 	int err;
123001a6c311SAlfredo Cardigliano 
12314c8f8d57SAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, qcq);
123201a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
123301a6c311SAlfredo Cardigliano 	if (err)
123401a6c311SAlfredo Cardigliano 		return err;
123501a6c311SAlfredo Cardigliano 
123601a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
123701a6c311SAlfredo Cardigliano 
123801a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
1239*09f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(comp.hw_index);
124001a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
124101a6c311SAlfredo Cardigliano 
124201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
124301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
124401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
124501a6c311SAlfredo Cardigliano 
124601a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
124701a6c311SAlfredo Cardigliano 
124801a6c311SAlfredo Cardigliano 	return 0;
124901a6c311SAlfredo Cardigliano }
125001a6c311SAlfredo Cardigliano 
125127b942c8SAlfredo Cardigliano static int
125227b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
125327b942c8SAlfredo Cardigliano {
125427b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
125527b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
125627b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
125727b942c8SAlfredo Cardigliano 	int err;
125827b942c8SAlfredo Cardigliano 
125927b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
126027b942c8SAlfredo Cardigliano 		.pending_work = true,
126127b942c8SAlfredo Cardigliano 		.cmd.q_init = {
126227b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
126327b942c8SAlfredo Cardigliano 			.type = q->type,
1264*09f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1265*09f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(qcq->intr.index),
1266*09f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_IRQ |
1267*09f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
126827b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1269*09f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
127027b942c8SAlfredo Cardigliano 		}
127127b942c8SAlfredo Cardigliano 	};
127227b942c8SAlfredo Cardigliano 
1273*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.index %d", q->index);
1274*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", q->base_pa);
127527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
127627b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
12774ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
127827b942c8SAlfredo Cardigliano 
127927b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
128027b942c8SAlfredo Cardigliano 	if (err)
128127b942c8SAlfredo Cardigliano 		return err;
128227b942c8SAlfredo Cardigliano 
128327b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1284*09f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
128527b942c8SAlfredo Cardigliano 	q->db = NULL;
128627b942c8SAlfredo Cardigliano 
128727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
128827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
128927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
129027b942c8SAlfredo Cardigliano 
129127b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
129227b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
129327b942c8SAlfredo Cardigliano 
129427b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
129527b942c8SAlfredo Cardigliano 
129627b942c8SAlfredo Cardigliano 	return 0;
129727b942c8SAlfredo Cardigliano }
129827b942c8SAlfredo Cardigliano 
1299669c8de6SAlfredo Cardigliano int
1300598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1301598f6726SAlfredo Cardigliano {
1302598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1303598f6726SAlfredo Cardigliano 		.pending_work = true,
1304598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1305598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1306598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1307*09f806e9SAndrew Boyer 			.features = rte_cpu_to_le_64(lif->features),
1308598f6726SAlfredo Cardigliano 		},
1309598f6726SAlfredo Cardigliano 	};
1310598f6726SAlfredo Cardigliano 	int err;
1311598f6726SAlfredo Cardigliano 
1312598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1313598f6726SAlfredo Cardigliano 	if (err)
1314598f6726SAlfredo Cardigliano 		return err;
1315598f6726SAlfredo Cardigliano 
1316*09f806e9SAndrew Boyer 	lif->hw_features = rte_le_to_cpu_64(ctx.cmd.lif_setattr.features &
1317598f6726SAlfredo Cardigliano 						ctx.comp.lif_setattr.features);
1318598f6726SAlfredo Cardigliano 
1319598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1320598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1321598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1322598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1323598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1324598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1325598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1326598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1327598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1328598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1329598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1330598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1331598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1332598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1333598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1334598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1335598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1336598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1337598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1338598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1339598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1340598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1341598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1342598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1343598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1344598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1345598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1346598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1347598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1348598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1349598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1350598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1351598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1352598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1353598f6726SAlfredo Cardigliano 
1354598f6726SAlfredo Cardigliano 	return 0;
1355598f6726SAlfredo Cardigliano }
1356598f6726SAlfredo Cardigliano 
1357a27d9013SAlfredo Cardigliano int
1358a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1359a27d9013SAlfredo Cardigliano {
1360a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1361a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1362a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1363a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1364a27d9013SAlfredo Cardigliano 		.pending_work = true,
1365a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1366a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1367a27d9013SAlfredo Cardigliano 			.type = q->type,
1368*09f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1369*09f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
1370*09f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
1371*09f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1372a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1373*09f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
1374*09f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
1375*09f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1376a27d9013SAlfredo Cardigliano 		},
1377a27d9013SAlfredo Cardigliano 	};
1378a27d9013SAlfredo Cardigliano 	int err;
1379a27d9013SAlfredo Cardigliano 
1380*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.index %d", q->index);
1381*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1382a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1383a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13844ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1385a27d9013SAlfredo Cardigliano 
1386a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1387a27d9013SAlfredo Cardigliano 	if (err)
1388a27d9013SAlfredo Cardigliano 		return err;
1389a27d9013SAlfredo Cardigliano 
1390a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1391*09f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1392a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1393a27d9013SAlfredo Cardigliano 
1394a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1395a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1396a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1397a27d9013SAlfredo Cardigliano 
1398a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1399a27d9013SAlfredo Cardigliano 
1400a27d9013SAlfredo Cardigliano 	return 0;
1401a27d9013SAlfredo Cardigliano }
1402a27d9013SAlfredo Cardigliano 
1403a27d9013SAlfredo Cardigliano int
1404a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1405a27d9013SAlfredo Cardigliano {
1406a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1407a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1408a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1409a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1410a27d9013SAlfredo Cardigliano 		.pending_work = true,
1411a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1412a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1413a27d9013SAlfredo Cardigliano 			.type = q->type,
1414*09f806e9SAndrew Boyer 			.index = rte_cpu_to_le_32(q->index),
1415*09f806e9SAndrew Boyer 			.flags = rte_cpu_to_le_16(IONIC_QINIT_F_SG |
1416*09f806e9SAndrew Boyer 						IONIC_QINIT_F_ENA),
1417*09f806e9SAndrew Boyer 			.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE),
1418a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1419*09f806e9SAndrew Boyer 			.ring_base = rte_cpu_to_le_64(q->base_pa),
1420*09f806e9SAndrew Boyer 			.cq_ring_base = rte_cpu_to_le_64(cq->base_pa),
1421*09f806e9SAndrew Boyer 			.sg_ring_base = rte_cpu_to_le_64(q->sg_base_pa),
1422a27d9013SAlfredo Cardigliano 		},
1423a27d9013SAlfredo Cardigliano 	};
1424a27d9013SAlfredo Cardigliano 	int err;
1425a27d9013SAlfredo Cardigliano 
1426*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.index %d", q->index);
1427*09f806e9SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "", q->base_pa);
1428a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1429a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14304ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1431a27d9013SAlfredo Cardigliano 
1432a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1433a27d9013SAlfredo Cardigliano 	if (err)
1434a27d9013SAlfredo Cardigliano 		return err;
1435a27d9013SAlfredo Cardigliano 
1436a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1437*09f806e9SAndrew Boyer 	q->hw_index = rte_le_to_cpu_32(ctx.comp.q_init.hw_index);
1438a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1439a27d9013SAlfredo Cardigliano 
1440a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1441a27d9013SAlfredo Cardigliano 
1442a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1443a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1444a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1445a27d9013SAlfredo Cardigliano 
1446a27d9013SAlfredo Cardigliano 	return 0;
1447a27d9013SAlfredo Cardigliano }
1448a27d9013SAlfredo Cardigliano 
1449598f6726SAlfredo Cardigliano static int
1450598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1451598f6726SAlfredo Cardigliano {
1452598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1453598f6726SAlfredo Cardigliano 		.pending_work = true,
1454598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1455598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1456598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1457598f6726SAlfredo Cardigliano 		},
1458598f6726SAlfredo Cardigliano 	};
1459598f6726SAlfredo Cardigliano 	int err;
1460598f6726SAlfredo Cardigliano 
1461598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1462598f6726SAlfredo Cardigliano 
1463598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1464598f6726SAlfredo Cardigliano 	if (err)
1465598f6726SAlfredo Cardigliano 		return err;
1466598f6726SAlfredo Cardigliano 
1467598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1468598f6726SAlfredo Cardigliano 
1469598f6726SAlfredo Cardigliano 	return 0;
1470598f6726SAlfredo Cardigliano }
1471598f6726SAlfredo Cardigliano 
1472598f6726SAlfredo Cardigliano static void
1473598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1474598f6726SAlfredo Cardigliano {
1475598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1476598f6726SAlfredo Cardigliano 		.pending_work = true,
1477598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1478598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1479598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1480598f6726SAlfredo Cardigliano 		},
1481598f6726SAlfredo Cardigliano 	};
1482598f6726SAlfredo Cardigliano 
14834ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
14844ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1485598f6726SAlfredo Cardigliano 
1486598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1487598f6726SAlfredo Cardigliano }
1488598f6726SAlfredo Cardigliano 
1489598f6726SAlfredo Cardigliano int
1490669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1491669c8de6SAlfredo Cardigliano {
1492669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1493669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1494669c8de6SAlfredo Cardigliano 	int err;
1495669c8de6SAlfredo Cardigliano 
14963cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
14973cdfd905SAlfredo Cardigliano 
149800b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1499669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1500669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1501669c8de6SAlfredo Cardigliano 	if (err)
1502669c8de6SAlfredo Cardigliano 		return err;
1503669c8de6SAlfredo Cardigliano 
1504*09f806e9SAndrew Boyer 	lif->hw_index = rte_cpu_to_le_16(comp.hw_index);
1505669c8de6SAlfredo Cardigliano 
150601a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
150701a6c311SAlfredo Cardigliano 	if (err)
150801a6c311SAlfredo Cardigliano 		return err;
150901a6c311SAlfredo Cardigliano 
151027b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
151127b942c8SAlfredo Cardigliano 	if (err)
151227b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
151327b942c8SAlfredo Cardigliano 
151418a44465SAndrew Boyer 	/*
151518a44465SAndrew Boyer 	 * Configure initial feature set
151618a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
151718a44465SAndrew Boyer 	 */
151818a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1519598f6726SAlfredo Cardigliano 
1520598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1521598f6726SAlfredo Cardigliano 	if (err)
1522598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1523598f6726SAlfredo Cardigliano 
152454fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1525598f6726SAlfredo Cardigliano 	if (err)
1526598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1527598f6726SAlfredo Cardigliano 
152854fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
152954fe083fSAlfredo Cardigliano 	if (err)
153054fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
153154fe083fSAlfredo Cardigliano 
1532598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1533598f6726SAlfredo Cardigliano 
1534669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1535669c8de6SAlfredo Cardigliano 
1536669c8de6SAlfredo Cardigliano 	return 0;
153727b942c8SAlfredo Cardigliano 
153854fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
153954fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
154054fe083fSAlfredo Cardigliano 
1541598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
15424c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1543598f6726SAlfredo Cardigliano 
154427b942c8SAlfredo Cardigliano err_out_adminq_deinit:
15454c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
154627b942c8SAlfredo Cardigliano 
154727b942c8SAlfredo Cardigliano 	return err;
1548669c8de6SAlfredo Cardigliano }
1549669c8de6SAlfredo Cardigliano 
1550669c8de6SAlfredo Cardigliano void
1551669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1552669c8de6SAlfredo Cardigliano {
1553669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1554669c8de6SAlfredo Cardigliano 		return;
1555669c8de6SAlfredo Cardigliano 
155654fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
155722e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
15584c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
15594c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
156001a6c311SAlfredo Cardigliano 
1561669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1562669c8de6SAlfredo Cardigliano }
1563669c8de6SAlfredo Cardigliano 
156418a44465SAndrew Boyer void
156518a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
156618a44465SAndrew Boyer {
156718a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
156818a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
156918a44465SAndrew Boyer 
157018a44465SAndrew Boyer 	/*
157118a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
157218a44465SAndrew Boyer 	 * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK
157318a44465SAndrew Boyer 	 */
157418a44465SAndrew Boyer 	rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
157518a44465SAndrew Boyer 
157618a44465SAndrew Boyer 	if (mask & ETH_VLAN_STRIP_MASK) {
157718a44465SAndrew Boyer 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
157818a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
157918a44465SAndrew Boyer 		else
158018a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
158118a44465SAndrew Boyer 	}
158218a44465SAndrew Boyer }
158318a44465SAndrew Boyer 
158418a44465SAndrew Boyer void
1585598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1586598f6726SAlfredo Cardigliano {
158718a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
158818a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
158922e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
1590*09f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
159122e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
1592*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
159322e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
1594*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
159522e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
159622e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
159722e7171bSAlfredo Cardigliano 
1598598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1599598f6726SAlfredo Cardigliano 
160022e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
160122e7171bSAlfredo Cardigliano 		lif->port_id);
160222e7171bSAlfredo Cardigliano 
160322e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
160422e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
160522e7171bSAlfredo Cardigliano 
160622e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
160722e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
160822e7171bSAlfredo Cardigliano 
160922e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
161022e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1611a27d9013SAlfredo Cardigliano 
161218a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
161318a44465SAndrew Boyer 
161418a44465SAndrew Boyer 	/*
161518a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
161618a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
161718a44465SAndrew Boyer 	 * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH;
161818a44465SAndrew Boyer 	 */
161918a44465SAndrew Boyer 
162018a44465SAndrew Boyer 	/* RX per-port */
162118a44465SAndrew Boyer 
162218a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM ||
162318a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM ||
162418a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM)
162518a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
162618a44465SAndrew Boyer 	else
162718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
162818a44465SAndrew Boyer 
162918a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) {
163018a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
163118a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
163218a44465SAndrew Boyer 	} else {
163318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
163418a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
163518a44465SAndrew Boyer 	}
163618a44465SAndrew Boyer 
163718a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
163818a44465SAndrew Boyer 	ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK);
163918a44465SAndrew Boyer 
164018a44465SAndrew Boyer 	/* TX per-port */
164118a44465SAndrew Boyer 
164218a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM ||
164318a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM ||
164418a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM ||
164518a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
164618a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
164718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
164818a44465SAndrew Boyer 	else
164918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
165018a44465SAndrew Boyer 
165118a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
165218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
165318a44465SAndrew Boyer 	else
165418a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
165518a44465SAndrew Boyer 
165618a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
165718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
165818a44465SAndrew Boyer 	else
165918a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
166018a44465SAndrew Boyer 
166118a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) {
166218a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
166318a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
166418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
166518a44465SAndrew Boyer 	} else {
166618a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
166718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
166818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
166918a44465SAndrew Boyer 	}
1670598f6726SAlfredo Cardigliano }
1671598f6726SAlfredo Cardigliano 
1672598f6726SAlfredo Cardigliano int
1673598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1674598f6726SAlfredo Cardigliano {
16750578335aSAndrew Boyer 	uint32_t rx_mode;
1676a27d9013SAlfredo Cardigliano 	uint32_t i;
1677a27d9013SAlfredo Cardigliano 	int err;
1678598f6726SAlfredo Cardigliano 
167922e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
168022e7171bSAlfredo Cardigliano 	if (err)
168122e7171bSAlfredo Cardigliano 		return err;
168222e7171bSAlfredo Cardigliano 
16830578335aSAndrew Boyer 	if (!lif->rx_mode) {
16840578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
16850578335aSAndrew Boyer 			lif->name);
1686598f6726SAlfredo Cardigliano 
16870578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1688598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1689598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1690598f6726SAlfredo Cardigliano 
1691598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
16920578335aSAndrew Boyer 	}
1693598f6726SAlfredo Cardigliano 
1694a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1695a27d9013SAlfredo Cardigliano 		"on port %u",
1696a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1697a27d9013SAlfredo Cardigliano 
1698a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1699a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
170002eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1701a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1702a27d9013SAlfredo Cardigliano 
1703a27d9013SAlfredo Cardigliano 			if (err)
1704a27d9013SAlfredo Cardigliano 				return err;
1705a27d9013SAlfredo Cardigliano 		}
1706a27d9013SAlfredo Cardigliano 	}
1707a27d9013SAlfredo Cardigliano 
1708a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1709a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
171002eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1711a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1712a27d9013SAlfredo Cardigliano 
1713a27d9013SAlfredo Cardigliano 			if (err)
1714a27d9013SAlfredo Cardigliano 				return err;
1715a27d9013SAlfredo Cardigliano 		}
1716a27d9013SAlfredo Cardigliano 	}
1717a27d9013SAlfredo Cardigliano 
1718598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1719be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1720be63459eSAndrew Boyer 
1721be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1722598f6726SAlfredo Cardigliano 
1723598f6726SAlfredo Cardigliano 	return 0;
1724598f6726SAlfredo Cardigliano }
1725598f6726SAlfredo Cardigliano 
1726598f6726SAlfredo Cardigliano int
1727669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1728669c8de6SAlfredo Cardigliano {
1729669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1730669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1731*09f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
1732669c8de6SAlfredo Cardigliano 	int err;
1733669c8de6SAlfredo Cardigliano 	unsigned int i;
1734669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1735669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1736669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1737669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1738669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1739669c8de6SAlfredo Cardigliano 
1740669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1741669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1742669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1743669c8de6SAlfredo Cardigliano 	if (err)
1744669c8de6SAlfredo Cardigliano 		return (err);
1745669c8de6SAlfredo Cardigliano 
1746669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1747669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1748669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1749669c8de6SAlfredo Cardigliano 
1750669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1751*09f806e9SAndrew Boyer 		rte_le_to_cpu_64(ident->lif.capabilities));
1752669c8de6SAlfredo Cardigliano 
1753669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1754*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_ucast_filters));
1755669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1756*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(ident->lif.eth.max_mcast_filters));
1757669c8de6SAlfredo Cardigliano 
1758669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1759*09f806e9SAndrew Boyer 		rte_le_to_cpu_64(cfg->features));
1760669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1761*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_ADMINQ]));
1762669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1763*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_NOTIFYQ]));
1764669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1765*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]));
1766669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1767*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]));
1768669c8de6SAlfredo Cardigliano 
1769669c8de6SAlfredo Cardigliano 	return 0;
1770669c8de6SAlfredo Cardigliano }
1771669c8de6SAlfredo Cardigliano 
1772669c8de6SAlfredo Cardigliano int
1773669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1774669c8de6SAlfredo Cardigliano {
1775669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1776*09f806e9SAndrew Boyer 	union ionic_lif_config *cfg = &ident->lif.eth.config;
1777*09f806e9SAndrew Boyer 	uint32_t nintrs, dev_nintrs = rte_le_to_cpu_32(ident->dev.nintrs);
1778669c8de6SAlfredo Cardigliano 
1779669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1780*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
1781669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1782*09f806e9SAndrew Boyer 		rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
1783669c8de6SAlfredo Cardigliano 
178400b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1785669c8de6SAlfredo Cardigliano 
1786669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
17874ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
17884ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1789669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1790669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1791669c8de6SAlfredo Cardigliano 	}
1792669c8de6SAlfredo Cardigliano 
1793669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1794669c8de6SAlfredo Cardigliano 
1795669c8de6SAlfredo Cardigliano 	return 0;
1796669c8de6SAlfredo Cardigliano }
1797