xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 4c8f8d57f6d288a10af463ffe4a2c031b58d08b0)
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,
2801a6c311SAlfredo Cardigliano 			.index = 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,
4601a6c311SAlfredo Cardigliano 			.index = 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,
24454fe083fSAlfredo Cardigliano 			.match = 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)",
25654fe083fSAlfredo Cardigliano 		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 
28354fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = 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)",
29354fe083fSAlfredo Cardigliano 		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,
36754fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_VLAN,
36854fe083fSAlfredo Cardigliano 			.vlan.vlan = 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,
37854fe083fSAlfredo Cardigliano 		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 
40554fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = 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,
41454fe083fSAlfredo Cardigliano 		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,
441598f6726SAlfredo Cardigliano 			.rx_mode = 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,
533598f6726SAlfredo Cardigliano 			.mtu = 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 {
575*4c8f8d57SAndrew 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");
631*4c8f8d57SAndrew Boyer 		err = -ENOMEM;
632*4c8f8d57SAndrew 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");
641*4c8f8d57SAndrew Boyer 		goto err_out_free_info;
64201a6c311SAlfredo Cardigliano 	}
64301a6c311SAlfredo Cardigliano 
644*4c8f8d57SAndrew 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");
647*4c8f8d57SAndrew 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;
657*4c8f8d57SAndrew 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 
689*4c8f8d57SAndrew Boyer err_out_free_info:
690*4c8f8d57SAndrew Boyer 	rte_free(new->q.info);
691*4c8f8d57SAndrew Boyer err_out_free_qcq:
692*4c8f8d57SAndrew 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 {
781*4c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq;
782*4c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
783*4c8f8d57SAndrew 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,
792*4c8f8d57SAndrew Boyer 		&nqcq);
79301a6c311SAlfredo Cardigliano 	if (err)
79401a6c311SAlfredo Cardigliano 		return err;
79501a6c311SAlfredo Cardigliano 
796*4c8f8d57SAndrew Boyer 	err = ionic_intr_alloc(lif, &nqcq->intr);
797*4c8f8d57SAndrew Boyer 	if (err) {
798*4c8f8d57SAndrew Boyer 		ionic_qcq_free(nqcq);
799*4c8f8d57SAndrew Boyer 		return err;
800*4c8f8d57SAndrew Boyer 	}
801*4c8f8d57SAndrew Boyer 
802*4c8f8d57SAndrew Boyer 	ionic_intr_mask_assert(idev->intr_ctrl, nqcq->intr.index,
803*4c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
804*4c8f8d57SAndrew Boyer 
805*4c8f8d57SAndrew Boyer 	lif->notifyqcq = nqcq;
806*4c8f8d57SAndrew 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 {
94522e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
94622e7171bSAlfredo Cardigliano 		.pending_work = true,
94722e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
94822e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
94922e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
95022e7171bSAlfredo Cardigliano 			.rss.types = types,
95122e7171bSAlfredo Cardigliano 			.rss.addr = lif->rss_ind_tbl_pa,
95222e7171bSAlfredo Cardigliano 		},
95322e7171bSAlfredo Cardigliano 	};
95422e7171bSAlfredo Cardigliano 	unsigned int i;
95522e7171bSAlfredo Cardigliano 
95622e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
95722e7171bSAlfredo Cardigliano 
95822e7171bSAlfredo Cardigliano 	lif->rss_types = types;
95922e7171bSAlfredo Cardigliano 
96022e7171bSAlfredo Cardigliano 	if (key)
96122e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
96222e7171bSAlfredo Cardigliano 
96322e7171bSAlfredo Cardigliano 	if (indir)
96422e7171bSAlfredo Cardigliano 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
96522e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
96622e7171bSAlfredo Cardigliano 
96722e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
96822e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
96922e7171bSAlfredo Cardigliano 
97022e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
97122e7171bSAlfredo Cardigliano }
97222e7171bSAlfredo Cardigliano 
97322e7171bSAlfredo Cardigliano static int
97422e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
97522e7171bSAlfredo Cardigliano {
97622e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
97722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98222e7171bSAlfredo Cardigliano 	};
98322e7171bSAlfredo Cardigliano 	uint32_t i;
9843d845eddSAndrew Boyer 	uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
98522e7171bSAlfredo Cardigliano 
98622e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
98722e7171bSAlfredo Cardigliano 
9883d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
98922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
9903d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
9913d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
9923d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
99322e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
99422e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
99522e7171bSAlfredo Cardigliano 			return -ENOMEM;
99622e7171bSAlfredo Cardigliano 		}
99722e7171bSAlfredo Cardigliano 
99822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
99922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
10003d845eddSAndrew Boyer 	}
10013d845eddSAndrew Boyer 
10023d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
10033d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
100422e7171bSAlfredo Cardigliano 
100522e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
10063d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
100722e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
10083d845eddSAndrew Boyer 	}
100922e7171bSAlfredo Cardigliano 
10103d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
101122e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
101222e7171bSAlfredo Cardigliano }
101322e7171bSAlfredo Cardigliano 
101422e7171bSAlfredo Cardigliano static void
101522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
101622e7171bSAlfredo Cardigliano {
101722e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
101822e7171bSAlfredo Cardigliano 		return;
101922e7171bSAlfredo Cardigliano 
102022e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
102122e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
102222e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
102322e7171bSAlfredo Cardigliano 
102422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
102522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
102622e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
102722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
102822e7171bSAlfredo Cardigliano 	}
102922e7171bSAlfredo Cardigliano }
103022e7171bSAlfredo Cardigliano 
103101a6c311SAlfredo Cardigliano static void
1032*4c8f8d57SAndrew Boyer ionic_lif_qcq_deinit(struct ionic_qcq *qcq)
103301a6c311SAlfredo Cardigliano {
103401a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
103501a6c311SAlfredo Cardigliano }
103601a6c311SAlfredo Cardigliano 
1037a27d9013SAlfredo Cardigliano void
1038a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1039a27d9013SAlfredo Cardigliano {
1040*4c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
1041a27d9013SAlfredo Cardigliano }
1042a27d9013SAlfredo Cardigliano 
1043a27d9013SAlfredo Cardigliano void
1044a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1045a27d9013SAlfredo Cardigliano {
1046*4c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(qcq);
1047*4c8f8d57SAndrew Boyer }
1048*4c8f8d57SAndrew Boyer 
1049*4c8f8d57SAndrew Boyer static void
1050*4c8f8d57SAndrew Boyer ionic_lif_notifyq_deinit(struct ionic_lif *lif)
1051*4c8f8d57SAndrew Boyer {
1052*4c8f8d57SAndrew Boyer 	struct ionic_qcq *nqcq = lif->notifyqcq;
1053*4c8f8d57SAndrew Boyer 	struct ionic_dev *idev = &lif->adapter->idev;
1054*4c8f8d57SAndrew Boyer 
1055*4c8f8d57SAndrew Boyer 	if (!(nqcq->flags & IONIC_QCQ_F_INITED))
1056*4c8f8d57SAndrew Boyer 		return;
1057*4c8f8d57SAndrew Boyer 
1058*4c8f8d57SAndrew Boyer 	ionic_intr_mask(idev->intr_ctrl, nqcq->intr.index,
1059*4c8f8d57SAndrew Boyer 		IONIC_INTR_MASK_SET);
1060*4c8f8d57SAndrew Boyer 
1061*4c8f8d57SAndrew Boyer 	nqcq->flags &= ~IONIC_QCQ_F_INITED;
1062a27d9013SAlfredo Cardigliano }
1063a27d9013SAlfredo Cardigliano 
106401a6c311SAlfredo Cardigliano bool
106501a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
106601a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
106701a6c311SAlfredo Cardigliano {
106801a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
106901a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
107001a6c311SAlfredo Cardigliano 
107101a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
107201a6c311SAlfredo Cardigliano 		return false;
107301a6c311SAlfredo Cardigliano 
107401a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
107501a6c311SAlfredo Cardigliano 
107601a6c311SAlfredo Cardigliano 	return true;
107701a6c311SAlfredo Cardigliano }
107801a6c311SAlfredo Cardigliano 
107901a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
108001a6c311SAlfredo Cardigliano int
108101a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
108201a6c311SAlfredo Cardigliano 		void *cb_arg)
108301a6c311SAlfredo Cardigliano {
108401a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
108501a6c311SAlfredo Cardigliano 	uint32_t work_done;
108601a6c311SAlfredo Cardigliano 
108701a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
108801a6c311SAlfredo Cardigliano 
108901a6c311SAlfredo Cardigliano 	return work_done;
109001a6c311SAlfredo Cardigliano }
109101a6c311SAlfredo Cardigliano 
109227b942c8SAlfredo Cardigliano static void
109327b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
109427b942c8SAlfredo Cardigliano {
109527b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
109627b942c8SAlfredo Cardigliano 	bool link_up;
109727b942c8SAlfredo Cardigliano 
109827b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
109927b942c8SAlfredo Cardigliano 
110027b942c8SAlfredo Cardigliano 	if (!lif->info)
110127b942c8SAlfredo Cardigliano 		return;
110227b942c8SAlfredo Cardigliano 
110327b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
110427b942c8SAlfredo Cardigliano 
110527b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
110627b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
110727b942c8SAlfredo Cardigliano 		return;
110827b942c8SAlfredo Cardigliano 
110927b942c8SAlfredo Cardigliano 	if (link_up) {
111027b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
1111be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1112be63459eSAndrew Boyer 			adapter->link_speed);
111327b942c8SAlfredo Cardigliano 	} else {
111427b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
111527b942c8SAlfredo Cardigliano 	}
111627b942c8SAlfredo Cardigliano 
111727b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1118be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1119be63459eSAndrew Boyer }
1120be63459eSAndrew Boyer 
1121be63459eSAndrew Boyer static void
1122be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1123be63459eSAndrew Boyer {
1124be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1125be63459eSAndrew Boyer 		return;
1126be63459eSAndrew Boyer 
1127be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1128be63459eSAndrew Boyer 
1129be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1130be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1131be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1132be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1133be63459eSAndrew Boyer 	}
1134be63459eSAndrew Boyer 
1135be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
113627b942c8SAlfredo Cardigliano }
113727b942c8SAlfredo Cardigliano 
113827b942c8SAlfredo Cardigliano static bool
113927b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
114027b942c8SAlfredo Cardigliano {
114127b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
114227b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
114327b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
114427b942c8SAlfredo Cardigliano 
114527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
114627b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
114727b942c8SAlfredo Cardigliano 
114827b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
114927b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
115027b942c8SAlfredo Cardigliano 		return false;
115127b942c8SAlfredo Cardigliano 
115227b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
115327b942c8SAlfredo Cardigliano 
115427b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
115527b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
115627b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1157be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1158be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1159be63459eSAndrew Boyer 			lif->name,
116027b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
116127b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
116227b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
116327b942c8SAlfredo Cardigliano 
116427b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
116527b942c8SAlfredo Cardigliano 		break;
1166be63459eSAndrew Boyer 
1167be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1168be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1169be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1170be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1171be63459eSAndrew Boyer 			lif->name,
1172be63459eSAndrew Boyer 			cq_desc->event.eid,
1173be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1174be63459eSAndrew Boyer 			cq_desc->reset.state);
1175be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1176be63459eSAndrew Boyer 		break;
1177be63459eSAndrew Boyer 
117827b942c8SAlfredo Cardigliano 	default:
117927b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
118027b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
118127b942c8SAlfredo Cardigliano 		break;
118227b942c8SAlfredo Cardigliano 	}
118327b942c8SAlfredo Cardigliano 
118427b942c8SAlfredo Cardigliano 	return true;
118527b942c8SAlfredo Cardigliano }
118627b942c8SAlfredo Cardigliano 
118727b942c8SAlfredo Cardigliano int
118827b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
118927b942c8SAlfredo Cardigliano {
119027b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
119127b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
119227b942c8SAlfredo Cardigliano 	uint32_t work_done;
119327b942c8SAlfredo Cardigliano 
119427b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
119527b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
119627b942c8SAlfredo Cardigliano 		return -1;
119727b942c8SAlfredo Cardigliano 	}
119827b942c8SAlfredo Cardigliano 
119927b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
120027b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
120127b942c8SAlfredo Cardigliano 
120227b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
120327b942c8SAlfredo Cardigliano 
120427b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
120527b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
120627b942c8SAlfredo Cardigliano 
120727b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
120827b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
120927b942c8SAlfredo Cardigliano 
121027b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
121127b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
121227b942c8SAlfredo Cardigliano 
121327b942c8SAlfredo Cardigliano 	return 0;
121427b942c8SAlfredo Cardigliano }
121527b942c8SAlfredo Cardigliano 
121601a6c311SAlfredo Cardigliano static int
121701a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
121801a6c311SAlfredo Cardigliano {
121901a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
122001a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
122101a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
122201a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
122301a6c311SAlfredo Cardigliano 	int err;
122401a6c311SAlfredo Cardigliano 
1225*4c8f8d57SAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, qcq);
122601a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
122701a6c311SAlfredo Cardigliano 	if (err)
122801a6c311SAlfredo Cardigliano 		return err;
122901a6c311SAlfredo Cardigliano 
123001a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
123101a6c311SAlfredo Cardigliano 
123201a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
123301a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
123401a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
123501a6c311SAlfredo Cardigliano 
123601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
123701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
123801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
123901a6c311SAlfredo Cardigliano 
124001a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
124101a6c311SAlfredo Cardigliano 
124201a6c311SAlfredo Cardigliano 	return 0;
124301a6c311SAlfredo Cardigliano }
124401a6c311SAlfredo Cardigliano 
124527b942c8SAlfredo Cardigliano static int
124627b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
124727b942c8SAlfredo Cardigliano {
124827b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
124927b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
125027b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
125127b942c8SAlfredo Cardigliano 	int err;
125227b942c8SAlfredo Cardigliano 
125327b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
125427b942c8SAlfredo Cardigliano 		.pending_work = true,
125527b942c8SAlfredo Cardigliano 		.cmd.q_init = {
125627b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
125727b942c8SAlfredo Cardigliano 			.type = q->type,
125827b942c8SAlfredo Cardigliano 			.index = q->index,
125927b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
126027b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
126127b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
126227b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
126327b942c8SAlfredo Cardigliano 		}
126427b942c8SAlfredo Cardigliano 	};
126527b942c8SAlfredo Cardigliano 
126627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
126727b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
126827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
126927b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
127027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
127127b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
12724ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
127327b942c8SAlfredo Cardigliano 
127427b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
127527b942c8SAlfredo Cardigliano 	if (err)
127627b942c8SAlfredo Cardigliano 		return err;
127727b942c8SAlfredo Cardigliano 
127827b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
127927b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
128027b942c8SAlfredo Cardigliano 	q->db = NULL;
128127b942c8SAlfredo Cardigliano 
128227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
128327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
128427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
128527b942c8SAlfredo Cardigliano 
128627b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
128727b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
128827b942c8SAlfredo Cardigliano 
128927b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
129027b942c8SAlfredo Cardigliano 
129127b942c8SAlfredo Cardigliano 	return 0;
129227b942c8SAlfredo Cardigliano }
129327b942c8SAlfredo Cardigliano 
1294669c8de6SAlfredo Cardigliano int
1295598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1296598f6726SAlfredo Cardigliano {
1297598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1298598f6726SAlfredo Cardigliano 		.pending_work = true,
1299598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1300598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1301598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1302598f6726SAlfredo Cardigliano 			.features = lif->features,
1303598f6726SAlfredo Cardigliano 		},
1304598f6726SAlfredo Cardigliano 	};
1305598f6726SAlfredo Cardigliano 	int err;
1306598f6726SAlfredo Cardigliano 
1307598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1308598f6726SAlfredo Cardigliano 	if (err)
1309598f6726SAlfredo Cardigliano 		return err;
1310598f6726SAlfredo Cardigliano 
1311598f6726SAlfredo Cardigliano 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1312598f6726SAlfredo Cardigliano 		ctx.comp.lif_setattr.features);
1313598f6726SAlfredo Cardigliano 
1314598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1315598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1316598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1317598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1318598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1319598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1320598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1321598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1322598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1323598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1324598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1325598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1326598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1327598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1328598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1329598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1330598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1331598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1332598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1333598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1334598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1335598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1336598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1337598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1338598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1339598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1340598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1341598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1342598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1343598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1344598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1345598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1346598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1347598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1348598f6726SAlfredo Cardigliano 
1349598f6726SAlfredo Cardigliano 	return 0;
1350598f6726SAlfredo Cardigliano }
1351598f6726SAlfredo Cardigliano 
1352a27d9013SAlfredo Cardigliano int
1353a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1354a27d9013SAlfredo Cardigliano {
1355a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1356a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1357a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1358a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1359a27d9013SAlfredo Cardigliano 		.pending_work = true,
1360a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1361a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1362a27d9013SAlfredo Cardigliano 			.type = q->type,
1363a27d9013SAlfredo Cardigliano 			.index = q->index,
1364b5d9a4f0SAndrew Boyer 			.flags = IONIC_QINIT_F_SG | IONIC_QINIT_F_ENA,
1365*4c8f8d57SAndrew Boyer 			.intr_index = IONIC_INTR_NONE,
1366a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1367a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1368a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1369a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1370a27d9013SAlfredo Cardigliano 		},
1371a27d9013SAlfredo Cardigliano 	};
1372a27d9013SAlfredo Cardigliano 	int err;
1373a27d9013SAlfredo Cardigliano 
1374a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1375a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1376a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1377a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1378a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13794ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1380a27d9013SAlfredo Cardigliano 
1381a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1382a27d9013SAlfredo Cardigliano 	if (err)
1383a27d9013SAlfredo Cardigliano 		return err;
1384a27d9013SAlfredo Cardigliano 
1385a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1386a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1387a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1388a27d9013SAlfredo Cardigliano 
1389a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1390a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1391a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1392a27d9013SAlfredo Cardigliano 
1393a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1394a27d9013SAlfredo Cardigliano 
1395a27d9013SAlfredo Cardigliano 	return 0;
1396a27d9013SAlfredo Cardigliano }
1397a27d9013SAlfredo Cardigliano 
1398a27d9013SAlfredo Cardigliano int
1399a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1400a27d9013SAlfredo Cardigliano {
1401a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1402a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1403a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1404a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1405a27d9013SAlfredo Cardigliano 		.pending_work = true,
1406a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1407a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1408a27d9013SAlfredo Cardigliano 			.type = q->type,
1409a27d9013SAlfredo Cardigliano 			.index = q->index,
1410b5d9a4f0SAndrew Boyer 			.flags = IONIC_QINIT_F_SG | IONIC_QINIT_F_ENA,
1411*4c8f8d57SAndrew Boyer 			.intr_index = IONIC_INTR_NONE,
1412a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1413a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1414a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1415a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1416a27d9013SAlfredo Cardigliano 		},
1417a27d9013SAlfredo Cardigliano 	};
1418a27d9013SAlfredo Cardigliano 	int err;
1419a27d9013SAlfredo Cardigliano 
1420a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1421a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1422a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1423a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1424a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14254ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1426a27d9013SAlfredo Cardigliano 
1427a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1428a27d9013SAlfredo Cardigliano 	if (err)
1429a27d9013SAlfredo Cardigliano 		return err;
1430a27d9013SAlfredo Cardigliano 
1431a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1432a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1433a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1434a27d9013SAlfredo Cardigliano 
1435a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1436a27d9013SAlfredo Cardigliano 
1437a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1438a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1439a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1440a27d9013SAlfredo Cardigliano 
1441a27d9013SAlfredo Cardigliano 	return 0;
1442a27d9013SAlfredo Cardigliano }
1443a27d9013SAlfredo Cardigliano 
1444598f6726SAlfredo Cardigliano static int
1445598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1446598f6726SAlfredo Cardigliano {
1447598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1448598f6726SAlfredo Cardigliano 		.pending_work = true,
1449598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1450598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1451598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1452598f6726SAlfredo Cardigliano 		},
1453598f6726SAlfredo Cardigliano 	};
1454598f6726SAlfredo Cardigliano 	int err;
1455598f6726SAlfredo Cardigliano 
1456598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1457598f6726SAlfredo Cardigliano 
1458598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1459598f6726SAlfredo Cardigliano 	if (err)
1460598f6726SAlfredo Cardigliano 		return err;
1461598f6726SAlfredo Cardigliano 
1462598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1463598f6726SAlfredo Cardigliano 
1464598f6726SAlfredo Cardigliano 	return 0;
1465598f6726SAlfredo Cardigliano }
1466598f6726SAlfredo Cardigliano 
1467598f6726SAlfredo Cardigliano static void
1468598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1469598f6726SAlfredo Cardigliano {
1470598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1471598f6726SAlfredo Cardigliano 		.pending_work = true,
1472598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1473598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1474598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1475598f6726SAlfredo Cardigliano 		},
1476598f6726SAlfredo Cardigliano 	};
1477598f6726SAlfredo Cardigliano 
14784ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
14794ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1480598f6726SAlfredo Cardigliano 
1481598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1482598f6726SAlfredo Cardigliano }
1483598f6726SAlfredo Cardigliano 
1484598f6726SAlfredo Cardigliano int
1485669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1486669c8de6SAlfredo Cardigliano {
1487669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1488669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1489669c8de6SAlfredo Cardigliano 	int err;
1490669c8de6SAlfredo Cardigliano 
14913cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
14923cdfd905SAlfredo Cardigliano 
149300b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1494669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1495669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1496669c8de6SAlfredo Cardigliano 	if (err)
1497669c8de6SAlfredo Cardigliano 		return err;
1498669c8de6SAlfredo Cardigliano 
1499669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
1500669c8de6SAlfredo Cardigliano 
150101a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
150201a6c311SAlfredo Cardigliano 	if (err)
150301a6c311SAlfredo Cardigliano 		return err;
150401a6c311SAlfredo Cardigliano 
150527b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
150627b942c8SAlfredo Cardigliano 	if (err)
150727b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
150827b942c8SAlfredo Cardigliano 
150918a44465SAndrew Boyer 	/*
151018a44465SAndrew Boyer 	 * Configure initial feature set
151118a44465SAndrew Boyer 	 * This will be updated later by the dev_configure() step
151218a44465SAndrew Boyer 	 */
151318a44465SAndrew Boyer 	lif->features = IONIC_ETH_HW_RX_HASH | IONIC_ETH_HW_VLAN_RX_FILTER;
1514598f6726SAlfredo Cardigliano 
1515598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1516598f6726SAlfredo Cardigliano 	if (err)
1517598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1518598f6726SAlfredo Cardigliano 
151954fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1520598f6726SAlfredo Cardigliano 	if (err)
1521598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1522598f6726SAlfredo Cardigliano 
152354fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
152454fe083fSAlfredo Cardigliano 	if (err)
152554fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
152654fe083fSAlfredo Cardigliano 
1527598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1528598f6726SAlfredo Cardigliano 
1529669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1530669c8de6SAlfredo Cardigliano 
1531669c8de6SAlfredo Cardigliano 	return 0;
153227b942c8SAlfredo Cardigliano 
153354fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
153454fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
153554fe083fSAlfredo Cardigliano 
1536598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
1537*4c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1538598f6726SAlfredo Cardigliano 
153927b942c8SAlfredo Cardigliano err_out_adminq_deinit:
1540*4c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
154127b942c8SAlfredo Cardigliano 
154227b942c8SAlfredo Cardigliano 	return err;
1543669c8de6SAlfredo Cardigliano }
1544669c8de6SAlfredo Cardigliano 
1545669c8de6SAlfredo Cardigliano void
1546669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1547669c8de6SAlfredo Cardigliano {
1548669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1549669c8de6SAlfredo Cardigliano 		return;
1550669c8de6SAlfredo Cardigliano 
155154fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
155222e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
1553*4c8f8d57SAndrew Boyer 	ionic_lif_notifyq_deinit(lif);
1554*4c8f8d57SAndrew Boyer 	ionic_lif_qcq_deinit(lif->adminqcq);
155501a6c311SAlfredo Cardigliano 
1556669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1557669c8de6SAlfredo Cardigliano }
1558669c8de6SAlfredo Cardigliano 
155918a44465SAndrew Boyer void
156018a44465SAndrew Boyer ionic_lif_configure_vlan_offload(struct ionic_lif *lif, int mask)
156118a44465SAndrew Boyer {
156218a44465SAndrew Boyer 	struct rte_eth_dev *eth_dev = lif->eth_dev;
156318a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
156418a44465SAndrew Boyer 
156518a44465SAndrew Boyer 	/*
156618a44465SAndrew Boyer 	 * IONIC_ETH_HW_VLAN_RX_FILTER cannot be turned off, so
156718a44465SAndrew Boyer 	 * set DEV_RX_OFFLOAD_VLAN_FILTER and ignore ETH_VLAN_FILTER_MASK
156818a44465SAndrew Boyer 	 */
156918a44465SAndrew Boyer 	rxmode->offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
157018a44465SAndrew Boyer 
157118a44465SAndrew Boyer 	if (mask & ETH_VLAN_STRIP_MASK) {
157218a44465SAndrew Boyer 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
157318a44465SAndrew Boyer 			lif->features |= IONIC_ETH_HW_VLAN_RX_STRIP;
157418a44465SAndrew Boyer 		else
157518a44465SAndrew Boyer 			lif->features &= ~IONIC_ETH_HW_VLAN_RX_STRIP;
157618a44465SAndrew Boyer 	}
157718a44465SAndrew Boyer }
157818a44465SAndrew Boyer 
157918a44465SAndrew Boyer void
1580598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1581598f6726SAlfredo Cardigliano {
158218a44465SAndrew Boyer 	struct rte_eth_rxmode *rxmode = &lif->eth_dev->data->dev_conf.rxmode;
158318a44465SAndrew Boyer 	struct rte_eth_txmode *txmode = &lif->eth_dev->data->dev_conf.txmode;
158422e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
158522e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
158622e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
158722e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
158822e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
158922e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
159022e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
159122e7171bSAlfredo Cardigliano 
1592598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1593598f6726SAlfredo Cardigliano 
159422e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
159522e7171bSAlfredo Cardigliano 		lif->port_id);
159622e7171bSAlfredo Cardigliano 
159722e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
159822e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
159922e7171bSAlfredo Cardigliano 
160022e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
160122e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
160222e7171bSAlfredo Cardigliano 
160322e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
160422e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1605a27d9013SAlfredo Cardigliano 
160618a44465SAndrew Boyer 	/* Update the LIF configuration based on the eth_dev */
160718a44465SAndrew Boyer 
160818a44465SAndrew Boyer 	/*
160918a44465SAndrew Boyer 	 * NB: While it is true that RSS_HASH is always enabled on ionic,
161018a44465SAndrew Boyer 	 *     setting this flag unconditionally causes problems in DTS.
161118a44465SAndrew Boyer 	 * rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH;
161218a44465SAndrew Boyer 	 */
161318a44465SAndrew Boyer 
161418a44465SAndrew Boyer 	/* RX per-port */
161518a44465SAndrew Boyer 
161618a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_IPV4_CKSUM ||
161718a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_UDP_CKSUM ||
161818a44465SAndrew Boyer 	    rxmode->offloads & DEV_RX_OFFLOAD_TCP_CKSUM)
161918a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_CSUM;
162018a44465SAndrew Boyer 	else
162118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_CSUM;
162218a44465SAndrew Boyer 
162318a44465SAndrew Boyer 	if (rxmode->offloads & DEV_RX_OFFLOAD_SCATTER) {
162418a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_RX_SG;
162518a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 1;
162618a44465SAndrew Boyer 	} else {
162718a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_RX_SG;
162818a44465SAndrew Boyer 		lif->eth_dev->data->scattered_rx = 0;
162918a44465SAndrew Boyer 	}
163018a44465SAndrew Boyer 
163118a44465SAndrew Boyer 	/* Covers VLAN_STRIP */
163218a44465SAndrew Boyer 	ionic_lif_configure_vlan_offload(lif, ETH_VLAN_STRIP_MASK);
163318a44465SAndrew Boyer 
163418a44465SAndrew Boyer 	/* TX per-port */
163518a44465SAndrew Boyer 
163618a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_IPV4_CKSUM ||
163718a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_UDP_CKSUM ||
163818a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_TCP_CKSUM ||
163918a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM ||
164018a44465SAndrew Boyer 	    txmode->offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
164118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_CSUM;
164218a44465SAndrew Boyer 	else
164318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_CSUM;
164418a44465SAndrew Boyer 
164518a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
164618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_VLAN_TX_TAG;
164718a44465SAndrew Boyer 	else
164818a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_VLAN_TX_TAG;
164918a44465SAndrew Boyer 
165018a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
165118a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TX_SG;
165218a44465SAndrew Boyer 	else
165318a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TX_SG;
165418a44465SAndrew Boyer 
165518a44465SAndrew Boyer 	if (txmode->offloads & DEV_TX_OFFLOAD_TCP_TSO) {
165618a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO;
165718a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_IPV6;
165818a44465SAndrew Boyer 		lif->features |= IONIC_ETH_HW_TSO_ECN;
165918a44465SAndrew Boyer 	} else {
166018a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO;
166118a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_IPV6;
166218a44465SAndrew Boyer 		lif->features &= ~IONIC_ETH_HW_TSO_ECN;
166318a44465SAndrew Boyer 	}
1664598f6726SAlfredo Cardigliano }
1665598f6726SAlfredo Cardigliano 
1666598f6726SAlfredo Cardigliano int
1667598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1668598f6726SAlfredo Cardigliano {
16690578335aSAndrew Boyer 	uint32_t rx_mode;
1670a27d9013SAlfredo Cardigliano 	uint32_t i;
1671a27d9013SAlfredo Cardigliano 	int err;
1672598f6726SAlfredo Cardigliano 
167322e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
167422e7171bSAlfredo Cardigliano 	if (err)
167522e7171bSAlfredo Cardigliano 		return err;
167622e7171bSAlfredo Cardigliano 
16770578335aSAndrew Boyer 	if (!lif->rx_mode) {
16780578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
16790578335aSAndrew Boyer 			lif->name);
1680598f6726SAlfredo Cardigliano 
16810578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1682598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1683598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1684598f6726SAlfredo Cardigliano 
1685598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
16860578335aSAndrew Boyer 	}
1687598f6726SAlfredo Cardigliano 
1688a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1689a27d9013SAlfredo Cardigliano 		"on port %u",
1690a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1691a27d9013SAlfredo Cardigliano 
1692a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1693a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
169402eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1695a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1696a27d9013SAlfredo Cardigliano 
1697a27d9013SAlfredo Cardigliano 			if (err)
1698a27d9013SAlfredo Cardigliano 				return err;
1699a27d9013SAlfredo Cardigliano 		}
1700a27d9013SAlfredo Cardigliano 	}
1701a27d9013SAlfredo Cardigliano 
1702a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1703a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
170402eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1705a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1706a27d9013SAlfredo Cardigliano 
1707a27d9013SAlfredo Cardigliano 			if (err)
1708a27d9013SAlfredo Cardigliano 				return err;
1709a27d9013SAlfredo Cardigliano 		}
1710a27d9013SAlfredo Cardigliano 	}
1711a27d9013SAlfredo Cardigliano 
1712598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1713be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1714be63459eSAndrew Boyer 
1715be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1716598f6726SAlfredo Cardigliano 
1717598f6726SAlfredo Cardigliano 	return 0;
1718598f6726SAlfredo Cardigliano }
1719598f6726SAlfredo Cardigliano 
1720598f6726SAlfredo Cardigliano int
1721669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1722669c8de6SAlfredo Cardigliano {
1723669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1724669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1725669c8de6SAlfredo Cardigliano 	int err;
1726669c8de6SAlfredo Cardigliano 	unsigned int i;
1727669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1728669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1729669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1730669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1731669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1732669c8de6SAlfredo Cardigliano 
1733669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1734669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1735669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1736669c8de6SAlfredo Cardigliano 	if (err)
1737669c8de6SAlfredo Cardigliano 		return (err);
1738669c8de6SAlfredo Cardigliano 
1739669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1740669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1741669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1742669c8de6SAlfredo Cardigliano 
1743669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1744669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
1745669c8de6SAlfredo Cardigliano 
1746669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1747669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
1748669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1749669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
1750669c8de6SAlfredo Cardigliano 
1751669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1752669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
1753669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1754669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1755669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1756669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1757669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1758669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1759669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1760669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1761669c8de6SAlfredo Cardigliano 
1762669c8de6SAlfredo Cardigliano 	return 0;
1763669c8de6SAlfredo Cardigliano }
1764669c8de6SAlfredo Cardigliano 
1765669c8de6SAlfredo Cardigliano int
1766669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1767669c8de6SAlfredo Cardigliano {
1768669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1769669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1770669c8de6SAlfredo Cardigliano 
1771669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1772669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1773669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1774669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1775669c8de6SAlfredo Cardigliano 
177600b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1777669c8de6SAlfredo Cardigliano 
1778669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
17794ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
17804ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1781669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1782669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1783669c8de6SAlfredo Cardigliano 	}
1784669c8de6SAlfredo Cardigliano 
1785669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1786669c8de6SAlfredo Cardigliano 
1787669c8de6SAlfredo Cardigliano 	return 0;
1788669c8de6SAlfredo Cardigliano }
1789