xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision a0a99f21dd8a3edfe7d8e35831793930d2c0172e)
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>
6669c8de6SAlfredo Cardigliano #include <rte_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_dev *idev = &lif->adapter->idev;
2401a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
2501a6c311SAlfredo Cardigliano 		.pending_work = true,
2601a6c311SAlfredo Cardigliano 		.cmd.q_control = {
2701a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
2801a6c311SAlfredo Cardigliano 			.type = q->type,
2901a6c311SAlfredo Cardigliano 			.index = q->index,
3001a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
3101a6c311SAlfredo Cardigliano 		},
3201a6c311SAlfredo Cardigliano 	};
3301a6c311SAlfredo Cardigliano 
3401a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
3501a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
3601a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
3701a6c311SAlfredo Cardigliano 	}
3801a6c311SAlfredo Cardigliano 
3901a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4001a6c311SAlfredo Cardigliano }
4101a6c311SAlfredo Cardigliano 
4201a6c311SAlfredo Cardigliano int
4301a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
4401a6c311SAlfredo Cardigliano {
4501a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
4601a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
4701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
4801a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
4901a6c311SAlfredo Cardigliano 		.pending_work = true,
5001a6c311SAlfredo Cardigliano 		.cmd.q_control = {
5101a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
5201a6c311SAlfredo Cardigliano 			.type = q->type,
5301a6c311SAlfredo Cardigliano 			.index = q->index,
5401a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
5501a6c311SAlfredo Cardigliano 		},
5601a6c311SAlfredo Cardigliano 	};
5701a6c311SAlfredo Cardigliano 
5801a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
5901a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
6001a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
6101a6c311SAlfredo Cardigliano 	}
6201a6c311SAlfredo Cardigliano 
6301a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6401a6c311SAlfredo Cardigliano }
6501a6c311SAlfredo Cardigliano 
66be63459eSAndrew Boyer void
67be63459eSAndrew Boyer ionic_lif_stop(struct ionic_lif *lif)
68598f6726SAlfredo Cardigliano {
69*a0a99f21SAndrew Boyer 	uint32_t i;
70*a0a99f21SAndrew Boyer 
71be63459eSAndrew Boyer 	IONIC_PRINT_CALL();
72598f6726SAlfredo Cardigliano 
73be63459eSAndrew Boyer 	lif->state &= ~IONIC_LIF_F_UP;
74*a0a99f21SAndrew Boyer 
75*a0a99f21SAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
76*a0a99f21SAndrew Boyer 		struct ionic_qcq *rxq = lif->rxqcqs[i];
77*a0a99f21SAndrew Boyer 		if (rxq->flags & IONIC_QCQ_F_INITED)
78*a0a99f21SAndrew Boyer 			(void)ionic_dev_rx_queue_stop(lif->eth_dev, i);
79*a0a99f21SAndrew Boyer 	}
80*a0a99f21SAndrew Boyer 
81*a0a99f21SAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
82*a0a99f21SAndrew Boyer 		struct ionic_qcq *txq = lif->txqcqs[i];
83*a0a99f21SAndrew Boyer 		if (txq->flags & IONIC_QCQ_F_INITED)
84*a0a99f21SAndrew Boyer 			(void)ionic_dev_tx_queue_stop(lif->eth_dev, i);
85*a0a99f21SAndrew Boyer 	}
86598f6726SAlfredo Cardigliano }
87598f6726SAlfredo Cardigliano 
88598f6726SAlfredo Cardigliano void
89598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
90598f6726SAlfredo Cardigliano {
91598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
9275f96902SAndrew Boyer 	int err;
93598f6726SAlfredo Cardigliano 
94598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
95598f6726SAlfredo Cardigliano 
9600b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
9775f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
9875f96902SAndrew Boyer 	if (err)
994ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
100598f6726SAlfredo Cardigliano }
101598f6726SAlfredo Cardigliano 
1023cdfd905SAlfredo Cardigliano static void
1033cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
1043cdfd905SAlfredo Cardigliano {
1053cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
1063cdfd905SAlfredo Cardigliano 	uint32_t i;
1073cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
1083cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1093cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
1103cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
1113cdfd905SAlfredo Cardigliano 
1123cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1133cdfd905SAlfredo Cardigliano 
1143cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1153cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1163cdfd905SAlfredo Cardigliano 			lif->port_id);
1173cdfd905SAlfredo Cardigliano 		return;
1183cdfd905SAlfredo Cardigliano 	}
1193cdfd905SAlfredo Cardigliano 
1203cdfd905SAlfredo Cardigliano 	/* RX */
1213cdfd905SAlfredo Cardigliano 
1223cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1233cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1243cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1253cdfd905SAlfredo Cardigliano 
1263cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1273cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1283cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1293cdfd905SAlfredo Cardigliano 
1303cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1313cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1323cdfd905SAlfredo Cardigliano 		stats->imissed +=
1333cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1343cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1353cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1363cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1373cdfd905SAlfredo Cardigliano 	}
1383cdfd905SAlfredo Cardigliano 
1393cdfd905SAlfredo Cardigliano 	stats->imissed +=
1403cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1413cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1423cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1433cdfd905SAlfredo Cardigliano 
1443cdfd905SAlfredo Cardigliano 	stats->imissed +=
1453cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
1463cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1473cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
1483cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1493cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1503cdfd905SAlfredo Cardigliano 
1513cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
1523cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1533cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1543cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1553cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1563cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1573cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1583cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1593cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1603cdfd905SAlfredo Cardigliano 	}
1613cdfd905SAlfredo Cardigliano 
1623cdfd905SAlfredo Cardigliano 	/* TX */
1633cdfd905SAlfredo Cardigliano 
1643cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1653cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1663cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1673cdfd905SAlfredo Cardigliano 
1683cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1693cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1703cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1713cdfd905SAlfredo Cardigliano 
1723cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1733cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1743cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1753cdfd905SAlfredo Cardigliano 	}
1763cdfd905SAlfredo Cardigliano 
1773cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1783cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1793cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1803cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1813cdfd905SAlfredo Cardigliano 
1823cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1833cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1843cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1853cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1863cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1873cdfd905SAlfredo Cardigliano 
1883cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
1893cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1903cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1913cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1923cdfd905SAlfredo Cardigliano 	}
1933cdfd905SAlfredo Cardigliano }
1943cdfd905SAlfredo Cardigliano 
1953cdfd905SAlfredo Cardigliano void
1963cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1973cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1983cdfd905SAlfredo Cardigliano {
1993cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
2003cdfd905SAlfredo Cardigliano 
2013cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
2023cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
2033cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
2043cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
2053cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
2063cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
2073cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
2083cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
2093cdfd905SAlfredo Cardigliano }
2103cdfd905SAlfredo Cardigliano 
2113cdfd905SAlfredo Cardigliano void
2123cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2133cdfd905SAlfredo Cardigliano {
2143cdfd905SAlfredo Cardigliano 	uint32_t i;
2153cdfd905SAlfredo Cardigliano 
2163cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
2173cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
2183cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
2193cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 0,
2203cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2213cdfd905SAlfredo Cardigliano 	}
2223cdfd905SAlfredo Cardigliano 
2233cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2243cdfd905SAlfredo Cardigliano }
2253cdfd905SAlfredo Cardigliano 
2263cdfd905SAlfredo Cardigliano void
2273cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2283cdfd905SAlfredo Cardigliano {
2293cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2303cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2313cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2323cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2333cdfd905SAlfredo Cardigliano 
2343cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2353cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2363cdfd905SAlfredo Cardigliano }
2373cdfd905SAlfredo Cardigliano 
2383cdfd905SAlfredo Cardigliano void
2393cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2403cdfd905SAlfredo Cardigliano {
2413cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2423cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2433cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2443cdfd905SAlfredo Cardigliano 
2453cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2463cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2473cdfd905SAlfredo Cardigliano }
2483cdfd905SAlfredo Cardigliano 
249598f6726SAlfredo Cardigliano static int
25054fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
251598f6726SAlfredo Cardigliano {
25254fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
25354fe083fSAlfredo Cardigliano 		.pending_work = true,
25454fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
25554fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
25654fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_MAC,
25754fe083fSAlfredo Cardigliano 		},
25854fe083fSAlfredo Cardigliano 	};
25954fe083fSAlfredo Cardigliano 	int err;
26054fe083fSAlfredo Cardigliano 
26154fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
26254fe083fSAlfredo Cardigliano 
26354fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
26454fe083fSAlfredo Cardigliano 	if (err)
26554fe083fSAlfredo Cardigliano 		return err;
26654fe083fSAlfredo Cardigliano 
26754fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
26854fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
26954fe083fSAlfredo Cardigliano 
27054fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
27154fe083fSAlfredo Cardigliano }
27254fe083fSAlfredo Cardigliano 
27354fe083fSAlfredo Cardigliano static int
27454fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
27554fe083fSAlfredo Cardigliano {
27654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
27754fe083fSAlfredo Cardigliano 		.pending_work = true,
27854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
27954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
28054fe083fSAlfredo Cardigliano 		},
28154fe083fSAlfredo Cardigliano 	};
28254fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
28354fe083fSAlfredo Cardigliano 	int err;
28454fe083fSAlfredo Cardigliano 
28554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
28654fe083fSAlfredo Cardigliano 
28754fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
28854fe083fSAlfredo Cardigliano 
28954fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
29054fe083fSAlfredo Cardigliano 	if (!f) {
29154fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
29254fe083fSAlfredo Cardigliano 		return -ENOENT;
29354fe083fSAlfredo Cardigliano 	}
29454fe083fSAlfredo Cardigliano 
29554fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
29654fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
29754fe083fSAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
29954fe083fSAlfredo Cardigliano 
30054fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
30154fe083fSAlfredo Cardigliano 	if (err)
30254fe083fSAlfredo Cardigliano 		return err;
30354fe083fSAlfredo Cardigliano 
30454fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
30554fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
306598f6726SAlfredo Cardigliano 
307598f6726SAlfredo Cardigliano 	return 0;
308598f6726SAlfredo Cardigliano }
309598f6726SAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano int
31154fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
31254fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
31354fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
314598f6726SAlfredo Cardigliano {
31554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31654fe083fSAlfredo Cardigliano 
31754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31854fe083fSAlfredo Cardigliano 
31954fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
32054fe083fSAlfredo Cardigliano }
32154fe083fSAlfredo Cardigliano 
32254fe083fSAlfredo Cardigliano void
32375f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
32454fe083fSAlfredo Cardigliano {
32554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
32654fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
32775f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
32854fe083fSAlfredo Cardigliano 
32954fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33054fe083fSAlfredo Cardigliano 
33154fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
33254fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
33354fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
33454fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
33554fe083fSAlfredo Cardigliano 		return;
33654fe083fSAlfredo Cardigliano 	}
33754fe083fSAlfredo Cardigliano 
33875f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
33975f96902SAndrew Boyer 
34075f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
34154fe083fSAlfredo Cardigliano 		return;
34254fe083fSAlfredo Cardigliano 
34375f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
34454fe083fSAlfredo Cardigliano }
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano int
34754fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
34854fe083fSAlfredo Cardigliano {
34954fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
35054fe083fSAlfredo Cardigliano 
35154fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
35254fe083fSAlfredo Cardigliano 
35354fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
35454fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
35554fe083fSAlfredo Cardigliano 		return -1;
35654fe083fSAlfredo Cardigliano 	}
35754fe083fSAlfredo Cardigliano 
35854fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
35954fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
36054fe083fSAlfredo Cardigliano 			lif->mac_addr);
36154fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
36254fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
36354fe083fSAlfredo Cardigliano 	}
36454fe083fSAlfredo Cardigliano 
36554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
36654fe083fSAlfredo Cardigliano 
36754fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
36854fe083fSAlfredo Cardigliano 
36954fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
37054fe083fSAlfredo Cardigliano }
37154fe083fSAlfredo Cardigliano 
37254fe083fSAlfredo Cardigliano static int
37354fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
37454fe083fSAlfredo Cardigliano {
37554fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
37654fe083fSAlfredo Cardigliano 		.pending_work = true,
37754fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
37854fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
37954fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_VLAN,
38054fe083fSAlfredo Cardigliano 			.vlan.vlan = vid,
38154fe083fSAlfredo Cardigliano 		},
38254fe083fSAlfredo Cardigliano 	};
38354fe083fSAlfredo Cardigliano 	int err;
38454fe083fSAlfredo Cardigliano 
38554fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
38654fe083fSAlfredo Cardigliano 	if (err)
38754fe083fSAlfredo Cardigliano 		return err;
38854fe083fSAlfredo Cardigliano 
38954fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
39054fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
39154fe083fSAlfredo Cardigliano 
39254fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
39354fe083fSAlfredo Cardigliano }
39454fe083fSAlfredo Cardigliano 
39554fe083fSAlfredo Cardigliano static int
39654fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
39754fe083fSAlfredo Cardigliano {
39854fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
39954fe083fSAlfredo Cardigliano 		.pending_work = true,
40054fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
40154fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
40254fe083fSAlfredo Cardigliano 		},
40354fe083fSAlfredo Cardigliano 	};
40454fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
40554fe083fSAlfredo Cardigliano 	int err;
40654fe083fSAlfredo Cardigliano 
40754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
40854fe083fSAlfredo Cardigliano 
40954fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
41054fe083fSAlfredo Cardigliano 
41154fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
41254fe083fSAlfredo Cardigliano 	if (!f) {
41354fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
41454fe083fSAlfredo Cardigliano 		return -ENOENT;
41554fe083fSAlfredo Cardigliano 	}
41654fe083fSAlfredo Cardigliano 
41754fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
41854fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
41954fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
42054fe083fSAlfredo Cardigliano 
42154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
42254fe083fSAlfredo Cardigliano 	if (err)
42354fe083fSAlfredo Cardigliano 		return err;
42454fe083fSAlfredo Cardigliano 
42554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
42654fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
427598f6726SAlfredo Cardigliano 
428598f6726SAlfredo Cardigliano 	return 0;
429598f6726SAlfredo Cardigliano }
430598f6726SAlfredo Cardigliano 
43154fe083fSAlfredo Cardigliano int
43254fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
43354fe083fSAlfredo Cardigliano 		int on)
43454fe083fSAlfredo Cardigliano {
43554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
43654fe083fSAlfredo Cardigliano 	int err;
43754fe083fSAlfredo Cardigliano 
43854fe083fSAlfredo Cardigliano 	if (on)
43954fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
44054fe083fSAlfredo Cardigliano 	else
44154fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
44254fe083fSAlfredo Cardigliano 
44354fe083fSAlfredo Cardigliano 	return err;
44454fe083fSAlfredo Cardigliano }
44554fe083fSAlfredo Cardigliano 
446598f6726SAlfredo Cardigliano static void
447598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
448598f6726SAlfredo Cardigliano {
449598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
450598f6726SAlfredo Cardigliano 		.pending_work = true,
451598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
452598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
453598f6726SAlfredo Cardigliano 			.rx_mode = rx_mode,
454598f6726SAlfredo Cardigliano 		},
455598f6726SAlfredo Cardigliano 	};
456598f6726SAlfredo Cardigliano 	int err;
457598f6726SAlfredo Cardigliano 
458598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
459598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
460598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
461598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
462598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
463598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
464598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
465598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
466598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
467598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
468598f6726SAlfredo Cardigliano 
469598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
470598f6726SAlfredo Cardigliano 	if (err)
471598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
472598f6726SAlfredo Cardigliano }
473598f6726SAlfredo Cardigliano 
474598f6726SAlfredo Cardigliano static void
475598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
476598f6726SAlfredo Cardigliano {
477598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
478598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
479598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
480598f6726SAlfredo Cardigliano 	}
481598f6726SAlfredo Cardigliano }
482598f6726SAlfredo Cardigliano 
48354fe083fSAlfredo Cardigliano int
48454fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
48554fe083fSAlfredo Cardigliano {
48654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48754fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48854fe083fSAlfredo Cardigliano 
48954fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
49054fe083fSAlfredo Cardigliano 
49154fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
49254fe083fSAlfredo Cardigliano 
49354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49454fe083fSAlfredo Cardigliano 
49554fe083fSAlfredo Cardigliano 	return 0;
49654fe083fSAlfredo Cardigliano }
49754fe083fSAlfredo Cardigliano 
49854fe083fSAlfredo Cardigliano int
49954fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
50054fe083fSAlfredo Cardigliano {
50154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50254fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50354fe083fSAlfredo Cardigliano 
50454fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
50554fe083fSAlfredo Cardigliano 
50654fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50754fe083fSAlfredo Cardigliano 
50854fe083fSAlfredo Cardigliano 	return 0;
50954fe083fSAlfredo Cardigliano }
51054fe083fSAlfredo Cardigliano 
51154fe083fSAlfredo Cardigliano int
51254fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
51354fe083fSAlfredo Cardigliano {
51454fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51554fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51654fe083fSAlfredo Cardigliano 
51754fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
51854fe083fSAlfredo Cardigliano 
51954fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52054fe083fSAlfredo Cardigliano 
52154fe083fSAlfredo Cardigliano 	return 0;
52254fe083fSAlfredo Cardigliano }
52354fe083fSAlfredo Cardigliano 
52454fe083fSAlfredo Cardigliano int
52554fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
52654fe083fSAlfredo Cardigliano {
52754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
52854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
52954fe083fSAlfredo Cardigliano 
53054fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
53154fe083fSAlfredo Cardigliano 
53254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
53354fe083fSAlfredo Cardigliano 
53454fe083fSAlfredo Cardigliano 	return 0;
53554fe083fSAlfredo Cardigliano }
536598f6726SAlfredo Cardigliano 
537598f6726SAlfredo Cardigliano int
538598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
539598f6726SAlfredo Cardigliano {
540598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
541598f6726SAlfredo Cardigliano 		.pending_work = true,
542598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
543598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
544598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
545598f6726SAlfredo Cardigliano 			.mtu = new_mtu,
546598f6726SAlfredo Cardigliano 		},
547598f6726SAlfredo Cardigliano 	};
548598f6726SAlfredo Cardigliano 	int err;
549598f6726SAlfredo Cardigliano 
550598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
551598f6726SAlfredo Cardigliano 	if (err)
552598f6726SAlfredo Cardigliano 		return err;
553598f6726SAlfredo Cardigliano 
554598f6726SAlfredo Cardigliano 	return 0;
555598f6726SAlfredo Cardigliano }
556598f6726SAlfredo Cardigliano 
557598f6726SAlfredo Cardigliano int
55801a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
55901a6c311SAlfredo Cardigliano {
56001a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
56101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
56201a6c311SAlfredo Cardigliano 	unsigned long index;
56301a6c311SAlfredo Cardigliano 
56401a6c311SAlfredo Cardigliano 	/*
56501a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
56601a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5674ae96cb8SAndrew Boyer 	 * which has index = 0)
56801a6c311SAlfredo Cardigliano 	 */
56901a6c311SAlfredo Cardigliano 
57001a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
57101a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
57201a6c311SAlfredo Cardigliano 			break;
57301a6c311SAlfredo Cardigliano 
57401a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
57501a6c311SAlfredo Cardigliano 		return -ENOSPC;
57601a6c311SAlfredo Cardigliano 
57701a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
57801a6c311SAlfredo Cardigliano 
57901a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
58001a6c311SAlfredo Cardigliano 
58101a6c311SAlfredo Cardigliano 	return 0;
58201a6c311SAlfredo Cardigliano }
58301a6c311SAlfredo Cardigliano 
58401a6c311SAlfredo Cardigliano void
58501a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
58601a6c311SAlfredo Cardigliano {
58701a6c311SAlfredo Cardigliano 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
58801a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
58901a6c311SAlfredo Cardigliano }
59001a6c311SAlfredo Cardigliano 
59101a6c311SAlfredo Cardigliano static int
59201a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
59301a6c311SAlfredo Cardigliano 		uint32_t index,
59401a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
59501a6c311SAlfredo Cardigliano 		uint32_t num_descs,
59601a6c311SAlfredo Cardigliano 		uint32_t desc_size,
59701a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
59801a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
5991abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
60001a6c311SAlfredo Cardigliano {
60101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
60201a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
60301a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
60401a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
60501a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
60601a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
60701a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
60801a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
60901a6c311SAlfredo Cardigliano 	int err;
61001a6c311SAlfredo Cardigliano 
61101a6c311SAlfredo Cardigliano 	*qcq = NULL;
61201a6c311SAlfredo Cardigliano 
61301a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
61401a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
61501a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
61601a6c311SAlfredo Cardigliano 
61701a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
61801a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
61901a6c311SAlfredo Cardigliano 	/*
62001a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
62101a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
62201a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
62301a6c311SAlfredo Cardigliano 	 */
62401a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
62501a6c311SAlfredo Cardigliano 
62601a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
62701a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
62801a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
62901a6c311SAlfredo Cardigliano 	}
63001a6c311SAlfredo Cardigliano 
63101a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
63201a6c311SAlfredo Cardigliano 	if (!new) {
63301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
63401a6c311SAlfredo Cardigliano 		return -ENOMEM;
63501a6c311SAlfredo Cardigliano 	}
63601a6c311SAlfredo Cardigliano 
63701a6c311SAlfredo Cardigliano 	new->lif = lif;
63801a6c311SAlfredo Cardigliano 	new->flags = flags;
63901a6c311SAlfredo Cardigliano 
64001a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
64101a6c311SAlfredo Cardigliano 	if (!new->q.info) {
64201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
64301a6c311SAlfredo Cardigliano 		return -ENOMEM;
64401a6c311SAlfredo Cardigliano 	}
64501a6c311SAlfredo Cardigliano 
64601a6c311SAlfredo Cardigliano 	new->q.type = type;
64701a6c311SAlfredo Cardigliano 
64801a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
6491abf69fcSAndrew Boyer 		desc_size, sg_desc_size);
65001a6c311SAlfredo Cardigliano 	if (err) {
65101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
65201a6c311SAlfredo Cardigliano 		return err;
65301a6c311SAlfredo Cardigliano 	}
65401a6c311SAlfredo Cardigliano 
65501a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR) {
65601a6c311SAlfredo Cardigliano 		err = ionic_intr_alloc(lif, &new->intr);
65701a6c311SAlfredo Cardigliano 		if (err)
65801a6c311SAlfredo Cardigliano 			return err;
65901a6c311SAlfredo Cardigliano 
66001a6c311SAlfredo Cardigliano 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
66101a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
66201a6c311SAlfredo Cardigliano 	} else {
66301a6c311SAlfredo Cardigliano 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
66401a6c311SAlfredo Cardigliano 	}
66501a6c311SAlfredo Cardigliano 
66601a6c311SAlfredo Cardigliano 	err = ionic_cq_init(lif, &new->cq, &new->intr,
66701a6c311SAlfredo Cardigliano 		num_descs, cq_desc_size);
66801a6c311SAlfredo Cardigliano 	if (err) {
66901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
67001a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
67101a6c311SAlfredo Cardigliano 	}
67201a6c311SAlfredo Cardigliano 
67301a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
67401a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
67501a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
67601a6c311SAlfredo Cardigliano 
67701a6c311SAlfredo Cardigliano 	if (!new->base_z) {
67801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
67901a6c311SAlfredo Cardigliano 		err = -ENOMEM;
68001a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
68101a6c311SAlfredo Cardigliano 	}
68201a6c311SAlfredo Cardigliano 
68301a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
68401a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
68501a6c311SAlfredo Cardigliano 	new->total_size = total_size;
68601a6c311SAlfredo Cardigliano 
68701a6c311SAlfredo Cardigliano 	q_base = new->base;
68801a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
68901a6c311SAlfredo Cardigliano 
69001a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
69101a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
69201a6c311SAlfredo Cardigliano 
69301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
69401a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
69501a6c311SAlfredo Cardigliano 			PAGE_SIZE);
69601a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
69701a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
69801a6c311SAlfredo Cardigliano 	}
69901a6c311SAlfredo Cardigliano 
7004ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
7014ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
70201a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
70301a6c311SAlfredo Cardigliano 
70401a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
70501a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
70601a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
70701a6c311SAlfredo Cardigliano 
70801a6c311SAlfredo Cardigliano 	*qcq = new;
70901a6c311SAlfredo Cardigliano 
71001a6c311SAlfredo Cardigliano 	return 0;
71101a6c311SAlfredo Cardigliano 
71201a6c311SAlfredo Cardigliano err_out_free_intr:
71301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR)
71401a6c311SAlfredo Cardigliano 		ionic_intr_free(lif, &new->intr);
71501a6c311SAlfredo Cardigliano 
71601a6c311SAlfredo Cardigliano 	return err;
71701a6c311SAlfredo Cardigliano }
71801a6c311SAlfredo Cardigliano 
71901a6c311SAlfredo Cardigliano void
72001a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
72101a6c311SAlfredo Cardigliano {
72201a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
72301a6c311SAlfredo Cardigliano 		qcq->base = NULL;
72401a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
72501a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
72601a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
72701a6c311SAlfredo Cardigliano 	}
72801a6c311SAlfredo Cardigliano 
72901a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
73001a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
73101a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
73201a6c311SAlfredo Cardigliano 	}
73301a6c311SAlfredo Cardigliano 
73401a6c311SAlfredo Cardigliano 	rte_free(qcq);
73501a6c311SAlfredo Cardigliano }
73601a6c311SAlfredo Cardigliano 
737a27d9013SAlfredo Cardigliano int
738a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_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_RXQ, index, "rx", flags,
746a27d9013SAlfredo Cardigliano 		nrxq_descs,
747a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
748a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
749a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
7501abf69fcSAndrew Boyer 		&lif->rxqcqs[index]);
751a27d9013SAlfredo Cardigliano 	if (err)
752a27d9013SAlfredo Cardigliano 		return err;
753a27d9013SAlfredo Cardigliano 
754a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
755a27d9013SAlfredo Cardigliano 
756a27d9013SAlfredo Cardigliano 	return 0;
757a27d9013SAlfredo Cardigliano }
758a27d9013SAlfredo Cardigliano 
759a27d9013SAlfredo Cardigliano int
760a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
761a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
762a27d9013SAlfredo Cardigliano {
763a27d9013SAlfredo Cardigliano 	uint32_t flags;
764a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
765a27d9013SAlfredo Cardigliano 
766a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
767a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
768a27d9013SAlfredo Cardigliano 		ntxq_descs,
769a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
770a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
771a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_sg_desc),
7721abf69fcSAndrew Boyer 		&lif->txqcqs[index]);
773a27d9013SAlfredo Cardigliano 	if (err)
774a27d9013SAlfredo Cardigliano 		return err;
775a27d9013SAlfredo Cardigliano 
776a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
777a27d9013SAlfredo Cardigliano 
778a27d9013SAlfredo Cardigliano 	return 0;
779a27d9013SAlfredo Cardigliano }
780a27d9013SAlfredo Cardigliano 
78101a6c311SAlfredo Cardigliano static int
78201a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
78301a6c311SAlfredo Cardigliano {
78401a6c311SAlfredo Cardigliano 	uint32_t flags;
78501a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
78601a6c311SAlfredo Cardigliano 
78701a6c311SAlfredo Cardigliano 	flags = 0;
78801a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
78901a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
79001a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
79101a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
79201a6c311SAlfredo Cardigliano 		0,
7931abf69fcSAndrew Boyer 		&lif->adminqcq);
79427b942c8SAlfredo Cardigliano 	if (err)
79527b942c8SAlfredo Cardigliano 		return err;
79601a6c311SAlfredo Cardigliano 
79727b942c8SAlfredo Cardigliano 	return 0;
79827b942c8SAlfredo Cardigliano }
79927b942c8SAlfredo Cardigliano 
80027b942c8SAlfredo Cardigliano static int
80127b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
80227b942c8SAlfredo Cardigliano {
80327b942c8SAlfredo Cardigliano 	uint32_t flags;
80427b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
80527b942c8SAlfredo Cardigliano 
80627b942c8SAlfredo Cardigliano 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
80727b942c8SAlfredo Cardigliano 
80827b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
80927b942c8SAlfredo Cardigliano 		flags,
81027b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
81127b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
81227b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
81327b942c8SAlfredo Cardigliano 		0,
8141abf69fcSAndrew Boyer 		&lif->notifyqcq);
81501a6c311SAlfredo Cardigliano 	if (err)
81601a6c311SAlfredo Cardigliano 		return err;
81701a6c311SAlfredo Cardigliano 
81801a6c311SAlfredo Cardigliano 	return 0;
81901a6c311SAlfredo Cardigliano }
82001a6c311SAlfredo Cardigliano 
821c67719e1SAlfredo Cardigliano static void *
822c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
823c67719e1SAlfredo Cardigliano {
824c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
825c67719e1SAlfredo Cardigliano 
826c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
827c67719e1SAlfredo Cardigliano 		return NULL;
828c67719e1SAlfredo Cardigliano 
829c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
830c67719e1SAlfredo Cardigliano }
831c67719e1SAlfredo Cardigliano 
832669c8de6SAlfredo Cardigliano int
833669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
834669c8de6SAlfredo Cardigliano {
835c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
836669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
83701a6c311SAlfredo Cardigliano 	int err;
838669c8de6SAlfredo Cardigliano 
8394ae96cb8SAndrew Boyer 	/*
8404ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
8414ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
8424ae96cb8SAndrew Boyer 	 */
8434ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
8444ae96cb8SAndrew Boyer 
8454ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
846669c8de6SAlfredo Cardigliano 
847669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
848669c8de6SAlfredo Cardigliano 
84901a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
85001a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
85101a6c311SAlfredo Cardigliano 
85200b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
853c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
854c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
855c67719e1SAlfredo Cardigliano 		return -ENOMEM;
856c67719e1SAlfredo Cardigliano 	}
857c67719e1SAlfredo Cardigliano 
858a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
859a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
860a27d9013SAlfredo Cardigliano 
861a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
862a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
863a27d9013SAlfredo Cardigliano 		return -ENOMEM;
864a27d9013SAlfredo Cardigliano 	}
865a27d9013SAlfredo Cardigliano 
866a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
867a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
868a27d9013SAlfredo Cardigliano 
869a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
870a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
871a27d9013SAlfredo Cardigliano 		return -ENOMEM;
872a27d9013SAlfredo Cardigliano 	}
873a27d9013SAlfredo Cardigliano 
87427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
87527b942c8SAlfredo Cardigliano 
87627b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
87727b942c8SAlfredo Cardigliano 	if (err) {
87827b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
87927b942c8SAlfredo Cardigliano 		return err;
88027b942c8SAlfredo Cardigliano 	}
88127b942c8SAlfredo Cardigliano 
88227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
88327b942c8SAlfredo Cardigliano 
88401a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
88501a6c311SAlfredo Cardigliano 	if (err) {
88601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
88701a6c311SAlfredo Cardigliano 		return err;
88801a6c311SAlfredo Cardigliano 	}
88901a6c311SAlfredo Cardigliano 
89001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
89101a6c311SAlfredo Cardigliano 
892669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
893669c8de6SAlfredo Cardigliano 
894669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
895669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
896669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
897669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
898669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
899669c8de6SAlfredo Cardigliano 		return -ENOMEM;
900669c8de6SAlfredo Cardigliano 	}
901669c8de6SAlfredo Cardigliano 
902669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
903669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
904669c8de6SAlfredo Cardigliano 
905669c8de6SAlfredo Cardigliano 	return 0;
906669c8de6SAlfredo Cardigliano }
907669c8de6SAlfredo Cardigliano 
908669c8de6SAlfredo Cardigliano void
909669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
910669c8de6SAlfredo Cardigliano {
91127b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
91227b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
91327b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
91427b942c8SAlfredo Cardigliano 	}
91527b942c8SAlfredo Cardigliano 
91601a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
91701a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
91801a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
91901a6c311SAlfredo Cardigliano 	}
92001a6c311SAlfredo Cardigliano 
921a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
922a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
923a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
924a27d9013SAlfredo Cardigliano 	}
925a27d9013SAlfredo Cardigliano 
926a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
927a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
928a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
929a27d9013SAlfredo Cardigliano 	}
930a27d9013SAlfredo Cardigliano 
931669c8de6SAlfredo Cardigliano 	if (lif->info) {
932669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
933669c8de6SAlfredo Cardigliano 		lif->info = NULL;
934669c8de6SAlfredo Cardigliano 	}
935669c8de6SAlfredo Cardigliano }
936669c8de6SAlfredo Cardigliano 
937175e4e7eSAndrew Boyer void
938175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
939175e4e7eSAndrew Boyer {
940175e4e7eSAndrew Boyer 	uint32_t i;
941175e4e7eSAndrew Boyer 
942175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
943175e4e7eSAndrew Boyer 		ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]);
944175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
945175e4e7eSAndrew Boyer 	}
946175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
947175e4e7eSAndrew Boyer 		ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]);
948175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
949175e4e7eSAndrew Boyer 	}
950175e4e7eSAndrew Boyer }
951175e4e7eSAndrew Boyer 
95222e7171bSAlfredo Cardigliano int
95322e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
95422e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
95522e7171bSAlfredo Cardigliano {
95622e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
95722e7171bSAlfredo Cardigliano 		.pending_work = true,
95822e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
95922e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
96022e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
96122e7171bSAlfredo Cardigliano 			.rss.types = types,
96222e7171bSAlfredo Cardigliano 			.rss.addr = lif->rss_ind_tbl_pa,
96322e7171bSAlfredo Cardigliano 		},
96422e7171bSAlfredo Cardigliano 	};
96522e7171bSAlfredo Cardigliano 	unsigned int i;
96622e7171bSAlfredo Cardigliano 
96722e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
96822e7171bSAlfredo Cardigliano 
96922e7171bSAlfredo Cardigliano 	lif->rss_types = types;
97022e7171bSAlfredo Cardigliano 
97122e7171bSAlfredo Cardigliano 	if (key)
97222e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
97322e7171bSAlfredo Cardigliano 
97422e7171bSAlfredo Cardigliano 	if (indir)
97522e7171bSAlfredo Cardigliano 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
97622e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
97722e7171bSAlfredo Cardigliano 
97822e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
97922e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
98022e7171bSAlfredo Cardigliano 
98122e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
98222e7171bSAlfredo Cardigliano }
98322e7171bSAlfredo Cardigliano 
98422e7171bSAlfredo Cardigliano static int
98522e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
98622e7171bSAlfredo Cardigliano {
98722e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
98822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
98922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
99022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
99122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
99222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
99322e7171bSAlfredo Cardigliano 	};
99422e7171bSAlfredo Cardigliano 	uint32_t i;
9953d845eddSAndrew Boyer 	uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
99622e7171bSAlfredo Cardigliano 
99722e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
99822e7171bSAlfredo Cardigliano 
9993d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
100022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
10013d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
10023d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
10033d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
100422e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
100522e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
100622e7171bSAlfredo Cardigliano 			return -ENOMEM;
100722e7171bSAlfredo Cardigliano 		}
100822e7171bSAlfredo Cardigliano 
100922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
101022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
10113d845eddSAndrew Boyer 	}
10123d845eddSAndrew Boyer 
10133d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
10143d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
101522e7171bSAlfredo Cardigliano 
101622e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
10173d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
101822e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
10193d845eddSAndrew Boyer 	}
102022e7171bSAlfredo Cardigliano 
10213d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
102222e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
102322e7171bSAlfredo Cardigliano }
102422e7171bSAlfredo Cardigliano 
102522e7171bSAlfredo Cardigliano static void
102622e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
102722e7171bSAlfredo Cardigliano {
102822e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
102922e7171bSAlfredo Cardigliano 		return;
103022e7171bSAlfredo Cardigliano 
103122e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
103222e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
103322e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
103422e7171bSAlfredo Cardigliano 
103522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
103622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
103722e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
103822e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
103922e7171bSAlfredo Cardigliano 	}
104022e7171bSAlfredo Cardigliano }
104122e7171bSAlfredo Cardigliano 
104201a6c311SAlfredo Cardigliano static void
104301a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
104401a6c311SAlfredo Cardigliano {
104501a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
104601a6c311SAlfredo Cardigliano 
104701a6c311SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
104801a6c311SAlfredo Cardigliano 		return;
104901a6c311SAlfredo Cardigliano 
105001a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
105101a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
105201a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
105301a6c311SAlfredo Cardigliano 
105401a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
105501a6c311SAlfredo Cardigliano }
105601a6c311SAlfredo Cardigliano 
1057a27d9013SAlfredo Cardigliano void
1058a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1059a27d9013SAlfredo Cardigliano {
1060a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1061a27d9013SAlfredo Cardigliano }
1062a27d9013SAlfredo Cardigliano 
1063a27d9013SAlfredo Cardigliano void
1064a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1065a27d9013SAlfredo Cardigliano {
1066a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1067a27d9013SAlfredo Cardigliano }
1068a27d9013SAlfredo Cardigliano 
106901a6c311SAlfredo Cardigliano bool
107001a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
107101a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
107201a6c311SAlfredo Cardigliano {
107301a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
107401a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
107501a6c311SAlfredo Cardigliano 
107601a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
107701a6c311SAlfredo Cardigliano 		return false;
107801a6c311SAlfredo Cardigliano 
107901a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
108001a6c311SAlfredo Cardigliano 
108101a6c311SAlfredo Cardigliano 	return true;
108201a6c311SAlfredo Cardigliano }
108301a6c311SAlfredo Cardigliano 
108401a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
108501a6c311SAlfredo Cardigliano int
108601a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
108701a6c311SAlfredo Cardigliano 		void *cb_arg)
108801a6c311SAlfredo Cardigliano {
108901a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
109001a6c311SAlfredo Cardigliano 	uint32_t work_done;
109101a6c311SAlfredo Cardigliano 
109201a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
109301a6c311SAlfredo Cardigliano 
109401a6c311SAlfredo Cardigliano 	return work_done;
109501a6c311SAlfredo Cardigliano }
109601a6c311SAlfredo Cardigliano 
109727b942c8SAlfredo Cardigliano static void
109827b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
109927b942c8SAlfredo Cardigliano {
110027b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
110127b942c8SAlfredo Cardigliano 	bool link_up;
110227b942c8SAlfredo Cardigliano 
110327b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
110427b942c8SAlfredo Cardigliano 
110527b942c8SAlfredo Cardigliano 	if (!lif->info)
110627b942c8SAlfredo Cardigliano 		return;
110727b942c8SAlfredo Cardigliano 
110827b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
110927b942c8SAlfredo Cardigliano 
111027b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
111127b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
111227b942c8SAlfredo Cardigliano 		return;
111327b942c8SAlfredo Cardigliano 
111427b942c8SAlfredo Cardigliano 	if (link_up) {
111527b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
1116be63459eSAndrew Boyer 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1117be63459eSAndrew Boyer 			adapter->link_speed);
111827b942c8SAlfredo Cardigliano 	} else {
111927b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
112027b942c8SAlfredo Cardigliano 	}
112127b942c8SAlfredo Cardigliano 
112227b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
1123be63459eSAndrew Boyer 	ionic_dev_link_update(lif->eth_dev, 0);
1124be63459eSAndrew Boyer }
1125be63459eSAndrew Boyer 
1126be63459eSAndrew Boyer static void
1127be63459eSAndrew Boyer ionic_lif_handle_fw_down(struct ionic_lif *lif)
1128be63459eSAndrew Boyer {
1129be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_FW_RESET)
1130be63459eSAndrew Boyer 		return;
1131be63459eSAndrew Boyer 
1132be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_FW_RESET;
1133be63459eSAndrew Boyer 
1134be63459eSAndrew Boyer 	if (lif->state & IONIC_LIF_F_UP) {
1135be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1136be63459eSAndrew Boyer 			"Surprise FW stop, stopping %s\n", lif->name);
1137be63459eSAndrew Boyer 		ionic_lif_stop(lif);
1138be63459eSAndrew Boyer 	}
1139be63459eSAndrew Boyer 
1140be63459eSAndrew Boyer 	IONIC_PRINT(NOTICE, "FW down, %s stopped", lif->name);
114127b942c8SAlfredo Cardigliano }
114227b942c8SAlfredo Cardigliano 
114327b942c8SAlfredo Cardigliano static bool
114427b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
114527b942c8SAlfredo Cardigliano {
114627b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
114727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
114827b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
114927b942c8SAlfredo Cardigliano 
115027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
115127b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
115227b942c8SAlfredo Cardigliano 
115327b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
115427b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
115527b942c8SAlfredo Cardigliano 		return false;
115627b942c8SAlfredo Cardigliano 
115727b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
115827b942c8SAlfredo Cardigliano 
115927b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
116027b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
116127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
1162be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_LINK_CHANGE %s "
1163be63459eSAndrew Boyer 			"eid=%jd link_status=%d link_speed=%d",
1164be63459eSAndrew Boyer 			lif->name,
116527b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
116627b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
116727b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
116827b942c8SAlfredo Cardigliano 
116927b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
117027b942c8SAlfredo Cardigliano 		break;
1171be63459eSAndrew Boyer 
1172be63459eSAndrew Boyer 	case IONIC_EVENT_RESET:
1173be63459eSAndrew Boyer 		IONIC_PRINT(NOTICE,
1174be63459eSAndrew Boyer 			"Notifyq IONIC_EVENT_RESET %s "
1175be63459eSAndrew Boyer 			"eid=%jd, reset_code=%d state=%d",
1176be63459eSAndrew Boyer 			lif->name,
1177be63459eSAndrew Boyer 			cq_desc->event.eid,
1178be63459eSAndrew Boyer 			cq_desc->reset.reset_code,
1179be63459eSAndrew Boyer 			cq_desc->reset.state);
1180be63459eSAndrew Boyer 		ionic_lif_handle_fw_down(lif);
1181be63459eSAndrew Boyer 		break;
1182be63459eSAndrew Boyer 
118327b942c8SAlfredo Cardigliano 	default:
118427b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
118527b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
118627b942c8SAlfredo Cardigliano 		break;
118727b942c8SAlfredo Cardigliano 	}
118827b942c8SAlfredo Cardigliano 
118927b942c8SAlfredo Cardigliano 	return true;
119027b942c8SAlfredo Cardigliano }
119127b942c8SAlfredo Cardigliano 
119227b942c8SAlfredo Cardigliano int
119327b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
119427b942c8SAlfredo Cardigliano {
119527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
119627b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
119727b942c8SAlfredo Cardigliano 	uint32_t work_done;
119827b942c8SAlfredo Cardigliano 
119927b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
120027b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
120127b942c8SAlfredo Cardigliano 		return -1;
120227b942c8SAlfredo Cardigliano 	}
120327b942c8SAlfredo Cardigliano 
120427b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
120527b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
120627b942c8SAlfredo Cardigliano 
120727b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
120827b942c8SAlfredo Cardigliano 
120927b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
121027b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
121127b942c8SAlfredo Cardigliano 
121227b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
121327b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
121427b942c8SAlfredo Cardigliano 
121527b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
121627b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
121727b942c8SAlfredo Cardigliano 
121827b942c8SAlfredo Cardigliano 	return 0;
121927b942c8SAlfredo Cardigliano }
122027b942c8SAlfredo Cardigliano 
122101a6c311SAlfredo Cardigliano static int
122201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
122301a6c311SAlfredo Cardigliano {
122401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
122501a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
122601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
122701a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
122801a6c311SAlfredo Cardigliano 	int err;
122901a6c311SAlfredo Cardigliano 
123000b65da5SAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, qcq, qcq->intr.index);
123101a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
123201a6c311SAlfredo Cardigliano 	if (err)
123301a6c311SAlfredo Cardigliano 		return err;
123401a6c311SAlfredo Cardigliano 
123501a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
123601a6c311SAlfredo Cardigliano 
123701a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
123801a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
123901a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
124001a6c311SAlfredo Cardigliano 
124101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
124201a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
124301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
124401a6c311SAlfredo Cardigliano 
124501a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
124601a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
124701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
124801a6c311SAlfredo Cardigliano 
124901a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
125001a6c311SAlfredo Cardigliano 
125101a6c311SAlfredo Cardigliano 	return 0;
125201a6c311SAlfredo Cardigliano }
125301a6c311SAlfredo Cardigliano 
125427b942c8SAlfredo Cardigliano static int
125527b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
125627b942c8SAlfredo Cardigliano {
125727b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
125827b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
125927b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
126027b942c8SAlfredo Cardigliano 	int err;
126127b942c8SAlfredo Cardigliano 
126227b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
126327b942c8SAlfredo Cardigliano 		.pending_work = true,
126427b942c8SAlfredo Cardigliano 		.cmd.q_init = {
126527b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
126627b942c8SAlfredo Cardigliano 			.type = q->type,
126727b942c8SAlfredo Cardigliano 			.index = q->index,
126827b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
126927b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
127027b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
127127b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
127227b942c8SAlfredo Cardigliano 		}
127327b942c8SAlfredo Cardigliano 	};
127427b942c8SAlfredo Cardigliano 
127527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
127627b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
127727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
127827b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
127927b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
128027b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
12814ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
128227b942c8SAlfredo Cardigliano 
128327b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
128427b942c8SAlfredo Cardigliano 	if (err)
128527b942c8SAlfredo Cardigliano 		return err;
128627b942c8SAlfredo Cardigliano 
128727b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
128827b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
128927b942c8SAlfredo Cardigliano 	q->db = NULL;
129027b942c8SAlfredo Cardigliano 
129127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
129227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
129327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
129427b942c8SAlfredo Cardigliano 
129527b942c8SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
129627b942c8SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
129727b942c8SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
129827b942c8SAlfredo Cardigliano 
129927b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
130027b942c8SAlfredo Cardigliano 
130127b942c8SAlfredo Cardigliano 	return 0;
130227b942c8SAlfredo Cardigliano }
130327b942c8SAlfredo Cardigliano 
1304669c8de6SAlfredo Cardigliano int
1305598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1306598f6726SAlfredo Cardigliano {
1307598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1308598f6726SAlfredo Cardigliano 		.pending_work = true,
1309598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1310598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1311598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1312598f6726SAlfredo Cardigliano 			.features = lif->features,
1313598f6726SAlfredo Cardigliano 		},
1314598f6726SAlfredo Cardigliano 	};
1315598f6726SAlfredo Cardigliano 	int err;
1316598f6726SAlfredo Cardigliano 
1317598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1318598f6726SAlfredo Cardigliano 	if (err)
1319598f6726SAlfredo Cardigliano 		return err;
1320598f6726SAlfredo Cardigliano 
1321598f6726SAlfredo Cardigliano 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1322598f6726SAlfredo Cardigliano 		ctx.comp.lif_setattr.features);
1323598f6726SAlfredo Cardigliano 
1324598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1325598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1326598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1327598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1328598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1329598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1330598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1331598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1332598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1333598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1334598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1335598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1336598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1337598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1338598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1339598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1340598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1341598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1342598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1343598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1344598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1345598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1346598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1347598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1348598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1349598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1350598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1351598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1352598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1353598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1354598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1355598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1356598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1357598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1358598f6726SAlfredo Cardigliano 
1359598f6726SAlfredo Cardigliano 	return 0;
1360598f6726SAlfredo Cardigliano }
1361598f6726SAlfredo Cardigliano 
1362a27d9013SAlfredo Cardigliano int
1363a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1364a27d9013SAlfredo Cardigliano {
1365a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1366a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1367a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1368a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1369a27d9013SAlfredo Cardigliano 		.pending_work = true,
1370a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1371a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1372a27d9013SAlfredo Cardigliano 			.type = q->type,
1373a27d9013SAlfredo Cardigliano 			.index = q->index,
1374a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1375a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1376a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1377a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1378a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1379a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1380a27d9013SAlfredo Cardigliano 		},
1381a27d9013SAlfredo Cardigliano 	};
1382a27d9013SAlfredo Cardigliano 	int err;
1383a27d9013SAlfredo Cardigliano 
1384a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1385a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1386a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1387a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1388a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13894ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1390a27d9013SAlfredo Cardigliano 
1391a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1392a27d9013SAlfredo Cardigliano 	if (err)
1393a27d9013SAlfredo Cardigliano 		return err;
1394a27d9013SAlfredo Cardigliano 
1395a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1396a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1397a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1398a27d9013SAlfredo Cardigliano 
1399a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1400a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1401a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1402a27d9013SAlfredo Cardigliano 
1403a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1404a27d9013SAlfredo Cardigliano 
1405a27d9013SAlfredo Cardigliano 	return 0;
1406a27d9013SAlfredo Cardigliano }
1407a27d9013SAlfredo Cardigliano 
1408a27d9013SAlfredo Cardigliano int
1409a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1410a27d9013SAlfredo Cardigliano {
1411a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1412a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1413a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1414a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1415a27d9013SAlfredo Cardigliano 		.pending_work = true,
1416a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1417a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1418a27d9013SAlfredo Cardigliano 			.type = q->type,
1419a27d9013SAlfredo Cardigliano 			.index = q->index,
1420a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1421a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1422a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1423a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1424a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1425a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1426a27d9013SAlfredo Cardigliano 		},
1427a27d9013SAlfredo Cardigliano 	};
1428a27d9013SAlfredo Cardigliano 	int err;
1429a27d9013SAlfredo Cardigliano 
1430a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1431a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1432a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1433a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1434a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
14354ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1436a27d9013SAlfredo Cardigliano 
1437a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1438a27d9013SAlfredo Cardigliano 	if (err)
1439a27d9013SAlfredo Cardigliano 		return err;
1440a27d9013SAlfredo Cardigliano 
1441a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1442a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1443a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1444a27d9013SAlfredo Cardigliano 
1445a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1446a27d9013SAlfredo Cardigliano 
1447a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1448a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1449a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1450a27d9013SAlfredo Cardigliano 
1451a27d9013SAlfredo Cardigliano 	return 0;
1452a27d9013SAlfredo Cardigliano }
1453a27d9013SAlfredo Cardigliano 
1454598f6726SAlfredo Cardigliano static int
1455598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1456598f6726SAlfredo Cardigliano {
1457598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1458598f6726SAlfredo Cardigliano 		.pending_work = true,
1459598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1460598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1461598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1462598f6726SAlfredo Cardigliano 		},
1463598f6726SAlfredo Cardigliano 	};
1464598f6726SAlfredo Cardigliano 	int err;
1465598f6726SAlfredo Cardigliano 
1466598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1467598f6726SAlfredo Cardigliano 
1468598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1469598f6726SAlfredo Cardigliano 	if (err)
1470598f6726SAlfredo Cardigliano 		return err;
1471598f6726SAlfredo Cardigliano 
1472598f6726SAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
1473598f6726SAlfredo Cardigliano 			lif->mac_addr)) {
1474598f6726SAlfredo Cardigliano 		IONIC_PRINT(INFO, "deleting station MAC addr");
1475598f6726SAlfredo Cardigliano 
1476598f6726SAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
1477598f6726SAlfredo Cardigliano 	}
1478598f6726SAlfredo Cardigliano 
1479598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1480598f6726SAlfredo Cardigliano 
1481598f6726SAlfredo Cardigliano 	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
1482598f6726SAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
1483598f6726SAlfredo Cardigliano 		return 0;
1484598f6726SAlfredo Cardigliano 	}
1485598f6726SAlfredo Cardigliano 
1486598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adding station MAC addr");
1487598f6726SAlfredo Cardigliano 
1488598f6726SAlfredo Cardigliano 	ionic_lif_addr_add(lif, lif->mac_addr);
1489598f6726SAlfredo Cardigliano 
1490598f6726SAlfredo Cardigliano 	return 0;
1491598f6726SAlfredo Cardigliano }
1492598f6726SAlfredo Cardigliano 
1493598f6726SAlfredo Cardigliano static void
1494598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1495598f6726SAlfredo Cardigliano {
1496598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1497598f6726SAlfredo Cardigliano 		.pending_work = true,
1498598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1499598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1500598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1501598f6726SAlfredo Cardigliano 		},
1502598f6726SAlfredo Cardigliano 	};
1503598f6726SAlfredo Cardigliano 
15044ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
15054ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1506598f6726SAlfredo Cardigliano 
1507598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1508598f6726SAlfredo Cardigliano }
1509598f6726SAlfredo Cardigliano 
1510598f6726SAlfredo Cardigliano int
1511669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1512669c8de6SAlfredo Cardigliano {
1513669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1514669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1515669c8de6SAlfredo Cardigliano 	int err;
1516669c8de6SAlfredo Cardigliano 
15173cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
15183cdfd905SAlfredo Cardigliano 
151900b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1520669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1521669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1522669c8de6SAlfredo Cardigliano 	if (err)
1523669c8de6SAlfredo Cardigliano 		return err;
1524669c8de6SAlfredo Cardigliano 
1525669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
1526669c8de6SAlfredo Cardigliano 
152701a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
152801a6c311SAlfredo Cardigliano 	if (err)
152901a6c311SAlfredo Cardigliano 		return err;
153001a6c311SAlfredo Cardigliano 
153127b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
153227b942c8SAlfredo Cardigliano 	if (err)
153327b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
153427b942c8SAlfredo Cardigliano 
1535a27d9013SAlfredo Cardigliano 	lif->features =
1536a27d9013SAlfredo Cardigliano 		  IONIC_ETH_HW_VLAN_TX_TAG
1537a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_STRIP
1538a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_FILTER
1539a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_HASH
1540a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_SG
1541a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_SG
154264b08152SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_CSUM
1543a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_CSUM
1544a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO
1545a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_IPV6
1546a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_ECN;
1547598f6726SAlfredo Cardigliano 
1548598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1549598f6726SAlfredo Cardigliano 	if (err)
1550598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1551598f6726SAlfredo Cardigliano 
155254fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1553598f6726SAlfredo Cardigliano 	if (err)
1554598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1555598f6726SAlfredo Cardigliano 
155654fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
155754fe083fSAlfredo Cardigliano 	if (err)
155854fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
155954fe083fSAlfredo Cardigliano 
1560598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1561598f6726SAlfredo Cardigliano 
1562669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1563669c8de6SAlfredo Cardigliano 
1564669c8de6SAlfredo Cardigliano 	return 0;
156527b942c8SAlfredo Cardigliano 
156654fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
156754fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
156854fe083fSAlfredo Cardigliano 
1569598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
1570598f6726SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1571598f6726SAlfredo Cardigliano 
157227b942c8SAlfredo Cardigliano err_out_adminq_deinit:
157327b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
157427b942c8SAlfredo Cardigliano 
157527b942c8SAlfredo Cardigliano 	return err;
1576669c8de6SAlfredo Cardigliano }
1577669c8de6SAlfredo Cardigliano 
1578669c8de6SAlfredo Cardigliano void
1579669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1580669c8de6SAlfredo Cardigliano {
1581669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1582669c8de6SAlfredo Cardigliano 		return;
1583669c8de6SAlfredo Cardigliano 
158454fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
158522e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
158627b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
158701a6c311SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
158801a6c311SAlfredo Cardigliano 
1589669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1590669c8de6SAlfredo Cardigliano }
1591669c8de6SAlfredo Cardigliano 
1592669c8de6SAlfredo Cardigliano int
1593598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1594598f6726SAlfredo Cardigliano {
159522e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
159622e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
159722e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
159822e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
159922e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
160022e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
160122e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
160222e7171bSAlfredo Cardigliano 
1603598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1604598f6726SAlfredo Cardigliano 
160522e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
160622e7171bSAlfredo Cardigliano 		lif->port_id);
160722e7171bSAlfredo Cardigliano 
160822e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
160922e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
161022e7171bSAlfredo Cardigliano 
161122e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
161222e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
161322e7171bSAlfredo Cardigliano 
161422e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
161522e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1616a27d9013SAlfredo Cardigliano 
1617598f6726SAlfredo Cardigliano 	return 0;
1618598f6726SAlfredo Cardigliano }
1619598f6726SAlfredo Cardigliano 
1620598f6726SAlfredo Cardigliano int
1621598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1622598f6726SAlfredo Cardigliano {
16230578335aSAndrew Boyer 	uint32_t rx_mode;
1624a27d9013SAlfredo Cardigliano 	uint32_t i;
1625a27d9013SAlfredo Cardigliano 	int err;
1626598f6726SAlfredo Cardigliano 
162722e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
162822e7171bSAlfredo Cardigliano 	if (err)
162922e7171bSAlfredo Cardigliano 		return err;
163022e7171bSAlfredo Cardigliano 
16310578335aSAndrew Boyer 	if (!lif->rx_mode) {
16320578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
16330578335aSAndrew Boyer 			lif->name);
1634598f6726SAlfredo Cardigliano 
16350578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1636598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1637598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1638598f6726SAlfredo Cardigliano 
1639598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
16400578335aSAndrew Boyer 	}
1641598f6726SAlfredo Cardigliano 
1642a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1643a27d9013SAlfredo Cardigliano 		"on port %u",
1644a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1645a27d9013SAlfredo Cardigliano 
1646a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1647a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
164802eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1649a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1650a27d9013SAlfredo Cardigliano 
1651a27d9013SAlfredo Cardigliano 			if (err)
1652a27d9013SAlfredo Cardigliano 				return err;
1653a27d9013SAlfredo Cardigliano 		}
1654a27d9013SAlfredo Cardigliano 	}
1655a27d9013SAlfredo Cardigliano 
1656a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1657a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
165802eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1659a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1660a27d9013SAlfredo Cardigliano 
1661a27d9013SAlfredo Cardigliano 			if (err)
1662a27d9013SAlfredo Cardigliano 				return err;
1663a27d9013SAlfredo Cardigliano 		}
1664a27d9013SAlfredo Cardigliano 	}
1665a27d9013SAlfredo Cardigliano 
1666598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1667be63459eSAndrew Boyer 	lif->state |= IONIC_LIF_F_UP;
1668be63459eSAndrew Boyer 
1669be63459eSAndrew Boyer 	ionic_link_status_check(lif);
1670598f6726SAlfredo Cardigliano 
1671598f6726SAlfredo Cardigliano 	return 0;
1672598f6726SAlfredo Cardigliano }
1673598f6726SAlfredo Cardigliano 
1674598f6726SAlfredo Cardigliano int
1675669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1676669c8de6SAlfredo Cardigliano {
1677669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1678669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1679669c8de6SAlfredo Cardigliano 	int err;
1680669c8de6SAlfredo Cardigliano 	unsigned int i;
1681669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1682669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1683669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1684669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1685669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1686669c8de6SAlfredo Cardigliano 
1687669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1688669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1689669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1690669c8de6SAlfredo Cardigliano 	if (err)
1691669c8de6SAlfredo Cardigliano 		return (err);
1692669c8de6SAlfredo Cardigliano 
1693669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1694669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1695669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1696669c8de6SAlfredo Cardigliano 
1697669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1698669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
1699669c8de6SAlfredo Cardigliano 
1700669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1701669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
1702669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1703669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
1704669c8de6SAlfredo Cardigliano 
1705669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1706669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
1707669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1708669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1709669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1710669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1711669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1712669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1713669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1714669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1715669c8de6SAlfredo Cardigliano 
1716669c8de6SAlfredo Cardigliano 	return 0;
1717669c8de6SAlfredo Cardigliano }
1718669c8de6SAlfredo Cardigliano 
1719669c8de6SAlfredo Cardigliano int
1720669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1721669c8de6SAlfredo Cardigliano {
1722669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1723669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1724669c8de6SAlfredo Cardigliano 
1725669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1726669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1727669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1728669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1729669c8de6SAlfredo Cardigliano 
173000b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1731669c8de6SAlfredo Cardigliano 
1732669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
17334ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
17344ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1735669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1736669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1737669c8de6SAlfredo Cardigliano 	}
1738669c8de6SAlfredo Cardigliano 
1739669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1740669c8de6SAlfredo Cardigliano 
1741669c8de6SAlfredo Cardigliano 	return 0;
1742669c8de6SAlfredo Cardigliano }
1743