xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 175e4e7ed760459d86fc928f1d9000a631e30b18)
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 
6601a6c311SAlfredo Cardigliano int
67598f6726SAlfredo Cardigliano ionic_lif_stop(struct ionic_lif *lif __rte_unused)
68598f6726SAlfredo Cardigliano {
69598f6726SAlfredo Cardigliano 	/* Carrier OFF here */
70598f6726SAlfredo Cardigliano 
71598f6726SAlfredo Cardigliano 	return 0;
72598f6726SAlfredo Cardigliano }
73598f6726SAlfredo Cardigliano 
74598f6726SAlfredo Cardigliano void
75598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
76598f6726SAlfredo Cardigliano {
77598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
7875f96902SAndrew Boyer 	int err;
79598f6726SAlfredo Cardigliano 
80598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
81598f6726SAlfredo Cardigliano 
8200b65da5SAndrew Boyer 	ionic_dev_cmd_lif_reset(idev);
8375f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
8475f96902SAndrew Boyer 	if (err)
854ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
86598f6726SAlfredo Cardigliano }
87598f6726SAlfredo Cardigliano 
883cdfd905SAlfredo Cardigliano static void
893cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
903cdfd905SAlfredo Cardigliano {
913cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
923cdfd905SAlfredo Cardigliano 	uint32_t i;
933cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
943cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
953cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
963cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
973cdfd905SAlfredo Cardigliano 
983cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
993cdfd905SAlfredo Cardigliano 
1003cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1013cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1023cdfd905SAlfredo Cardigliano 			lif->port_id);
1033cdfd905SAlfredo Cardigliano 		return;
1043cdfd905SAlfredo Cardigliano 	}
1053cdfd905SAlfredo Cardigliano 
1063cdfd905SAlfredo Cardigliano 	/* RX */
1073cdfd905SAlfredo Cardigliano 
1083cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1093cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1103cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1113cdfd905SAlfredo Cardigliano 
1123cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1133cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1143cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1153cdfd905SAlfredo Cardigliano 
1163cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1173cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1183cdfd905SAlfredo Cardigliano 		stats->imissed +=
1193cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1203cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1213cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1223cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1233cdfd905SAlfredo Cardigliano 	}
1243cdfd905SAlfredo Cardigliano 
1253cdfd905SAlfredo Cardigliano 	stats->imissed +=
1263cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1273cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1283cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1293cdfd905SAlfredo Cardigliano 
1303cdfd905SAlfredo Cardigliano 	stats->imissed +=
1313cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
1323cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1333cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
1343cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1353cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1363cdfd905SAlfredo Cardigliano 
1373cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
1383cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1393cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1403cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1413cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1423cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1433cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1443cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1453cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1463cdfd905SAlfredo Cardigliano 	}
1473cdfd905SAlfredo Cardigliano 
1483cdfd905SAlfredo Cardigliano 	/* TX */
1493cdfd905SAlfredo Cardigliano 
1503cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1513cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1523cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1533cdfd905SAlfredo Cardigliano 
1543cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1553cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1563cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1573cdfd905SAlfredo Cardigliano 
1583cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1593cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1603cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1613cdfd905SAlfredo Cardigliano 	}
1623cdfd905SAlfredo Cardigliano 
1633cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1643cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1653cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1663cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1673cdfd905SAlfredo Cardigliano 
1683cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1693cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1703cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1713cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1723cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1733cdfd905SAlfredo Cardigliano 
1743cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
1753cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1763cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1773cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1783cdfd905SAlfredo Cardigliano 	}
1793cdfd905SAlfredo Cardigliano }
1803cdfd905SAlfredo Cardigliano 
1813cdfd905SAlfredo Cardigliano void
1823cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1833cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1843cdfd905SAlfredo Cardigliano {
1853cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1863cdfd905SAlfredo Cardigliano 
1873cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1883cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1893cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1903cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1913cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1923cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1933cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1943cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1953cdfd905SAlfredo Cardigliano }
1963cdfd905SAlfredo Cardigliano 
1973cdfd905SAlfredo Cardigliano void
1983cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
1993cdfd905SAlfredo Cardigliano {
2003cdfd905SAlfredo Cardigliano 	uint32_t i;
2013cdfd905SAlfredo Cardigliano 
2023cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
2033cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
2043cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
2053cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 0,
2063cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2073cdfd905SAlfredo Cardigliano 	}
2083cdfd905SAlfredo Cardigliano 
2093cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2103cdfd905SAlfredo Cardigliano }
2113cdfd905SAlfredo Cardigliano 
2123cdfd905SAlfredo Cardigliano void
2133cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2143cdfd905SAlfredo Cardigliano {
2153cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2163cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2173cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2183cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2193cdfd905SAlfredo Cardigliano 
2203cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2213cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2223cdfd905SAlfredo Cardigliano }
2233cdfd905SAlfredo Cardigliano 
2243cdfd905SAlfredo Cardigliano void
2253cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2263cdfd905SAlfredo Cardigliano {
2273cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2283cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2293cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2303cdfd905SAlfredo Cardigliano 
2313cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2323cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2333cdfd905SAlfredo Cardigliano }
2343cdfd905SAlfredo Cardigliano 
235598f6726SAlfredo Cardigliano static int
23654fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
237598f6726SAlfredo Cardigliano {
23854fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
23954fe083fSAlfredo Cardigliano 		.pending_work = true,
24054fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
24154fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
24254fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_MAC,
24354fe083fSAlfredo Cardigliano 		},
24454fe083fSAlfredo Cardigliano 	};
24554fe083fSAlfredo Cardigliano 	int err;
24654fe083fSAlfredo Cardigliano 
24754fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
24854fe083fSAlfredo Cardigliano 
24954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
25054fe083fSAlfredo Cardigliano 	if (err)
25154fe083fSAlfredo Cardigliano 		return err;
25254fe083fSAlfredo Cardigliano 
25354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
25454fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
25554fe083fSAlfredo Cardigliano 
25654fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25754fe083fSAlfredo Cardigliano }
25854fe083fSAlfredo Cardigliano 
25954fe083fSAlfredo Cardigliano static int
26054fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
26154fe083fSAlfredo Cardigliano {
26254fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
26354fe083fSAlfredo Cardigliano 		.pending_work = true,
26454fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
26554fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
26654fe083fSAlfredo Cardigliano 		},
26754fe083fSAlfredo Cardigliano 	};
26854fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
26954fe083fSAlfredo Cardigliano 	int err;
27054fe083fSAlfredo Cardigliano 
27154fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
27254fe083fSAlfredo Cardigliano 
27354fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
27454fe083fSAlfredo Cardigliano 
27554fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
27654fe083fSAlfredo Cardigliano 	if (!f) {
27754fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
27854fe083fSAlfredo Cardigliano 		return -ENOENT;
27954fe083fSAlfredo Cardigliano 	}
28054fe083fSAlfredo Cardigliano 
28154fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
28254fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
28354fe083fSAlfredo Cardigliano 
28454fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
28554fe083fSAlfredo Cardigliano 
28654fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28754fe083fSAlfredo Cardigliano 	if (err)
28854fe083fSAlfredo Cardigliano 		return err;
28954fe083fSAlfredo Cardigliano 
29054fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
29154fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
292598f6726SAlfredo Cardigliano 
293598f6726SAlfredo Cardigliano 	return 0;
294598f6726SAlfredo Cardigliano }
295598f6726SAlfredo Cardigliano 
29654fe083fSAlfredo Cardigliano int
29754fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
29854fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
29954fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
300598f6726SAlfredo Cardigliano {
30154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30254fe083fSAlfredo Cardigliano 
30354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30454fe083fSAlfredo Cardigliano 
30554fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
30654fe083fSAlfredo Cardigliano }
30754fe083fSAlfredo Cardigliano 
30854fe083fSAlfredo Cardigliano void
30975f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
31054fe083fSAlfredo Cardigliano {
31154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31254fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
31375f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
31454fe083fSAlfredo Cardigliano 
31554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31654fe083fSAlfredo Cardigliano 
31754fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
31854fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
31954fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
32054fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
32154fe083fSAlfredo Cardigliano 		return;
32254fe083fSAlfredo Cardigliano 	}
32354fe083fSAlfredo Cardigliano 
32475f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
32575f96902SAndrew Boyer 
32675f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32754fe083fSAlfredo Cardigliano 		return;
32854fe083fSAlfredo Cardigliano 
32975f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
33054fe083fSAlfredo Cardigliano }
33154fe083fSAlfredo Cardigliano 
33254fe083fSAlfredo Cardigliano int
33354fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
33454fe083fSAlfredo Cardigliano {
33554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
33654fe083fSAlfredo Cardigliano 
33754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33854fe083fSAlfredo Cardigliano 
33954fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
34054fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
34154fe083fSAlfredo Cardigliano 		return -1;
34254fe083fSAlfredo Cardigliano 	}
34354fe083fSAlfredo Cardigliano 
34454fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
34554fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
34654fe083fSAlfredo Cardigliano 			lif->mac_addr);
34754fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
34854fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
34954fe083fSAlfredo Cardigliano 	}
35054fe083fSAlfredo Cardigliano 
35154fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
35254fe083fSAlfredo Cardigliano 
35354fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
35454fe083fSAlfredo Cardigliano 
35554fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
35654fe083fSAlfredo Cardigliano }
35754fe083fSAlfredo Cardigliano 
35854fe083fSAlfredo Cardigliano static int
35954fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
36054fe083fSAlfredo Cardigliano {
36154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
36254fe083fSAlfredo Cardigliano 		.pending_work = true,
36354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
36454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
36554fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_VLAN,
36654fe083fSAlfredo Cardigliano 			.vlan.vlan = vid,
36754fe083fSAlfredo Cardigliano 		},
36854fe083fSAlfredo Cardigliano 	};
36954fe083fSAlfredo Cardigliano 	int err;
37054fe083fSAlfredo Cardigliano 
37154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
37254fe083fSAlfredo Cardigliano 	if (err)
37354fe083fSAlfredo Cardigliano 		return err;
37454fe083fSAlfredo Cardigliano 
37554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
37654fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
37754fe083fSAlfredo Cardigliano 
37854fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
37954fe083fSAlfredo Cardigliano }
38054fe083fSAlfredo Cardigliano 
38154fe083fSAlfredo Cardigliano static int
38254fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
38354fe083fSAlfredo Cardigliano {
38454fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
38554fe083fSAlfredo Cardigliano 		.pending_work = true,
38654fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38754fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
38854fe083fSAlfredo Cardigliano 		},
38954fe083fSAlfredo Cardigliano 	};
39054fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
39154fe083fSAlfredo Cardigliano 	int err;
39254fe083fSAlfredo Cardigliano 
39354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
39454fe083fSAlfredo Cardigliano 
39554fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
39654fe083fSAlfredo Cardigliano 
39754fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
39854fe083fSAlfredo Cardigliano 	if (!f) {
39954fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
40054fe083fSAlfredo Cardigliano 		return -ENOENT;
40154fe083fSAlfredo Cardigliano 	}
40254fe083fSAlfredo Cardigliano 
40354fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
40454fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
40554fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
40654fe083fSAlfredo Cardigliano 
40754fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
40854fe083fSAlfredo Cardigliano 	if (err)
40954fe083fSAlfredo Cardigliano 		return err;
41054fe083fSAlfredo Cardigliano 
41154fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
41254fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
413598f6726SAlfredo Cardigliano 
414598f6726SAlfredo Cardigliano 	return 0;
415598f6726SAlfredo Cardigliano }
416598f6726SAlfredo Cardigliano 
41754fe083fSAlfredo Cardigliano int
41854fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
41954fe083fSAlfredo Cardigliano 		int on)
42054fe083fSAlfredo Cardigliano {
42154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
42254fe083fSAlfredo Cardigliano 	int err;
42354fe083fSAlfredo Cardigliano 
42454fe083fSAlfredo Cardigliano 	if (on)
42554fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
42654fe083fSAlfredo Cardigliano 	else
42754fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
42854fe083fSAlfredo Cardigliano 
42954fe083fSAlfredo Cardigliano 	return err;
43054fe083fSAlfredo Cardigliano }
43154fe083fSAlfredo Cardigliano 
432598f6726SAlfredo Cardigliano static void
433598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
434598f6726SAlfredo Cardigliano {
435598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
436598f6726SAlfredo Cardigliano 		.pending_work = true,
437598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
438598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
439598f6726SAlfredo Cardigliano 			.rx_mode = rx_mode,
440598f6726SAlfredo Cardigliano 		},
441598f6726SAlfredo Cardigliano 	};
442598f6726SAlfredo Cardigliano 	int err;
443598f6726SAlfredo Cardigliano 
444598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
445598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
446598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
448598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
450598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
452598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
453598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
454598f6726SAlfredo Cardigliano 
455598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
456598f6726SAlfredo Cardigliano 	if (err)
457598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
458598f6726SAlfredo Cardigliano }
459598f6726SAlfredo Cardigliano 
460598f6726SAlfredo Cardigliano static void
461598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
462598f6726SAlfredo Cardigliano {
463598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
464598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
465598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
466598f6726SAlfredo Cardigliano 	}
467598f6726SAlfredo Cardigliano }
468598f6726SAlfredo Cardigliano 
46954fe083fSAlfredo Cardigliano int
47054fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
47154fe083fSAlfredo Cardigliano {
47254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
47354fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
47454fe083fSAlfredo Cardigliano 
47554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
47654fe083fSAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
47854fe083fSAlfredo Cardigliano 
47954fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48054fe083fSAlfredo Cardigliano 
48154fe083fSAlfredo Cardigliano 	return 0;
48254fe083fSAlfredo Cardigliano }
48354fe083fSAlfredo Cardigliano 
48454fe083fSAlfredo Cardigliano int
48554fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
48654fe083fSAlfredo Cardigliano {
48754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48854fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49354fe083fSAlfredo Cardigliano 
49454fe083fSAlfredo Cardigliano 	return 0;
49554fe083fSAlfredo Cardigliano }
49654fe083fSAlfredo Cardigliano 
49754fe083fSAlfredo Cardigliano int
49854fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
49954fe083fSAlfredo Cardigliano {
50054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50254fe083fSAlfredo Cardigliano 
50354fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50654fe083fSAlfredo Cardigliano 
50754fe083fSAlfredo Cardigliano 	return 0;
50854fe083fSAlfredo Cardigliano }
50954fe083fSAlfredo Cardigliano 
51054fe083fSAlfredo Cardigliano int
51154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
51254fe083fSAlfredo Cardigliano {
51354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51454fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51554fe083fSAlfredo Cardigliano 
51654fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51954fe083fSAlfredo Cardigliano 
52054fe083fSAlfredo Cardigliano 	return 0;
52154fe083fSAlfredo Cardigliano }
522598f6726SAlfredo Cardigliano 
523598f6726SAlfredo Cardigliano int
524598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
525598f6726SAlfredo Cardigliano {
526598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
527598f6726SAlfredo Cardigliano 		.pending_work = true,
528598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
529598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
530598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
531598f6726SAlfredo Cardigliano 			.mtu = new_mtu,
532598f6726SAlfredo Cardigliano 		},
533598f6726SAlfredo Cardigliano 	};
534598f6726SAlfredo Cardigliano 	int err;
535598f6726SAlfredo Cardigliano 
536598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
537598f6726SAlfredo Cardigliano 	if (err)
538598f6726SAlfredo Cardigliano 		return err;
539598f6726SAlfredo Cardigliano 
540598f6726SAlfredo Cardigliano 	return 0;
541598f6726SAlfredo Cardigliano }
542598f6726SAlfredo Cardigliano 
543598f6726SAlfredo Cardigliano int
54401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
54501a6c311SAlfredo Cardigliano {
54601a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
54701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
54801a6c311SAlfredo Cardigliano 	unsigned long index;
54901a6c311SAlfredo Cardigliano 
55001a6c311SAlfredo Cardigliano 	/*
55101a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55201a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
5534ae96cb8SAndrew Boyer 	 * which has index = 0)
55401a6c311SAlfredo Cardigliano 	 */
55501a6c311SAlfredo Cardigliano 
55601a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
55701a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
55801a6c311SAlfredo Cardigliano 			break;
55901a6c311SAlfredo Cardigliano 
56001a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56101a6c311SAlfredo Cardigliano 		return -ENOSPC;
56201a6c311SAlfredo Cardigliano 
56301a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
56401a6c311SAlfredo Cardigliano 
56501a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
56601a6c311SAlfredo Cardigliano 
56701a6c311SAlfredo Cardigliano 	return 0;
56801a6c311SAlfredo Cardigliano }
56901a6c311SAlfredo Cardigliano 
57001a6c311SAlfredo Cardigliano void
57101a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
57201a6c311SAlfredo Cardigliano {
57301a6c311SAlfredo Cardigliano 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
57401a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
57501a6c311SAlfredo Cardigliano }
57601a6c311SAlfredo Cardigliano 
57701a6c311SAlfredo Cardigliano static int
57801a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
57901a6c311SAlfredo Cardigliano 		uint32_t index,
58001a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
58101a6c311SAlfredo Cardigliano 		uint32_t num_descs,
58201a6c311SAlfredo Cardigliano 		uint32_t desc_size,
58301a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
58401a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
5851abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
58601a6c311SAlfredo Cardigliano {
58701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
58801a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
58901a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59001a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
59101a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59201a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59301a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59401a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
59501a6c311SAlfredo Cardigliano 	int err;
59601a6c311SAlfredo Cardigliano 
59701a6c311SAlfredo Cardigliano 	*qcq = NULL;
59801a6c311SAlfredo Cardigliano 
59901a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60001a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60101a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60201a6c311SAlfredo Cardigliano 
60301a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
60401a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
60501a6c311SAlfredo Cardigliano 	/*
60601a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
60701a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
60801a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
60901a6c311SAlfredo Cardigliano 	 */
61001a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
61101a6c311SAlfredo Cardigliano 
61201a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61301a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
61401a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
61501a6c311SAlfredo Cardigliano 	}
61601a6c311SAlfredo Cardigliano 
61701a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
61801a6c311SAlfredo Cardigliano 	if (!new) {
61901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62001a6c311SAlfredo Cardigliano 		return -ENOMEM;
62101a6c311SAlfredo Cardigliano 	}
62201a6c311SAlfredo Cardigliano 
62301a6c311SAlfredo Cardigliano 	new->lif = lif;
62401a6c311SAlfredo Cardigliano 	new->flags = flags;
62501a6c311SAlfredo Cardigliano 
62601a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
62701a6c311SAlfredo Cardigliano 	if (!new->q.info) {
62801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
62901a6c311SAlfredo Cardigliano 		return -ENOMEM;
63001a6c311SAlfredo Cardigliano 	}
63101a6c311SAlfredo Cardigliano 
63201a6c311SAlfredo Cardigliano 	new->q.type = type;
63301a6c311SAlfredo Cardigliano 
63401a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
6351abf69fcSAndrew Boyer 		desc_size, sg_desc_size);
63601a6c311SAlfredo Cardigliano 	if (err) {
63701a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
63801a6c311SAlfredo Cardigliano 		return err;
63901a6c311SAlfredo Cardigliano 	}
64001a6c311SAlfredo Cardigliano 
64101a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR) {
64201a6c311SAlfredo Cardigliano 		err = ionic_intr_alloc(lif, &new->intr);
64301a6c311SAlfredo Cardigliano 		if (err)
64401a6c311SAlfredo Cardigliano 			return err;
64501a6c311SAlfredo Cardigliano 
64601a6c311SAlfredo Cardigliano 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
64701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
64801a6c311SAlfredo Cardigliano 	} else {
64901a6c311SAlfredo Cardigliano 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
65001a6c311SAlfredo Cardigliano 	}
65101a6c311SAlfredo Cardigliano 
65201a6c311SAlfredo Cardigliano 	err = ionic_cq_init(lif, &new->cq, &new->intr,
65301a6c311SAlfredo Cardigliano 		num_descs, cq_desc_size);
65401a6c311SAlfredo Cardigliano 	if (err) {
65501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
65601a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
65701a6c311SAlfredo Cardigliano 	}
65801a6c311SAlfredo Cardigliano 
65901a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
66001a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
66101a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66201a6c311SAlfredo Cardigliano 
66301a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66501a6c311SAlfredo Cardigliano 		err = -ENOMEM;
66601a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
66701a6c311SAlfredo Cardigliano 	}
66801a6c311SAlfredo Cardigliano 
66901a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
67001a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67101a6c311SAlfredo Cardigliano 	new->total_size = total_size;
67201a6c311SAlfredo Cardigliano 
67301a6c311SAlfredo Cardigliano 	q_base = new->base;
67401a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67501a6c311SAlfredo Cardigliano 
67601a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
67701a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
67801a6c311SAlfredo Cardigliano 
67901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
68001a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
68101a6c311SAlfredo Cardigliano 			PAGE_SIZE);
68201a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
68301a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68401a6c311SAlfredo Cardigliano 	}
68501a6c311SAlfredo Cardigliano 
6864ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
6874ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
68801a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
68901a6c311SAlfredo Cardigliano 
69001a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69101a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69201a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	*qcq = new;
69501a6c311SAlfredo Cardigliano 
69601a6c311SAlfredo Cardigliano 	return 0;
69701a6c311SAlfredo Cardigliano 
69801a6c311SAlfredo Cardigliano err_out_free_intr:
69901a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR)
70001a6c311SAlfredo Cardigliano 		ionic_intr_free(lif, &new->intr);
70101a6c311SAlfredo Cardigliano 
70201a6c311SAlfredo Cardigliano 	return err;
70301a6c311SAlfredo Cardigliano }
70401a6c311SAlfredo Cardigliano 
70501a6c311SAlfredo Cardigliano void
70601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70701a6c311SAlfredo Cardigliano {
70801a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
70901a6c311SAlfredo Cardigliano 		qcq->base = NULL;
71001a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71101a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71201a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71301a6c311SAlfredo Cardigliano 	}
71401a6c311SAlfredo Cardigliano 
71501a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71601a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71701a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71801a6c311SAlfredo Cardigliano 	}
71901a6c311SAlfredo Cardigliano 
72001a6c311SAlfredo Cardigliano 	rte_free(qcq);
72101a6c311SAlfredo Cardigliano }
72201a6c311SAlfredo Cardigliano 
723a27d9013SAlfredo Cardigliano int
724a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
725a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
726a27d9013SAlfredo Cardigliano {
727a27d9013SAlfredo Cardigliano 	uint32_t flags;
728a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
729a27d9013SAlfredo Cardigliano 
730a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
731a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags,
732a27d9013SAlfredo Cardigliano 		nrxq_descs,
733a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
734a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
735a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
7361abf69fcSAndrew Boyer 		&lif->rxqcqs[index]);
737a27d9013SAlfredo Cardigliano 	if (err)
738a27d9013SAlfredo Cardigliano 		return err;
739a27d9013SAlfredo Cardigliano 
740a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
741a27d9013SAlfredo Cardigliano 
742a27d9013SAlfredo Cardigliano 	return 0;
743a27d9013SAlfredo Cardigliano }
744a27d9013SAlfredo Cardigliano 
745a27d9013SAlfredo Cardigliano int
746a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
747a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
748a27d9013SAlfredo Cardigliano {
749a27d9013SAlfredo Cardigliano 	uint32_t flags;
750a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
751a27d9013SAlfredo Cardigliano 
752a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
753a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
754a27d9013SAlfredo Cardigliano 		ntxq_descs,
755a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
756a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
757a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_sg_desc),
7581abf69fcSAndrew Boyer 		&lif->txqcqs[index]);
759a27d9013SAlfredo Cardigliano 	if (err)
760a27d9013SAlfredo Cardigliano 		return err;
761a27d9013SAlfredo Cardigliano 
762a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
763a27d9013SAlfredo Cardigliano 
764a27d9013SAlfredo Cardigliano 	return 0;
765a27d9013SAlfredo Cardigliano }
766a27d9013SAlfredo Cardigliano 
76701a6c311SAlfredo Cardigliano static int
76801a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
76901a6c311SAlfredo Cardigliano {
77001a6c311SAlfredo Cardigliano 	uint32_t flags;
77101a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
77201a6c311SAlfredo Cardigliano 
77301a6c311SAlfredo Cardigliano 	flags = 0;
77401a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
77501a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
77601a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
77701a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
77801a6c311SAlfredo Cardigliano 		0,
7791abf69fcSAndrew Boyer 		&lif->adminqcq);
78027b942c8SAlfredo Cardigliano 	if (err)
78127b942c8SAlfredo Cardigliano 		return err;
78201a6c311SAlfredo Cardigliano 
78327b942c8SAlfredo Cardigliano 	return 0;
78427b942c8SAlfredo Cardigliano }
78527b942c8SAlfredo Cardigliano 
78627b942c8SAlfredo Cardigliano static int
78727b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
78827b942c8SAlfredo Cardigliano {
78927b942c8SAlfredo Cardigliano 	uint32_t flags;
79027b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
79127b942c8SAlfredo Cardigliano 
79227b942c8SAlfredo Cardigliano 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
79327b942c8SAlfredo Cardigliano 
79427b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
79527b942c8SAlfredo Cardigliano 		flags,
79627b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
79727b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
79827b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
79927b942c8SAlfredo Cardigliano 		0,
8001abf69fcSAndrew Boyer 		&lif->notifyqcq);
80101a6c311SAlfredo Cardigliano 	if (err)
80201a6c311SAlfredo Cardigliano 		return err;
80301a6c311SAlfredo Cardigliano 
80401a6c311SAlfredo Cardigliano 	return 0;
80501a6c311SAlfredo Cardigliano }
80601a6c311SAlfredo Cardigliano 
807c67719e1SAlfredo Cardigliano static void *
808c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
809c67719e1SAlfredo Cardigliano {
810c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
811c67719e1SAlfredo Cardigliano 
812c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
813c67719e1SAlfredo Cardigliano 		return NULL;
814c67719e1SAlfredo Cardigliano 
815c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
816c67719e1SAlfredo Cardigliano }
817c67719e1SAlfredo Cardigliano 
818669c8de6SAlfredo Cardigliano int
819669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
820669c8de6SAlfredo Cardigliano {
821c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
822669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
82301a6c311SAlfredo Cardigliano 	int err;
824669c8de6SAlfredo Cardigliano 
8254ae96cb8SAndrew Boyer 	/*
8264ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
8274ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
8284ae96cb8SAndrew Boyer 	 */
8294ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
8304ae96cb8SAndrew Boyer 
8314ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
832669c8de6SAlfredo Cardigliano 
833669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
834669c8de6SAlfredo Cardigliano 
83501a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
83601a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
83701a6c311SAlfredo Cardigliano 
83800b65da5SAndrew Boyer 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, 0);
839c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
840c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
841c67719e1SAlfredo Cardigliano 		return -ENOMEM;
842c67719e1SAlfredo Cardigliano 	}
843c67719e1SAlfredo Cardigliano 
844a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
845a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
846a27d9013SAlfredo Cardigliano 
847a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
848a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
849a27d9013SAlfredo Cardigliano 		return -ENOMEM;
850a27d9013SAlfredo Cardigliano 	}
851a27d9013SAlfredo Cardigliano 
852a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
853a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
854a27d9013SAlfredo Cardigliano 
855a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
856a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
857a27d9013SAlfredo Cardigliano 		return -ENOMEM;
858a27d9013SAlfredo Cardigliano 	}
859a27d9013SAlfredo Cardigliano 
86027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
86127b942c8SAlfredo Cardigliano 
86227b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
86327b942c8SAlfredo Cardigliano 	if (err) {
86427b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
86527b942c8SAlfredo Cardigliano 		return err;
86627b942c8SAlfredo Cardigliano 	}
86727b942c8SAlfredo Cardigliano 
86827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
86927b942c8SAlfredo Cardigliano 
87001a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
87101a6c311SAlfredo Cardigliano 	if (err) {
87201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
87301a6c311SAlfredo Cardigliano 		return err;
87401a6c311SAlfredo Cardigliano 	}
87501a6c311SAlfredo Cardigliano 
87601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
87701a6c311SAlfredo Cardigliano 
878669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
879669c8de6SAlfredo Cardigliano 
880669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
881669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
882669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
883669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
884669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
885669c8de6SAlfredo Cardigliano 		return -ENOMEM;
886669c8de6SAlfredo Cardigliano 	}
887669c8de6SAlfredo Cardigliano 
888669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
889669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
890669c8de6SAlfredo Cardigliano 
891669c8de6SAlfredo Cardigliano 	return 0;
892669c8de6SAlfredo Cardigliano }
893669c8de6SAlfredo Cardigliano 
894669c8de6SAlfredo Cardigliano void
895669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
896669c8de6SAlfredo Cardigliano {
89727b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
89827b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
89927b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
90027b942c8SAlfredo Cardigliano 	}
90127b942c8SAlfredo Cardigliano 
90201a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
90301a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
90401a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
90501a6c311SAlfredo Cardigliano 	}
90601a6c311SAlfredo Cardigliano 
907a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
908a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
909a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
910a27d9013SAlfredo Cardigliano 	}
911a27d9013SAlfredo Cardigliano 
912a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
913a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
914a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
915a27d9013SAlfredo Cardigliano 	}
916a27d9013SAlfredo Cardigliano 
917669c8de6SAlfredo Cardigliano 	if (lif->info) {
918669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
919669c8de6SAlfredo Cardigliano 		lif->info = NULL;
920669c8de6SAlfredo Cardigliano 	}
921669c8de6SAlfredo Cardigliano }
922669c8de6SAlfredo Cardigliano 
923*175e4e7eSAndrew Boyer void
924*175e4e7eSAndrew Boyer ionic_lif_free_queues(struct ionic_lif *lif)
925*175e4e7eSAndrew Boyer {
926*175e4e7eSAndrew Boyer 	uint32_t i;
927*175e4e7eSAndrew Boyer 
928*175e4e7eSAndrew Boyer 	for (i = 0; i < lif->ntxqcqs; i++) {
929*175e4e7eSAndrew Boyer 		ionic_dev_tx_queue_release(lif->eth_dev->data->tx_queues[i]);
930*175e4e7eSAndrew Boyer 		lif->eth_dev->data->tx_queues[i] = NULL;
931*175e4e7eSAndrew Boyer 	}
932*175e4e7eSAndrew Boyer 	for (i = 0; i < lif->nrxqcqs; i++) {
933*175e4e7eSAndrew Boyer 		ionic_dev_rx_queue_release(lif->eth_dev->data->rx_queues[i]);
934*175e4e7eSAndrew Boyer 		lif->eth_dev->data->rx_queues[i] = NULL;
935*175e4e7eSAndrew Boyer 	}
936*175e4e7eSAndrew Boyer }
937*175e4e7eSAndrew Boyer 
93822e7171bSAlfredo Cardigliano int
93922e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
94022e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
94122e7171bSAlfredo Cardigliano {
94222e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
94322e7171bSAlfredo Cardigliano 		.pending_work = true,
94422e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
94522e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
94622e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
94722e7171bSAlfredo Cardigliano 			.rss.types = types,
94822e7171bSAlfredo Cardigliano 			.rss.addr = lif->rss_ind_tbl_pa,
94922e7171bSAlfredo Cardigliano 		},
95022e7171bSAlfredo Cardigliano 	};
95122e7171bSAlfredo Cardigliano 	unsigned int i;
95222e7171bSAlfredo Cardigliano 
95322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
95422e7171bSAlfredo Cardigliano 
95522e7171bSAlfredo Cardigliano 	lif->rss_types = types;
95622e7171bSAlfredo Cardigliano 
95722e7171bSAlfredo Cardigliano 	if (key)
95822e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
95922e7171bSAlfredo Cardigliano 
96022e7171bSAlfredo Cardigliano 	if (indir)
96122e7171bSAlfredo Cardigliano 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
96222e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
96322e7171bSAlfredo Cardigliano 
96422e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
96522e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
96622e7171bSAlfredo Cardigliano 
96722e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
96822e7171bSAlfredo Cardigliano }
96922e7171bSAlfredo Cardigliano 
97022e7171bSAlfredo Cardigliano static int
97122e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
97222e7171bSAlfredo Cardigliano {
97322e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
97422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97922e7171bSAlfredo Cardigliano 	};
98022e7171bSAlfredo Cardigliano 	uint32_t i;
9813d845eddSAndrew Boyer 	uint16_t tbl_sz = lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
98222e7171bSAlfredo Cardigliano 
98322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
98422e7171bSAlfredo Cardigliano 
9853d845eddSAndrew Boyer 	if (!lif->rss_ind_tbl_z) {
98622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
9873d845eddSAndrew Boyer 					"rss_ind_tbl", 0 /* queue_idx */,
9883d845eddSAndrew Boyer 					sizeof(*lif->rss_ind_tbl) * tbl_sz,
9893d845eddSAndrew Boyer 					IONIC_ALIGN, rte_socket_id());
99022e7171bSAlfredo Cardigliano 		if (!lif->rss_ind_tbl_z) {
99122e7171bSAlfredo Cardigliano 			IONIC_PRINT(ERR, "OOM");
99222e7171bSAlfredo Cardigliano 			return -ENOMEM;
99322e7171bSAlfredo Cardigliano 		}
99422e7171bSAlfredo Cardigliano 
99522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
99622e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
9973d845eddSAndrew Boyer 	}
9983d845eddSAndrew Boyer 
9993d845eddSAndrew Boyer 	if (lif->rss_ind_tbl_nrxqcqs != lif->nrxqcqs) {
10003d845eddSAndrew Boyer 		lif->rss_ind_tbl_nrxqcqs = lif->nrxqcqs;
100122e7171bSAlfredo Cardigliano 
100222e7171bSAlfredo Cardigliano 		/* Fill indirection table with 'default' values */
10033d845eddSAndrew Boyer 		for (i = 0; i < tbl_sz; i++)
100422e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
10053d845eddSAndrew Boyer 	}
100622e7171bSAlfredo Cardigliano 
10073d845eddSAndrew Boyer 	return ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
100822e7171bSAlfredo Cardigliano 			toeplitz_symmetric_key, NULL);
100922e7171bSAlfredo Cardigliano }
101022e7171bSAlfredo Cardigliano 
101122e7171bSAlfredo Cardigliano static void
101222e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
101322e7171bSAlfredo Cardigliano {
101422e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
101522e7171bSAlfredo Cardigliano 		return;
101622e7171bSAlfredo Cardigliano 
101722e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
101822e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
101922e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
102022e7171bSAlfredo Cardigliano 
102122e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
102222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
102322e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
102422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
102522e7171bSAlfredo Cardigliano 	}
102622e7171bSAlfredo Cardigliano }
102722e7171bSAlfredo Cardigliano 
102801a6c311SAlfredo Cardigliano static void
102901a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
103001a6c311SAlfredo Cardigliano {
103101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
103201a6c311SAlfredo Cardigliano 
103301a6c311SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
103401a6c311SAlfredo Cardigliano 		return;
103501a6c311SAlfredo Cardigliano 
103601a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
103701a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
103801a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
103901a6c311SAlfredo Cardigliano 
104001a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
104101a6c311SAlfredo Cardigliano }
104201a6c311SAlfredo Cardigliano 
1043a27d9013SAlfredo Cardigliano void
1044a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1045a27d9013SAlfredo Cardigliano {
1046a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1047a27d9013SAlfredo Cardigliano }
1048a27d9013SAlfredo Cardigliano 
1049a27d9013SAlfredo Cardigliano void
1050a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1051a27d9013SAlfredo Cardigliano {
1052a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1053a27d9013SAlfredo Cardigliano }
1054a27d9013SAlfredo Cardigliano 
105501a6c311SAlfredo Cardigliano bool
105601a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
105701a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
105801a6c311SAlfredo Cardigliano {
105901a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
106001a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
106101a6c311SAlfredo Cardigliano 
106201a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
106301a6c311SAlfredo Cardigliano 		return false;
106401a6c311SAlfredo Cardigliano 
106501a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
106601a6c311SAlfredo Cardigliano 
106701a6c311SAlfredo Cardigliano 	return true;
106801a6c311SAlfredo Cardigliano }
106901a6c311SAlfredo Cardigliano 
107001a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
107101a6c311SAlfredo Cardigliano int
107201a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
107301a6c311SAlfredo Cardigliano 		void *cb_arg)
107401a6c311SAlfredo Cardigliano {
107501a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
107601a6c311SAlfredo Cardigliano 	uint32_t work_done;
107701a6c311SAlfredo Cardigliano 
107801a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
107901a6c311SAlfredo Cardigliano 
108001a6c311SAlfredo Cardigliano 	return work_done;
108101a6c311SAlfredo Cardigliano }
108201a6c311SAlfredo Cardigliano 
108327b942c8SAlfredo Cardigliano static void
108427b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
108527b942c8SAlfredo Cardigliano {
108627b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
108727b942c8SAlfredo Cardigliano 	bool link_up;
108827b942c8SAlfredo Cardigliano 
108927b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
109027b942c8SAlfredo Cardigliano 
109127b942c8SAlfredo Cardigliano 	if (!lif->info)
109227b942c8SAlfredo Cardigliano 		return;
109327b942c8SAlfredo Cardigliano 
109427b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
109527b942c8SAlfredo Cardigliano 
109627b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
109727b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
109827b942c8SAlfredo Cardigliano 		return;
109927b942c8SAlfredo Cardigliano 
110027b942c8SAlfredo Cardigliano 	if (link_up) {
110127b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
110227b942c8SAlfredo Cardigliano 			lif->info->status.link_speed);
110327b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
110427b942c8SAlfredo Cardigliano 	} else {
110527b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
110627b942c8SAlfredo Cardigliano 	}
110727b942c8SAlfredo Cardigliano 
110827b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
110927b942c8SAlfredo Cardigliano }
111027b942c8SAlfredo Cardigliano 
111127b942c8SAlfredo Cardigliano static bool
111227b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
111327b942c8SAlfredo Cardigliano {
111427b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
111527b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
111627b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
111727b942c8SAlfredo Cardigliano 
111827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
111927b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
112027b942c8SAlfredo Cardigliano 
112127b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
112227b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
112327b942c8SAlfredo Cardigliano 		return false;
112427b942c8SAlfredo Cardigliano 
112527b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
112627b942c8SAlfredo Cardigliano 
112727b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
112827b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
112927b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
113027b942c8SAlfredo Cardigliano 			"Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
113127b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
113227b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
113327b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
113427b942c8SAlfredo Cardigliano 
113527b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
113627b942c8SAlfredo Cardigliano 
113727b942c8SAlfredo Cardigliano 		break;
113827b942c8SAlfredo Cardigliano 	default:
113927b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
114027b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
114127b942c8SAlfredo Cardigliano 		break;
114227b942c8SAlfredo Cardigliano 	}
114327b942c8SAlfredo Cardigliano 
114427b942c8SAlfredo Cardigliano 	return true;
114527b942c8SAlfredo Cardigliano }
114627b942c8SAlfredo Cardigliano 
114727b942c8SAlfredo Cardigliano int
114827b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
114927b942c8SAlfredo Cardigliano {
115027b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
115127b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
115227b942c8SAlfredo Cardigliano 	uint32_t work_done;
115327b942c8SAlfredo Cardigliano 
115427b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
115527b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
115627b942c8SAlfredo Cardigliano 		return -1;
115727b942c8SAlfredo Cardigliano 	}
115827b942c8SAlfredo Cardigliano 
115927b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
116027b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
116127b942c8SAlfredo Cardigliano 
116227b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
116327b942c8SAlfredo Cardigliano 
116427b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
116527b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
116627b942c8SAlfredo Cardigliano 
116727b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
116827b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
116927b942c8SAlfredo Cardigliano 
117027b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
117127b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
117227b942c8SAlfredo Cardigliano 
117327b942c8SAlfredo Cardigliano 	return 0;
117427b942c8SAlfredo Cardigliano }
117527b942c8SAlfredo Cardigliano 
117601a6c311SAlfredo Cardigliano static int
117701a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
117801a6c311SAlfredo Cardigliano {
117901a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
118001a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
118101a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
118201a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
118301a6c311SAlfredo Cardigliano 	int err;
118401a6c311SAlfredo Cardigliano 
118500b65da5SAndrew Boyer 	ionic_dev_cmd_adminq_init(idev, qcq, qcq->intr.index);
118601a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
118701a6c311SAlfredo Cardigliano 	if (err)
118801a6c311SAlfredo Cardigliano 		return err;
118901a6c311SAlfredo Cardigliano 
119001a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
119101a6c311SAlfredo Cardigliano 
119201a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
119301a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
119401a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
119501a6c311SAlfredo Cardigliano 
119601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
119701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
119801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
119901a6c311SAlfredo Cardigliano 
120001a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
120101a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
120201a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
120301a6c311SAlfredo Cardigliano 
120401a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
120501a6c311SAlfredo Cardigliano 
120601a6c311SAlfredo Cardigliano 	return 0;
120701a6c311SAlfredo Cardigliano }
120801a6c311SAlfredo Cardigliano 
120927b942c8SAlfredo Cardigliano static int
121027b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
121127b942c8SAlfredo Cardigliano {
121227b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
121327b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
121427b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
121527b942c8SAlfredo Cardigliano 	int err;
121627b942c8SAlfredo Cardigliano 
121727b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
121827b942c8SAlfredo Cardigliano 		.pending_work = true,
121927b942c8SAlfredo Cardigliano 		.cmd.q_init = {
122027b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
122127b942c8SAlfredo Cardigliano 			.type = q->type,
122227b942c8SAlfredo Cardigliano 			.index = q->index,
122327b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
122427b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
122527b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
122627b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
122727b942c8SAlfredo Cardigliano 		}
122827b942c8SAlfredo Cardigliano 	};
122927b942c8SAlfredo Cardigliano 
123027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
123127b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
123227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
123327b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
123427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
123527b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
12364ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
123727b942c8SAlfredo Cardigliano 
123827b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
123927b942c8SAlfredo Cardigliano 	if (err)
124027b942c8SAlfredo Cardigliano 		return err;
124127b942c8SAlfredo Cardigliano 
124227b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
124327b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
124427b942c8SAlfredo Cardigliano 	q->db = NULL;
124527b942c8SAlfredo Cardigliano 
124627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
124727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
124827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
124927b942c8SAlfredo Cardigliano 
125027b942c8SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
125127b942c8SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
125227b942c8SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
125327b942c8SAlfredo Cardigliano 
125427b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
125527b942c8SAlfredo Cardigliano 
125627b942c8SAlfredo Cardigliano 	return 0;
125727b942c8SAlfredo Cardigliano }
125827b942c8SAlfredo Cardigliano 
1259669c8de6SAlfredo Cardigliano int
1260598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1261598f6726SAlfredo Cardigliano {
1262598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1263598f6726SAlfredo Cardigliano 		.pending_work = true,
1264598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1265598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1266598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1267598f6726SAlfredo Cardigliano 			.features = lif->features,
1268598f6726SAlfredo Cardigliano 		},
1269598f6726SAlfredo Cardigliano 	};
1270598f6726SAlfredo Cardigliano 	int err;
1271598f6726SAlfredo Cardigliano 
1272598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1273598f6726SAlfredo Cardigliano 	if (err)
1274598f6726SAlfredo Cardigliano 		return err;
1275598f6726SAlfredo Cardigliano 
1276598f6726SAlfredo Cardigliano 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1277598f6726SAlfredo Cardigliano 		ctx.comp.lif_setattr.features);
1278598f6726SAlfredo Cardigliano 
1279598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1280598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1281598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1282598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1283598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1284598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1285598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1286598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1287598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1288598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1289598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1290598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1291598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1292598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1293598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1294598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1295598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1296598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1297598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1298598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1299598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1300598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1301598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1302598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1303598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1304598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1305598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1306598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1307598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1308598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1309598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1310598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1311598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1312598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1313598f6726SAlfredo Cardigliano 
1314598f6726SAlfredo Cardigliano 	return 0;
1315598f6726SAlfredo Cardigliano }
1316598f6726SAlfredo Cardigliano 
1317a27d9013SAlfredo Cardigliano int
1318a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1319a27d9013SAlfredo Cardigliano {
1320a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1321a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1322a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1323a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1324a27d9013SAlfredo Cardigliano 		.pending_work = true,
1325a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1326a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1327a27d9013SAlfredo Cardigliano 			.type = q->type,
1328a27d9013SAlfredo Cardigliano 			.index = q->index,
1329a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1330a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1331a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1332a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1333a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1334a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1335a27d9013SAlfredo Cardigliano 		},
1336a27d9013SAlfredo Cardigliano 	};
1337a27d9013SAlfredo Cardigliano 	int err;
1338a27d9013SAlfredo Cardigliano 
1339a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1340a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1341a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1342a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1343a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13444ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1345a27d9013SAlfredo Cardigliano 
1346a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1347a27d9013SAlfredo Cardigliano 	if (err)
1348a27d9013SAlfredo Cardigliano 		return err;
1349a27d9013SAlfredo Cardigliano 
1350a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1351a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1352a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1353a27d9013SAlfredo Cardigliano 
1354a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1355a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1356a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1357a27d9013SAlfredo Cardigliano 
1358a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1359a27d9013SAlfredo Cardigliano 
1360a27d9013SAlfredo Cardigliano 	return 0;
1361a27d9013SAlfredo Cardigliano }
1362a27d9013SAlfredo Cardigliano 
1363a27d9013SAlfredo Cardigliano int
1364a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1365a27d9013SAlfredo Cardigliano {
1366a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1367a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1368a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1369a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1370a27d9013SAlfredo Cardigliano 		.pending_work = true,
1371a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1372a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1373a27d9013SAlfredo Cardigliano 			.type = q->type,
1374a27d9013SAlfredo Cardigliano 			.index = q->index,
1375a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1376a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1377a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1378a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1379a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1380a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1381a27d9013SAlfredo Cardigliano 		},
1382a27d9013SAlfredo Cardigliano 	};
1383a27d9013SAlfredo Cardigliano 	int err;
1384a27d9013SAlfredo Cardigliano 
1385a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1386a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1387a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1388a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1389a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
13904ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1391a27d9013SAlfredo Cardigliano 
1392a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1393a27d9013SAlfredo Cardigliano 	if (err)
1394a27d9013SAlfredo Cardigliano 		return err;
1395a27d9013SAlfredo Cardigliano 
1396a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1397a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1398a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1399a27d9013SAlfredo Cardigliano 
1400a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1401a27d9013SAlfredo Cardigliano 
1402a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1403a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1404a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1405a27d9013SAlfredo Cardigliano 
1406a27d9013SAlfredo Cardigliano 	return 0;
1407a27d9013SAlfredo Cardigliano }
1408a27d9013SAlfredo Cardigliano 
1409598f6726SAlfredo Cardigliano static int
1410598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1411598f6726SAlfredo Cardigliano {
1412598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1413598f6726SAlfredo Cardigliano 		.pending_work = true,
1414598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1415598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1416598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1417598f6726SAlfredo Cardigliano 		},
1418598f6726SAlfredo Cardigliano 	};
1419598f6726SAlfredo Cardigliano 	int err;
1420598f6726SAlfredo Cardigliano 
1421598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1422598f6726SAlfredo Cardigliano 
1423598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1424598f6726SAlfredo Cardigliano 	if (err)
1425598f6726SAlfredo Cardigliano 		return err;
1426598f6726SAlfredo Cardigliano 
1427598f6726SAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
1428598f6726SAlfredo Cardigliano 			lif->mac_addr)) {
1429598f6726SAlfredo Cardigliano 		IONIC_PRINT(INFO, "deleting station MAC addr");
1430598f6726SAlfredo Cardigliano 
1431598f6726SAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
1432598f6726SAlfredo Cardigliano 	}
1433598f6726SAlfredo Cardigliano 
1434598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1435598f6726SAlfredo Cardigliano 
1436598f6726SAlfredo Cardigliano 	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
1437598f6726SAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
1438598f6726SAlfredo Cardigliano 		return 0;
1439598f6726SAlfredo Cardigliano 	}
1440598f6726SAlfredo Cardigliano 
1441598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adding station MAC addr");
1442598f6726SAlfredo Cardigliano 
1443598f6726SAlfredo Cardigliano 	ionic_lif_addr_add(lif, lif->mac_addr);
1444598f6726SAlfredo Cardigliano 
1445598f6726SAlfredo Cardigliano 	return 0;
1446598f6726SAlfredo Cardigliano }
1447598f6726SAlfredo Cardigliano 
1448598f6726SAlfredo Cardigliano static void
1449598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1450598f6726SAlfredo Cardigliano {
1451598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1452598f6726SAlfredo Cardigliano 		.pending_work = true,
1453598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1454598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1455598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1456598f6726SAlfredo Cardigliano 		},
1457598f6726SAlfredo Cardigliano 	};
1458598f6726SAlfredo Cardigliano 
14594ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
14604ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1461598f6726SAlfredo Cardigliano 
1462598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1463598f6726SAlfredo Cardigliano }
1464598f6726SAlfredo Cardigliano 
1465598f6726SAlfredo Cardigliano int
1466669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1467669c8de6SAlfredo Cardigliano {
1468669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1469669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1470669c8de6SAlfredo Cardigliano 	int err;
1471669c8de6SAlfredo Cardigliano 
14723cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
14733cdfd905SAlfredo Cardigliano 
147400b65da5SAndrew Boyer 	ionic_dev_cmd_lif_init(idev, lif->info_pa);
1475669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1476669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1477669c8de6SAlfredo Cardigliano 	if (err)
1478669c8de6SAlfredo Cardigliano 		return err;
1479669c8de6SAlfredo Cardigliano 
1480669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
1481669c8de6SAlfredo Cardigliano 
148201a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
148301a6c311SAlfredo Cardigliano 	if (err)
148401a6c311SAlfredo Cardigliano 		return err;
148501a6c311SAlfredo Cardigliano 
148627b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
148727b942c8SAlfredo Cardigliano 	if (err)
148827b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
148927b942c8SAlfredo Cardigliano 
1490a27d9013SAlfredo Cardigliano 	lif->features =
1491a27d9013SAlfredo Cardigliano 		  IONIC_ETH_HW_VLAN_TX_TAG
1492a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_STRIP
1493a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_FILTER
1494a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_HASH
1495a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_SG
1496a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_SG
149764b08152SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_CSUM
1498a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_CSUM
1499a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO
1500a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_IPV6
1501a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_ECN;
1502598f6726SAlfredo Cardigliano 
1503598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1504598f6726SAlfredo Cardigliano 	if (err)
1505598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1506598f6726SAlfredo Cardigliano 
150754fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1508598f6726SAlfredo Cardigliano 	if (err)
1509598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1510598f6726SAlfredo Cardigliano 
151154fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
151254fe083fSAlfredo Cardigliano 	if (err)
151354fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
151454fe083fSAlfredo Cardigliano 
1515598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1516598f6726SAlfredo Cardigliano 
1517669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1518669c8de6SAlfredo Cardigliano 
1519669c8de6SAlfredo Cardigliano 	return 0;
152027b942c8SAlfredo Cardigliano 
152154fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
152254fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
152354fe083fSAlfredo Cardigliano 
1524598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
1525598f6726SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1526598f6726SAlfredo Cardigliano 
152727b942c8SAlfredo Cardigliano err_out_adminq_deinit:
152827b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
152927b942c8SAlfredo Cardigliano 
153027b942c8SAlfredo Cardigliano 	return err;
1531669c8de6SAlfredo Cardigliano }
1532669c8de6SAlfredo Cardigliano 
1533669c8de6SAlfredo Cardigliano void
1534669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1535669c8de6SAlfredo Cardigliano {
1536669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1537669c8de6SAlfredo Cardigliano 		return;
1538669c8de6SAlfredo Cardigliano 
153954fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
154022e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
154127b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
154201a6c311SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
154301a6c311SAlfredo Cardigliano 
1544669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1545669c8de6SAlfredo Cardigliano }
1546669c8de6SAlfredo Cardigliano 
1547669c8de6SAlfredo Cardigliano int
1548598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1549598f6726SAlfredo Cardigliano {
155022e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
155122e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
155222e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
155322e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
155422e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
155522e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
155622e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
155722e7171bSAlfredo Cardigliano 
1558598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1559598f6726SAlfredo Cardigliano 
156022e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
156122e7171bSAlfredo Cardigliano 		lif->port_id);
156222e7171bSAlfredo Cardigliano 
156322e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
156422e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
156522e7171bSAlfredo Cardigliano 
156622e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
156722e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
156822e7171bSAlfredo Cardigliano 
156922e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
157022e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1571a27d9013SAlfredo Cardigliano 
1572598f6726SAlfredo Cardigliano 	return 0;
1573598f6726SAlfredo Cardigliano }
1574598f6726SAlfredo Cardigliano 
1575598f6726SAlfredo Cardigliano int
1576598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1577598f6726SAlfredo Cardigliano {
15780578335aSAndrew Boyer 	uint32_t rx_mode;
1579a27d9013SAlfredo Cardigliano 	uint32_t i;
1580a27d9013SAlfredo Cardigliano 	int err;
1581598f6726SAlfredo Cardigliano 
158222e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
158322e7171bSAlfredo Cardigliano 	if (err)
158422e7171bSAlfredo Cardigliano 		return err;
158522e7171bSAlfredo Cardigliano 
15860578335aSAndrew Boyer 	if (!lif->rx_mode) {
15870578335aSAndrew Boyer 		IONIC_PRINT(DEBUG, "Setting RX mode on %s",
15880578335aSAndrew Boyer 			lif->name);
1589598f6726SAlfredo Cardigliano 
15900578335aSAndrew Boyer 		rx_mode  = IONIC_RX_MODE_F_UNICAST;
1591598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1592598f6726SAlfredo Cardigliano 		rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1593598f6726SAlfredo Cardigliano 
1594598f6726SAlfredo Cardigliano 		ionic_set_rx_mode(lif, rx_mode);
15950578335aSAndrew Boyer 	}
1596598f6726SAlfredo Cardigliano 
1597a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1598a27d9013SAlfredo Cardigliano 		"on port %u",
1599a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1600a27d9013SAlfredo Cardigliano 
1601a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1602a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
160302eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1604a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1605a27d9013SAlfredo Cardigliano 
1606a27d9013SAlfredo Cardigliano 			if (err)
1607a27d9013SAlfredo Cardigliano 				return err;
1608a27d9013SAlfredo Cardigliano 		}
1609a27d9013SAlfredo Cardigliano 	}
1610a27d9013SAlfredo Cardigliano 
1611a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1612a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
161302eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1614a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1615a27d9013SAlfredo Cardigliano 
1616a27d9013SAlfredo Cardigliano 			if (err)
1617a27d9013SAlfredo Cardigliano 				return err;
1618a27d9013SAlfredo Cardigliano 		}
1619a27d9013SAlfredo Cardigliano 	}
1620a27d9013SAlfredo Cardigliano 
1621598f6726SAlfredo Cardigliano 	ionic_link_status_check(lif);
1622598f6726SAlfredo Cardigliano 
1623598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1624598f6726SAlfredo Cardigliano 
1625598f6726SAlfredo Cardigliano 	return 0;
1626598f6726SAlfredo Cardigliano }
1627598f6726SAlfredo Cardigliano 
1628598f6726SAlfredo Cardigliano int
1629669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1630669c8de6SAlfredo Cardigliano {
1631669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1632669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1633669c8de6SAlfredo Cardigliano 	int err;
1634669c8de6SAlfredo Cardigliano 	unsigned int i;
1635669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1636669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1637669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1638669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1639669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1640669c8de6SAlfredo Cardigliano 
1641669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1642669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1643669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1644669c8de6SAlfredo Cardigliano 	if (err)
1645669c8de6SAlfredo Cardigliano 		return (err);
1646669c8de6SAlfredo Cardigliano 
1647669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1648669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1649669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1650669c8de6SAlfredo Cardigliano 
1651669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1652669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
1653669c8de6SAlfredo Cardigliano 
1654669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1655669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
1656669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1657669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
1658669c8de6SAlfredo Cardigliano 
1659669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1660669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
1661669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1662669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1663669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1664669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1665669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1666669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1667669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1668669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1669669c8de6SAlfredo Cardigliano 
1670669c8de6SAlfredo Cardigliano 	return 0;
1671669c8de6SAlfredo Cardigliano }
1672669c8de6SAlfredo Cardigliano 
1673669c8de6SAlfredo Cardigliano int
1674669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1675669c8de6SAlfredo Cardigliano {
1676669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1677669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1678669c8de6SAlfredo Cardigliano 
1679669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1680669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1681669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1682669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1683669c8de6SAlfredo Cardigliano 
168400b65da5SAndrew Boyer 	nintrs = 1 /* notifyq */;
1685669c8de6SAlfredo Cardigliano 
1686669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
16874ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
16884ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1689669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1690669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1691669c8de6SAlfredo Cardigliano 	}
1692669c8de6SAlfredo Cardigliano 
1693669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1694669c8de6SAlfredo Cardigliano 
1695669c8de6SAlfredo Cardigliano 	return 0;
1696669c8de6SAlfredo Cardigliano }
1697