xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 4ae96cb88fa06e37766c1bb0d91d1538f8ae34d3)
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 			.lif_index = lif->index,
2901a6c311SAlfredo Cardigliano 			.type = q->type,
3001a6c311SAlfredo Cardigliano 			.index = q->index,
3101a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_ENABLE,
3201a6c311SAlfredo Cardigliano 		},
3301a6c311SAlfredo Cardigliano 	};
3401a6c311SAlfredo Cardigliano 
3501a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
3601a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
3701a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
3801a6c311SAlfredo Cardigliano 	}
3901a6c311SAlfredo Cardigliano 
4001a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
4101a6c311SAlfredo Cardigliano }
4201a6c311SAlfredo Cardigliano 
4301a6c311SAlfredo Cardigliano int
4401a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq)
4501a6c311SAlfredo Cardigliano {
4601a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
4701a6c311SAlfredo Cardigliano 	struct ionic_lif *lif = q->lif;
4801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
4901a6c311SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
5001a6c311SAlfredo Cardigliano 		.pending_work = true,
5101a6c311SAlfredo Cardigliano 		.cmd.q_control = {
5201a6c311SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_CONTROL,
5301a6c311SAlfredo Cardigliano 			.lif_index = lif->index,
5401a6c311SAlfredo Cardigliano 			.type = q->type,
5501a6c311SAlfredo Cardigliano 			.index = q->index,
5601a6c311SAlfredo Cardigliano 			.oper = IONIC_Q_DISABLE,
5701a6c311SAlfredo Cardigliano 		},
5801a6c311SAlfredo Cardigliano 	};
5901a6c311SAlfredo Cardigliano 
6001a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR) {
6101a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
6201a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
6301a6c311SAlfredo Cardigliano 	}
6401a6c311SAlfredo Cardigliano 
6501a6c311SAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
6601a6c311SAlfredo Cardigliano }
6701a6c311SAlfredo Cardigliano 
6801a6c311SAlfredo Cardigliano int
69598f6726SAlfredo Cardigliano ionic_lif_stop(struct ionic_lif *lif __rte_unused)
70598f6726SAlfredo Cardigliano {
71598f6726SAlfredo Cardigliano 	/* Carrier OFF here */
72598f6726SAlfredo Cardigliano 
73598f6726SAlfredo Cardigliano 	return 0;
74598f6726SAlfredo Cardigliano }
75598f6726SAlfredo Cardigliano 
76598f6726SAlfredo Cardigliano void
77598f6726SAlfredo Cardigliano ionic_lif_reset(struct ionic_lif *lif)
78598f6726SAlfredo Cardigliano {
79598f6726SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
8075f96902SAndrew Boyer 	int err;
81598f6726SAlfredo Cardigliano 
82598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
83598f6726SAlfredo Cardigliano 
84598f6726SAlfredo Cardigliano 	ionic_dev_cmd_lif_reset(idev, lif->index);
8575f96902SAndrew Boyer 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
8675f96902SAndrew Boyer 	if (err)
87*4ae96cb8SAndrew Boyer 		IONIC_PRINT(WARNING, "Failed to reset %s", lif->name);
88598f6726SAlfredo Cardigliano }
89598f6726SAlfredo Cardigliano 
903cdfd905SAlfredo Cardigliano static void
913cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
923cdfd905SAlfredo Cardigliano {
933cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
943cdfd905SAlfredo Cardigliano 	uint32_t i;
953cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
963cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
973cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
983cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
993cdfd905SAlfredo Cardigliano 
1003cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
1013cdfd905SAlfredo Cardigliano 
1023cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
1033cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
1043cdfd905SAlfredo Cardigliano 			lif->port_id);
1053cdfd905SAlfredo Cardigliano 		return;
1063cdfd905SAlfredo Cardigliano 	}
1073cdfd905SAlfredo Cardigliano 
1083cdfd905SAlfredo Cardigliano 	/* RX */
1093cdfd905SAlfredo Cardigliano 
1103cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
1113cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
1123cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
1133cdfd905SAlfredo Cardigliano 
1143cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
1153cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
1163cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
1173cdfd905SAlfredo Cardigliano 
1183cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1193cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1203cdfd905SAlfredo Cardigliano 		stats->imissed +=
1213cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1223cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1233cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1243cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1253cdfd905SAlfredo Cardigliano 	}
1263cdfd905SAlfredo Cardigliano 
1273cdfd905SAlfredo Cardigliano 	stats->imissed +=
1283cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
1293cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
1303cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
1313cdfd905SAlfredo Cardigliano 
1323cdfd905SAlfredo Cardigliano 	stats->imissed +=
1333cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
1343cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
1353cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
1363cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
1373cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
1383cdfd905SAlfredo Cardigliano 
1393cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
1403cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
1413cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
1423cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
1433cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
1443cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
1453cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
1463cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
1473cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
1483cdfd905SAlfredo Cardigliano 	}
1493cdfd905SAlfredo Cardigliano 
1503cdfd905SAlfredo Cardigliano 	/* TX */
1513cdfd905SAlfredo Cardigliano 
1523cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
1533cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
1543cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
1553cdfd905SAlfredo Cardigliano 
1563cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
1573cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
1583cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
1593cdfd905SAlfredo Cardigliano 
1603cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1613cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1623cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
1633cdfd905SAlfredo Cardigliano 	}
1643cdfd905SAlfredo Cardigliano 
1653cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1663cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
1673cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
1683cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
1693cdfd905SAlfredo Cardigliano 
1703cdfd905SAlfredo Cardigliano 	stats->oerrors +=
1713cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
1723cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
1733cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
1743cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
1753cdfd905SAlfredo Cardigliano 
1763cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
1773cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
1783cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
1793cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
1803cdfd905SAlfredo Cardigliano 	}
1813cdfd905SAlfredo Cardigliano }
1823cdfd905SAlfredo Cardigliano 
1833cdfd905SAlfredo Cardigliano void
1843cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
1853cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
1863cdfd905SAlfredo Cardigliano {
1873cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
1883cdfd905SAlfredo Cardigliano 
1893cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
1903cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
1913cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
1923cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
1933cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
1943cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
1953cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
1963cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
1973cdfd905SAlfredo Cardigliano }
1983cdfd905SAlfredo Cardigliano 
1993cdfd905SAlfredo Cardigliano void
2003cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
2013cdfd905SAlfredo Cardigliano {
2023cdfd905SAlfredo Cardigliano 	uint32_t i;
2033cdfd905SAlfredo Cardigliano 
2043cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
2053cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
2063cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
2073cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 0,
2083cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
2093cdfd905SAlfredo Cardigliano 	}
2103cdfd905SAlfredo Cardigliano 
2113cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
2123cdfd905SAlfredo Cardigliano }
2133cdfd905SAlfredo Cardigliano 
2143cdfd905SAlfredo Cardigliano void
2153cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
2163cdfd905SAlfredo Cardigliano {
2173cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2183cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
2193cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2203cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2213cdfd905SAlfredo Cardigliano 
2223cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2233cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
2243cdfd905SAlfredo Cardigliano }
2253cdfd905SAlfredo Cardigliano 
2263cdfd905SAlfredo Cardigliano void
2273cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
2283cdfd905SAlfredo Cardigliano {
2293cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
2303cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
2313cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
2323cdfd905SAlfredo Cardigliano 
2333cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
2343cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
2353cdfd905SAlfredo Cardigliano }
2363cdfd905SAlfredo Cardigliano 
237598f6726SAlfredo Cardigliano static int
23854fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
239598f6726SAlfredo Cardigliano {
24054fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
24154fe083fSAlfredo Cardigliano 		.pending_work = true,
24254fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
24354fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
24454fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_MAC,
24554fe083fSAlfredo Cardigliano 		},
24654fe083fSAlfredo Cardigliano 	};
24754fe083fSAlfredo Cardigliano 	int err;
24854fe083fSAlfredo Cardigliano 
24954fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
25054fe083fSAlfredo Cardigliano 
25154fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
25254fe083fSAlfredo Cardigliano 	if (err)
25354fe083fSAlfredo Cardigliano 		return err;
25454fe083fSAlfredo Cardigliano 
25554fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
25654fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
25754fe083fSAlfredo Cardigliano 
25854fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25954fe083fSAlfredo Cardigliano }
26054fe083fSAlfredo Cardigliano 
26154fe083fSAlfredo Cardigliano static int
26254fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
26354fe083fSAlfredo Cardigliano {
26454fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
26554fe083fSAlfredo Cardigliano 		.pending_work = true,
26654fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
26754fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
26854fe083fSAlfredo Cardigliano 		},
26954fe083fSAlfredo Cardigliano 	};
27054fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
27154fe083fSAlfredo Cardigliano 	int err;
27254fe083fSAlfredo Cardigliano 
27354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
27454fe083fSAlfredo Cardigliano 
27554fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
27654fe083fSAlfredo Cardigliano 
27754fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
27854fe083fSAlfredo Cardigliano 	if (!f) {
27954fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
28054fe083fSAlfredo Cardigliano 		return -ENOENT;
28154fe083fSAlfredo Cardigliano 	}
28254fe083fSAlfredo Cardigliano 
28354fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
28454fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
28554fe083fSAlfredo Cardigliano 
28654fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
28754fe083fSAlfredo Cardigliano 
28854fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28954fe083fSAlfredo Cardigliano 	if (err)
29054fe083fSAlfredo Cardigliano 		return err;
29154fe083fSAlfredo Cardigliano 
29254fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
29354fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
294598f6726SAlfredo Cardigliano 
295598f6726SAlfredo Cardigliano 	return 0;
296598f6726SAlfredo Cardigliano }
297598f6726SAlfredo Cardigliano 
29854fe083fSAlfredo Cardigliano int
29954fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
30054fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
30154fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
302598f6726SAlfredo Cardigliano {
30354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30454fe083fSAlfredo Cardigliano 
30554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30654fe083fSAlfredo Cardigliano 
30754fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
30854fe083fSAlfredo Cardigliano }
30954fe083fSAlfredo Cardigliano 
31054fe083fSAlfredo Cardigliano void
31175f96902SAndrew Boyer ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index)
31254fe083fSAlfredo Cardigliano {
31354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31454fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
31575f96902SAndrew Boyer 	struct rte_ether_addr *mac_addr;
31654fe083fSAlfredo Cardigliano 
31754fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31854fe083fSAlfredo Cardigliano 
31954fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
32054fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
32154fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
32254fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
32354fe083fSAlfredo Cardigliano 		return;
32454fe083fSAlfredo Cardigliano 	}
32554fe083fSAlfredo Cardigliano 
32675f96902SAndrew Boyer 	mac_addr = &eth_dev->data->mac_addrs[index];
32775f96902SAndrew Boyer 
32875f96902SAndrew Boyer 	if (!rte_is_valid_assigned_ether_addr(mac_addr))
32954fe083fSAlfredo Cardigliano 		return;
33054fe083fSAlfredo Cardigliano 
33175f96902SAndrew Boyer 	ionic_lif_addr_del(lif, (const uint8_t *)mac_addr);
33254fe083fSAlfredo Cardigliano }
33354fe083fSAlfredo Cardigliano 
33454fe083fSAlfredo Cardigliano int
33554fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
33654fe083fSAlfredo Cardigliano {
33754fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
33854fe083fSAlfredo Cardigliano 
33954fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
34054fe083fSAlfredo Cardigliano 
34154fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
34254fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
34354fe083fSAlfredo Cardigliano 		return -1;
34454fe083fSAlfredo Cardigliano 	}
34554fe083fSAlfredo Cardigliano 
34654fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
34754fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
34854fe083fSAlfredo Cardigliano 			lif->mac_addr);
34954fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
35054fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
35154fe083fSAlfredo Cardigliano 	}
35254fe083fSAlfredo Cardigliano 
35354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
35454fe083fSAlfredo Cardigliano 
35554fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
35654fe083fSAlfredo Cardigliano 
35754fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
35854fe083fSAlfredo Cardigliano }
35954fe083fSAlfredo Cardigliano 
36054fe083fSAlfredo Cardigliano static int
36154fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
36254fe083fSAlfredo Cardigliano {
36354fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
36454fe083fSAlfredo Cardigliano 		.pending_work = true,
36554fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
36654fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
36754fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_VLAN,
36854fe083fSAlfredo Cardigliano 			.vlan.vlan = vid,
36954fe083fSAlfredo Cardigliano 		},
37054fe083fSAlfredo Cardigliano 	};
37154fe083fSAlfredo Cardigliano 	int err;
37254fe083fSAlfredo Cardigliano 
37354fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
37454fe083fSAlfredo Cardigliano 	if (err)
37554fe083fSAlfredo Cardigliano 		return err;
37654fe083fSAlfredo Cardigliano 
37754fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
37854fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
37954fe083fSAlfredo Cardigliano 
38054fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
38154fe083fSAlfredo Cardigliano }
38254fe083fSAlfredo Cardigliano 
38354fe083fSAlfredo Cardigliano static int
38454fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
38554fe083fSAlfredo Cardigliano {
38654fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
38754fe083fSAlfredo Cardigliano 		.pending_work = true,
38854fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38954fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
39054fe083fSAlfredo Cardigliano 		},
39154fe083fSAlfredo Cardigliano 	};
39254fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
39354fe083fSAlfredo Cardigliano 	int err;
39454fe083fSAlfredo Cardigliano 
39554fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
39654fe083fSAlfredo Cardigliano 
39754fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
39854fe083fSAlfredo Cardigliano 
39954fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
40054fe083fSAlfredo Cardigliano 	if (!f) {
40154fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
40254fe083fSAlfredo Cardigliano 		return -ENOENT;
40354fe083fSAlfredo Cardigliano 	}
40454fe083fSAlfredo Cardigliano 
40554fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
40654fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
40754fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
40854fe083fSAlfredo Cardigliano 
40954fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
41054fe083fSAlfredo Cardigliano 	if (err)
41154fe083fSAlfredo Cardigliano 		return err;
41254fe083fSAlfredo Cardigliano 
41354fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
41454fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
415598f6726SAlfredo Cardigliano 
416598f6726SAlfredo Cardigliano 	return 0;
417598f6726SAlfredo Cardigliano }
418598f6726SAlfredo Cardigliano 
41954fe083fSAlfredo Cardigliano int
42054fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
42154fe083fSAlfredo Cardigliano 		int on)
42254fe083fSAlfredo Cardigliano {
42354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
42454fe083fSAlfredo Cardigliano 	int err;
42554fe083fSAlfredo Cardigliano 
42654fe083fSAlfredo Cardigliano 	if (on)
42754fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
42854fe083fSAlfredo Cardigliano 	else
42954fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
43054fe083fSAlfredo Cardigliano 
43154fe083fSAlfredo Cardigliano 	return err;
43254fe083fSAlfredo Cardigliano }
43354fe083fSAlfredo Cardigliano 
434598f6726SAlfredo Cardigliano static void
435598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
436598f6726SAlfredo Cardigliano {
437598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
438598f6726SAlfredo Cardigliano 		.pending_work = true,
439598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
440598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
441598f6726SAlfredo Cardigliano 			.lif_index = lif->index,
442598f6726SAlfredo Cardigliano 			.rx_mode = rx_mode,
443598f6726SAlfredo Cardigliano 		},
444598f6726SAlfredo Cardigliano 	};
445598f6726SAlfredo Cardigliano 	int err;
446598f6726SAlfredo Cardigliano 
447598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
448598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
449598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
450598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
451598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
452598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
453598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
454598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
455598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
456598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
457598f6726SAlfredo Cardigliano 
458598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
459598f6726SAlfredo Cardigliano 	if (err)
460598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
461598f6726SAlfredo Cardigliano }
462598f6726SAlfredo Cardigliano 
463598f6726SAlfredo Cardigliano static void
464598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
465598f6726SAlfredo Cardigliano {
466598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
467598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
468598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
469598f6726SAlfredo Cardigliano 	}
470598f6726SAlfredo Cardigliano }
471598f6726SAlfredo Cardigliano 
47254fe083fSAlfredo Cardigliano int
47354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
47454fe083fSAlfredo Cardigliano {
47554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
47654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
47754fe083fSAlfredo Cardigliano 
47854fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
47954fe083fSAlfredo Cardigliano 
48054fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
48154fe083fSAlfredo Cardigliano 
48254fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
48354fe083fSAlfredo Cardigliano 
48454fe083fSAlfredo Cardigliano 	return 0;
48554fe083fSAlfredo Cardigliano }
48654fe083fSAlfredo Cardigliano 
48754fe083fSAlfredo Cardigliano int
48854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
48954fe083fSAlfredo Cardigliano {
49054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
49254fe083fSAlfredo Cardigliano 
49354fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
49454fe083fSAlfredo Cardigliano 
49554fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49654fe083fSAlfredo Cardigliano 
49754fe083fSAlfredo Cardigliano 	return 0;
49854fe083fSAlfredo Cardigliano }
49954fe083fSAlfredo Cardigliano 
50054fe083fSAlfredo Cardigliano int
50154fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
50254fe083fSAlfredo Cardigliano {
50354fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
50454fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50554fe083fSAlfredo Cardigliano 
50654fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
50754fe083fSAlfredo Cardigliano 
50854fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50954fe083fSAlfredo Cardigliano 
51054fe083fSAlfredo Cardigliano 	return 0;
51154fe083fSAlfredo Cardigliano }
51254fe083fSAlfredo Cardigliano 
51354fe083fSAlfredo Cardigliano int
51454fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
51554fe083fSAlfredo Cardigliano {
51654fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51754fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51854fe083fSAlfredo Cardigliano 
51954fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
52054fe083fSAlfredo Cardigliano 
52154fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
52254fe083fSAlfredo Cardigliano 
52354fe083fSAlfredo Cardigliano 	return 0;
52454fe083fSAlfredo Cardigliano }
525598f6726SAlfredo Cardigliano 
526598f6726SAlfredo Cardigliano int
527598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
528598f6726SAlfredo Cardigliano {
529598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
530598f6726SAlfredo Cardigliano 		.pending_work = true,
531598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
532598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
533598f6726SAlfredo Cardigliano 			.index = lif->index,
534598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
535598f6726SAlfredo Cardigliano 			.mtu = new_mtu,
536598f6726SAlfredo Cardigliano 		},
537598f6726SAlfredo Cardigliano 	};
538598f6726SAlfredo Cardigliano 	int err;
539598f6726SAlfredo Cardigliano 
540598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
541598f6726SAlfredo Cardigliano 	if (err)
542598f6726SAlfredo Cardigliano 		return err;
543598f6726SAlfredo Cardigliano 
544598f6726SAlfredo Cardigliano 	return 0;
545598f6726SAlfredo Cardigliano }
546598f6726SAlfredo Cardigliano 
547598f6726SAlfredo Cardigliano int
54801a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
54901a6c311SAlfredo Cardigliano {
55001a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
55101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
55201a6c311SAlfredo Cardigliano 	unsigned long index;
55301a6c311SAlfredo Cardigliano 
55401a6c311SAlfredo Cardigliano 	/*
55501a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55601a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
557*4ae96cb8SAndrew Boyer 	 * which has index = 0)
55801a6c311SAlfredo Cardigliano 	 */
55901a6c311SAlfredo Cardigliano 
56001a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
56101a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
56201a6c311SAlfredo Cardigliano 			break;
56301a6c311SAlfredo Cardigliano 
56401a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56501a6c311SAlfredo Cardigliano 		return -ENOSPC;
56601a6c311SAlfredo Cardigliano 
56701a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
56801a6c311SAlfredo Cardigliano 
56901a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
57001a6c311SAlfredo Cardigliano 
57101a6c311SAlfredo Cardigliano 	return 0;
57201a6c311SAlfredo Cardigliano }
57301a6c311SAlfredo Cardigliano 
57401a6c311SAlfredo Cardigliano void
57501a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
57601a6c311SAlfredo Cardigliano {
57701a6c311SAlfredo Cardigliano 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
57801a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
57901a6c311SAlfredo Cardigliano }
58001a6c311SAlfredo Cardigliano 
58101a6c311SAlfredo Cardigliano static int
58201a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
58301a6c311SAlfredo Cardigliano 		uint32_t index,
58401a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
58501a6c311SAlfredo Cardigliano 		uint32_t num_descs,
58601a6c311SAlfredo Cardigliano 		uint32_t desc_size,
58701a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
58801a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
5891abf69fcSAndrew Boyer 		struct ionic_qcq **qcq)
59001a6c311SAlfredo Cardigliano {
59101a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
59201a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
59301a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59401a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
59501a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59601a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59701a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59801a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
59901a6c311SAlfredo Cardigliano 	int err;
60001a6c311SAlfredo Cardigliano 
60101a6c311SAlfredo Cardigliano 	*qcq = NULL;
60201a6c311SAlfredo Cardigliano 
60301a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60401a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60501a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60601a6c311SAlfredo Cardigliano 
60701a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
60801a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
60901a6c311SAlfredo Cardigliano 	/*
61001a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
61101a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
61201a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
61301a6c311SAlfredo Cardigliano 	 */
61401a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
61501a6c311SAlfredo Cardigliano 
61601a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61701a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
61801a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
61901a6c311SAlfredo Cardigliano 	}
62001a6c311SAlfredo Cardigliano 
62101a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
62201a6c311SAlfredo Cardigliano 	if (!new) {
62301a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62401a6c311SAlfredo Cardigliano 		return -ENOMEM;
62501a6c311SAlfredo Cardigliano 	}
62601a6c311SAlfredo Cardigliano 
62701a6c311SAlfredo Cardigliano 	new->lif = lif;
62801a6c311SAlfredo Cardigliano 	new->flags = flags;
62901a6c311SAlfredo Cardigliano 
63001a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
63101a6c311SAlfredo Cardigliano 	if (!new->q.info) {
63201a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
63301a6c311SAlfredo Cardigliano 		return -ENOMEM;
63401a6c311SAlfredo Cardigliano 	}
63501a6c311SAlfredo Cardigliano 
63601a6c311SAlfredo Cardigliano 	new->q.type = type;
63701a6c311SAlfredo Cardigliano 
63801a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
6391abf69fcSAndrew Boyer 		desc_size, sg_desc_size);
64001a6c311SAlfredo Cardigliano 	if (err) {
64101a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
64201a6c311SAlfredo Cardigliano 		return err;
64301a6c311SAlfredo Cardigliano 	}
64401a6c311SAlfredo Cardigliano 
64501a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR) {
64601a6c311SAlfredo Cardigliano 		err = ionic_intr_alloc(lif, &new->intr);
64701a6c311SAlfredo Cardigliano 		if (err)
64801a6c311SAlfredo Cardigliano 			return err;
64901a6c311SAlfredo Cardigliano 
65001a6c311SAlfredo Cardigliano 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
65101a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
65201a6c311SAlfredo Cardigliano 	} else {
65301a6c311SAlfredo Cardigliano 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
65401a6c311SAlfredo Cardigliano 	}
65501a6c311SAlfredo Cardigliano 
65601a6c311SAlfredo Cardigliano 	err = ionic_cq_init(lif, &new->cq, &new->intr,
65701a6c311SAlfredo Cardigliano 		num_descs, cq_desc_size);
65801a6c311SAlfredo Cardigliano 	if (err) {
65901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
66001a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
66101a6c311SAlfredo Cardigliano 	}
66201a6c311SAlfredo Cardigliano 
66301a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
66401a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
66501a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66601a6c311SAlfredo Cardigliano 
66701a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66901a6c311SAlfredo Cardigliano 		err = -ENOMEM;
67001a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
67101a6c311SAlfredo Cardigliano 	}
67201a6c311SAlfredo Cardigliano 
67301a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
67401a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67501a6c311SAlfredo Cardigliano 	new->total_size = total_size;
67601a6c311SAlfredo Cardigliano 
67701a6c311SAlfredo Cardigliano 	q_base = new->base;
67801a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67901a6c311SAlfredo Cardigliano 
68001a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
68101a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
68201a6c311SAlfredo Cardigliano 
68301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
68401a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
68501a6c311SAlfredo Cardigliano 			PAGE_SIZE);
68601a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
68701a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68801a6c311SAlfredo Cardigliano 	}
68901a6c311SAlfredo Cardigliano 
690*4ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "Q-Base-PA = %#jx CQ-Base-PA = %#jx "
691*4ae96cb8SAndrew Boyer 		"SG-base-PA = %#jx",
69201a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
69301a6c311SAlfredo Cardigliano 
69401a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69501a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69601a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
69701a6c311SAlfredo Cardigliano 
69801a6c311SAlfredo Cardigliano 	*qcq = new;
69901a6c311SAlfredo Cardigliano 
70001a6c311SAlfredo Cardigliano 	return 0;
70101a6c311SAlfredo Cardigliano 
70201a6c311SAlfredo Cardigliano err_out_free_intr:
70301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR)
70401a6c311SAlfredo Cardigliano 		ionic_intr_free(lif, &new->intr);
70501a6c311SAlfredo Cardigliano 
70601a6c311SAlfredo Cardigliano 	return err;
70701a6c311SAlfredo Cardigliano }
70801a6c311SAlfredo Cardigliano 
70901a6c311SAlfredo Cardigliano void
71001a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
71101a6c311SAlfredo Cardigliano {
71201a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
71301a6c311SAlfredo Cardigliano 		qcq->base = NULL;
71401a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71501a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71601a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71701a6c311SAlfredo Cardigliano 	}
71801a6c311SAlfredo Cardigliano 
71901a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
72001a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
72101a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
72201a6c311SAlfredo Cardigliano 	}
72301a6c311SAlfredo Cardigliano 
72401a6c311SAlfredo Cardigliano 	rte_free(qcq);
72501a6c311SAlfredo Cardigliano }
72601a6c311SAlfredo Cardigliano 
727a27d9013SAlfredo Cardigliano int
728a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
729a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
730a27d9013SAlfredo Cardigliano {
731a27d9013SAlfredo Cardigliano 	uint32_t flags;
732a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
733a27d9013SAlfredo Cardigliano 
734a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
735a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags,
736a27d9013SAlfredo Cardigliano 		nrxq_descs,
737a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
738a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
739a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
7401abf69fcSAndrew Boyer 		&lif->rxqcqs[index]);
741a27d9013SAlfredo Cardigliano 	if (err)
742a27d9013SAlfredo Cardigliano 		return err;
743a27d9013SAlfredo Cardigliano 
744a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
745a27d9013SAlfredo Cardigliano 
746a27d9013SAlfredo Cardigliano 	return 0;
747a27d9013SAlfredo Cardigliano }
748a27d9013SAlfredo Cardigliano 
749a27d9013SAlfredo Cardigliano int
750a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
751a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
752a27d9013SAlfredo Cardigliano {
753a27d9013SAlfredo Cardigliano 	uint32_t flags;
754a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
755a27d9013SAlfredo Cardigliano 
756a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
757a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
758a27d9013SAlfredo Cardigliano 		ntxq_descs,
759a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
760a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
761a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_sg_desc),
7621abf69fcSAndrew Boyer 		&lif->txqcqs[index]);
763a27d9013SAlfredo Cardigliano 	if (err)
764a27d9013SAlfredo Cardigliano 		return err;
765a27d9013SAlfredo Cardigliano 
766a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
767a27d9013SAlfredo Cardigliano 
768a27d9013SAlfredo Cardigliano 	return 0;
769a27d9013SAlfredo Cardigliano }
770a27d9013SAlfredo Cardigliano 
77101a6c311SAlfredo Cardigliano static int
77201a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
77301a6c311SAlfredo Cardigliano {
77401a6c311SAlfredo Cardigliano 	uint32_t flags;
77501a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
77601a6c311SAlfredo Cardigliano 
77701a6c311SAlfredo Cardigliano 	flags = 0;
77801a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
77901a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
78001a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
78101a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
78201a6c311SAlfredo Cardigliano 		0,
7831abf69fcSAndrew Boyer 		&lif->adminqcq);
78427b942c8SAlfredo Cardigliano 	if (err)
78527b942c8SAlfredo Cardigliano 		return err;
78601a6c311SAlfredo Cardigliano 
78727b942c8SAlfredo Cardigliano 	return 0;
78827b942c8SAlfredo Cardigliano }
78927b942c8SAlfredo Cardigliano 
79027b942c8SAlfredo Cardigliano static int
79127b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
79227b942c8SAlfredo Cardigliano {
79327b942c8SAlfredo Cardigliano 	uint32_t flags;
79427b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
79527b942c8SAlfredo Cardigliano 
79627b942c8SAlfredo Cardigliano 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
79727b942c8SAlfredo Cardigliano 
79827b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
79927b942c8SAlfredo Cardigliano 		flags,
80027b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
80127b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
80227b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
80327b942c8SAlfredo Cardigliano 		0,
8041abf69fcSAndrew Boyer 		&lif->notifyqcq);
80501a6c311SAlfredo Cardigliano 	if (err)
80601a6c311SAlfredo Cardigliano 		return err;
80701a6c311SAlfredo Cardigliano 
80801a6c311SAlfredo Cardigliano 	return 0;
80901a6c311SAlfredo Cardigliano }
81001a6c311SAlfredo Cardigliano 
811c67719e1SAlfredo Cardigliano static void *
812c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
813c67719e1SAlfredo Cardigliano {
814c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
815c67719e1SAlfredo Cardigliano 
816c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
817c67719e1SAlfredo Cardigliano 		return NULL;
818c67719e1SAlfredo Cardigliano 
819c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
820c67719e1SAlfredo Cardigliano }
821c67719e1SAlfredo Cardigliano 
822669c8de6SAlfredo Cardigliano int
823669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
824669c8de6SAlfredo Cardigliano {
825c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
826669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
827c67719e1SAlfredo Cardigliano 	int dbpage_num;
82801a6c311SAlfredo Cardigliano 	int err;
829669c8de6SAlfredo Cardigliano 
830*4ae96cb8SAndrew Boyer 	/*
831*4ae96cb8SAndrew Boyer 	 * lif->name was zeroed on allocation.
832*4ae96cb8SAndrew Boyer 	 * Copy (sizeof() - 1) bytes to ensure that it is NULL terminated.
833*4ae96cb8SAndrew Boyer 	 */
834*4ae96cb8SAndrew Boyer 	memcpy(lif->name, lif->eth_dev->data->name, sizeof(lif->name) - 1);
835*4ae96cb8SAndrew Boyer 
836*4ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "LIF: %s", lif->name);
837669c8de6SAlfredo Cardigliano 
838669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
839669c8de6SAlfredo Cardigliano 
84001a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
84101a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
84201a6c311SAlfredo Cardigliano 
843c67719e1SAlfredo Cardigliano 	dbpage_num = ionic_db_page_num(lif, 0);
844c67719e1SAlfredo Cardigliano 
845c67719e1SAlfredo Cardigliano 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
846c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
847c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
848c67719e1SAlfredo Cardigliano 		return -ENOMEM;
849c67719e1SAlfredo Cardigliano 	}
850c67719e1SAlfredo Cardigliano 
851a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
852a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
853a27d9013SAlfredo Cardigliano 
854a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
855a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
856a27d9013SAlfredo Cardigliano 		return -ENOMEM;
857a27d9013SAlfredo Cardigliano 	}
858a27d9013SAlfredo Cardigliano 
859a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
860a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
861a27d9013SAlfredo Cardigliano 
862a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
863a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
864a27d9013SAlfredo Cardigliano 		return -ENOMEM;
865a27d9013SAlfredo Cardigliano 	}
866a27d9013SAlfredo Cardigliano 
86727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
86827b942c8SAlfredo Cardigliano 
86927b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
87027b942c8SAlfredo Cardigliano 	if (err) {
87127b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
87227b942c8SAlfredo Cardigliano 		return err;
87327b942c8SAlfredo Cardigliano 	}
87427b942c8SAlfredo Cardigliano 
87527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
87627b942c8SAlfredo Cardigliano 
87701a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
87801a6c311SAlfredo Cardigliano 	if (err) {
87901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
88001a6c311SAlfredo Cardigliano 		return err;
88101a6c311SAlfredo Cardigliano 	}
88201a6c311SAlfredo Cardigliano 
88301a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
88401a6c311SAlfredo Cardigliano 
885669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
886669c8de6SAlfredo Cardigliano 
887669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
888669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
889669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
890669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
891669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
892669c8de6SAlfredo Cardigliano 		return -ENOMEM;
893669c8de6SAlfredo Cardigliano 	}
894669c8de6SAlfredo Cardigliano 
895669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
896669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
897669c8de6SAlfredo Cardigliano 
898669c8de6SAlfredo Cardigliano 	return 0;
899669c8de6SAlfredo Cardigliano }
900669c8de6SAlfredo Cardigliano 
901669c8de6SAlfredo Cardigliano void
902669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
903669c8de6SAlfredo Cardigliano {
90427b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
90527b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
90627b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
90727b942c8SAlfredo Cardigliano 	}
90827b942c8SAlfredo Cardigliano 
90901a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
91001a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
91101a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
91201a6c311SAlfredo Cardigliano 	}
91301a6c311SAlfredo Cardigliano 
914a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
915a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
916a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
917a27d9013SAlfredo Cardigliano 	}
918a27d9013SAlfredo Cardigliano 
919a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
920a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
921a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
922a27d9013SAlfredo Cardigliano 	}
923a27d9013SAlfredo Cardigliano 
924669c8de6SAlfredo Cardigliano 	if (lif->info) {
925669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
926669c8de6SAlfredo Cardigliano 		lif->info = NULL;
927669c8de6SAlfredo Cardigliano 	}
928669c8de6SAlfredo Cardigliano }
929669c8de6SAlfredo Cardigliano 
93022e7171bSAlfredo Cardigliano int
93122e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
93222e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
93322e7171bSAlfredo Cardigliano {
93422e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
93522e7171bSAlfredo Cardigliano 		.pending_work = true,
93622e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
93722e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
93822e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
93922e7171bSAlfredo Cardigliano 			.rss.types = types,
94022e7171bSAlfredo Cardigliano 			.rss.addr = lif->rss_ind_tbl_pa,
94122e7171bSAlfredo Cardigliano 		},
94222e7171bSAlfredo Cardigliano 	};
94322e7171bSAlfredo Cardigliano 	unsigned int i;
94422e7171bSAlfredo Cardigliano 
94522e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
94622e7171bSAlfredo Cardigliano 
94722e7171bSAlfredo Cardigliano 	lif->rss_types = types;
94822e7171bSAlfredo Cardigliano 
94922e7171bSAlfredo Cardigliano 	if (key)
95022e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
95122e7171bSAlfredo Cardigliano 
95222e7171bSAlfredo Cardigliano 	if (indir)
95322e7171bSAlfredo Cardigliano 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
95422e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
95522e7171bSAlfredo Cardigliano 
95622e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
95722e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
95822e7171bSAlfredo Cardigliano 
95922e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
96022e7171bSAlfredo Cardigliano }
96122e7171bSAlfredo Cardigliano 
96222e7171bSAlfredo Cardigliano static int
96322e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
96422e7171bSAlfredo Cardigliano {
96522e7171bSAlfredo Cardigliano 	size_t tbl_size = sizeof(*lif->rss_ind_tbl) *
96622e7171bSAlfredo Cardigliano 		lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
96722e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
96822e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96922e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97022e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97122e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97222e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
97322e7171bSAlfredo Cardigliano 	};
97422e7171bSAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
97522e7171bSAlfredo Cardigliano 	uint32_t i;
97622e7171bSAlfredo Cardigliano 	int err;
97722e7171bSAlfredo Cardigliano 
97822e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
97922e7171bSAlfredo Cardigliano 
98022e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
98122e7171bSAlfredo Cardigliano 		"rss_ind_tbl",
98222e7171bSAlfredo Cardigliano 		0 /* queue_idx*/, tbl_size, IONIC_ALIGN, socket_id);
98322e7171bSAlfredo Cardigliano 
98422e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl_z) {
98522e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "OOM");
98622e7171bSAlfredo Cardigliano 		return -ENOMEM;
98722e7171bSAlfredo Cardigliano 	}
98822e7171bSAlfredo Cardigliano 
98922e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
99022e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
99122e7171bSAlfredo Cardigliano 
99222e7171bSAlfredo Cardigliano 	/* Fill indirection table with 'default' values */
99322e7171bSAlfredo Cardigliano 	for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
99422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
99522e7171bSAlfredo Cardigliano 
99622e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
99722e7171bSAlfredo Cardigliano 		toeplitz_symmetric_key, NULL);
99822e7171bSAlfredo Cardigliano 	if (err)
99922e7171bSAlfredo Cardigliano 		return err;
100022e7171bSAlfredo Cardigliano 
100122e7171bSAlfredo Cardigliano 	return 0;
100222e7171bSAlfredo Cardigliano }
100322e7171bSAlfredo Cardigliano 
100422e7171bSAlfredo Cardigliano static void
100522e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
100622e7171bSAlfredo Cardigliano {
100722e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
100822e7171bSAlfredo Cardigliano 		return;
100922e7171bSAlfredo Cardigliano 
101022e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
101122e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
101222e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
101322e7171bSAlfredo Cardigliano 
101422e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
101522e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
101622e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
101722e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
101822e7171bSAlfredo Cardigliano 	}
101922e7171bSAlfredo Cardigliano }
102022e7171bSAlfredo Cardigliano 
102101a6c311SAlfredo Cardigliano static void
102201a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
102301a6c311SAlfredo Cardigliano {
102401a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
102501a6c311SAlfredo Cardigliano 
102601a6c311SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
102701a6c311SAlfredo Cardigliano 		return;
102801a6c311SAlfredo Cardigliano 
102901a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
103001a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
103101a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
103201a6c311SAlfredo Cardigliano 
103301a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
103401a6c311SAlfredo Cardigliano }
103501a6c311SAlfredo Cardigliano 
1036a27d9013SAlfredo Cardigliano void
1037a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1038a27d9013SAlfredo Cardigliano {
1039a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1040a27d9013SAlfredo Cardigliano }
1041a27d9013SAlfredo Cardigliano 
1042a27d9013SAlfredo Cardigliano void
1043a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1044a27d9013SAlfredo Cardigliano {
1045a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1046a27d9013SAlfredo Cardigliano }
1047a27d9013SAlfredo Cardigliano 
104801a6c311SAlfredo Cardigliano bool
104901a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
105001a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
105101a6c311SAlfredo Cardigliano {
105201a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
105301a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
105401a6c311SAlfredo Cardigliano 
105501a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
105601a6c311SAlfredo Cardigliano 		return false;
105701a6c311SAlfredo Cardigliano 
105801a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
105901a6c311SAlfredo Cardigliano 
106001a6c311SAlfredo Cardigliano 	return true;
106101a6c311SAlfredo Cardigliano }
106201a6c311SAlfredo Cardigliano 
106301a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
106401a6c311SAlfredo Cardigliano int
106501a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
106601a6c311SAlfredo Cardigliano 		void *cb_arg)
106701a6c311SAlfredo Cardigliano {
106801a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
106901a6c311SAlfredo Cardigliano 	uint32_t work_done;
107001a6c311SAlfredo Cardigliano 
107101a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
107201a6c311SAlfredo Cardigliano 
107301a6c311SAlfredo Cardigliano 	return work_done;
107401a6c311SAlfredo Cardigliano }
107501a6c311SAlfredo Cardigliano 
107627b942c8SAlfredo Cardigliano static void
107727b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
107827b942c8SAlfredo Cardigliano {
107927b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
108027b942c8SAlfredo Cardigliano 	bool link_up;
108127b942c8SAlfredo Cardigliano 
108227b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
108327b942c8SAlfredo Cardigliano 
108427b942c8SAlfredo Cardigliano 	if (!lif->info)
108527b942c8SAlfredo Cardigliano 		return;
108627b942c8SAlfredo Cardigliano 
108727b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
108827b942c8SAlfredo Cardigliano 
108927b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
109027b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
109127b942c8SAlfredo Cardigliano 		return;
109227b942c8SAlfredo Cardigliano 
109327b942c8SAlfredo Cardigliano 	if (link_up) {
109427b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
109527b942c8SAlfredo Cardigliano 			lif->info->status.link_speed);
109627b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
109727b942c8SAlfredo Cardigliano 	} else {
109827b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
109927b942c8SAlfredo Cardigliano 	}
110027b942c8SAlfredo Cardigliano 
110127b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
110227b942c8SAlfredo Cardigliano }
110327b942c8SAlfredo Cardigliano 
110427b942c8SAlfredo Cardigliano static bool
110527b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
110627b942c8SAlfredo Cardigliano {
110727b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
110827b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
110927b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
111027b942c8SAlfredo Cardigliano 
111127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
111227b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
111327b942c8SAlfredo Cardigliano 
111427b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
111527b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
111627b942c8SAlfredo Cardigliano 		return false;
111727b942c8SAlfredo Cardigliano 
111827b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
111927b942c8SAlfredo Cardigliano 
112027b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
112127b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
112227b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
112327b942c8SAlfredo Cardigliano 			"Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
112427b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
112527b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
112627b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
112727b942c8SAlfredo Cardigliano 
112827b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
112927b942c8SAlfredo Cardigliano 
113027b942c8SAlfredo Cardigliano 		break;
113127b942c8SAlfredo Cardigliano 	default:
113227b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
113327b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
113427b942c8SAlfredo Cardigliano 		break;
113527b942c8SAlfredo Cardigliano 	}
113627b942c8SAlfredo Cardigliano 
113727b942c8SAlfredo Cardigliano 	return true;
113827b942c8SAlfredo Cardigliano }
113927b942c8SAlfredo Cardigliano 
114027b942c8SAlfredo Cardigliano int
114127b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
114227b942c8SAlfredo Cardigliano {
114327b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
114427b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
114527b942c8SAlfredo Cardigliano 	uint32_t work_done;
114627b942c8SAlfredo Cardigliano 
114727b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
114827b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
114927b942c8SAlfredo Cardigliano 		return -1;
115027b942c8SAlfredo Cardigliano 	}
115127b942c8SAlfredo Cardigliano 
115227b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
115327b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
115427b942c8SAlfredo Cardigliano 
115527b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
115627b942c8SAlfredo Cardigliano 
115727b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
115827b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
115927b942c8SAlfredo Cardigliano 
116027b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
116127b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
116227b942c8SAlfredo Cardigliano 
116327b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
116427b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
116527b942c8SAlfredo Cardigliano 
116627b942c8SAlfredo Cardigliano 	return 0;
116727b942c8SAlfredo Cardigliano }
116827b942c8SAlfredo Cardigliano 
116901a6c311SAlfredo Cardigliano static int
117001a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
117101a6c311SAlfredo Cardigliano {
117201a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
117301a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
117401a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
117501a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
117601a6c311SAlfredo Cardigliano 	int err;
117701a6c311SAlfredo Cardigliano 
117801a6c311SAlfredo Cardigliano 	ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);
117901a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
118001a6c311SAlfredo Cardigliano 	if (err)
118101a6c311SAlfredo Cardigliano 		return err;
118201a6c311SAlfredo Cardigliano 
118301a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
118401a6c311SAlfredo Cardigliano 
118501a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
118601a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
118701a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
118801a6c311SAlfredo Cardigliano 
118901a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
119001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
119101a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
119201a6c311SAlfredo Cardigliano 
119301a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
119401a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
119501a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
119601a6c311SAlfredo Cardigliano 
119701a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
119801a6c311SAlfredo Cardigliano 
119901a6c311SAlfredo Cardigliano 	return 0;
120001a6c311SAlfredo Cardigliano }
120101a6c311SAlfredo Cardigliano 
120227b942c8SAlfredo Cardigliano static int
120327b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
120427b942c8SAlfredo Cardigliano {
120527b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
120627b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
120727b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
120827b942c8SAlfredo Cardigliano 	int err;
120927b942c8SAlfredo Cardigliano 
121027b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
121127b942c8SAlfredo Cardigliano 		.pending_work = true,
121227b942c8SAlfredo Cardigliano 		.cmd.q_init = {
121327b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
121427b942c8SAlfredo Cardigliano 			.lif_index = lif->index,
121527b942c8SAlfredo Cardigliano 			.type = q->type,
121627b942c8SAlfredo Cardigliano 			.index = q->index,
121727b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
121827b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
121927b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
122027b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
122127b942c8SAlfredo Cardigliano 		}
122227b942c8SAlfredo Cardigliano 	};
122327b942c8SAlfredo Cardigliano 
122427b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
122527b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
122627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
122727b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
122827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
122927b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
1230*4ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "notifyq_init.ver %u", ctx.cmd.q_init.ver);
123127b942c8SAlfredo Cardigliano 
123227b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
123327b942c8SAlfredo Cardigliano 	if (err)
123427b942c8SAlfredo Cardigliano 		return err;
123527b942c8SAlfredo Cardigliano 
123627b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
123727b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
123827b942c8SAlfredo Cardigliano 	q->db = NULL;
123927b942c8SAlfredo Cardigliano 
124027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
124127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
124227b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
124327b942c8SAlfredo Cardigliano 
124427b942c8SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
124527b942c8SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
124627b942c8SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
124727b942c8SAlfredo Cardigliano 
124827b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
124927b942c8SAlfredo Cardigliano 
125027b942c8SAlfredo Cardigliano 	return 0;
125127b942c8SAlfredo Cardigliano }
125227b942c8SAlfredo Cardigliano 
1253669c8de6SAlfredo Cardigliano int
1254598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1255598f6726SAlfredo Cardigliano {
1256598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1257598f6726SAlfredo Cardigliano 		.pending_work = true,
1258598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1259598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1260598f6726SAlfredo Cardigliano 			.index = lif->index,
1261598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1262598f6726SAlfredo Cardigliano 			.features = lif->features,
1263598f6726SAlfredo Cardigliano 		},
1264598f6726SAlfredo Cardigliano 	};
1265598f6726SAlfredo Cardigliano 	int err;
1266598f6726SAlfredo Cardigliano 
1267598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1268598f6726SAlfredo Cardigliano 	if (err)
1269598f6726SAlfredo Cardigliano 		return err;
1270598f6726SAlfredo Cardigliano 
1271598f6726SAlfredo Cardigliano 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1272598f6726SAlfredo Cardigliano 		ctx.comp.lif_setattr.features);
1273598f6726SAlfredo Cardigliano 
1274598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1275598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1276598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1277598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1278598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1279598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1280598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1281598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1282598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1283598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1284598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1285598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1286598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1287598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1288598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1289598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1290598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1291598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1292598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1293598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1294598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1295598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1296598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1297598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1298598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1299598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1300598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1301598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1302598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1303598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1304598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1305598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1306598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1307598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1308598f6726SAlfredo Cardigliano 
1309598f6726SAlfredo Cardigliano 	return 0;
1310598f6726SAlfredo Cardigliano }
1311598f6726SAlfredo Cardigliano 
1312a27d9013SAlfredo Cardigliano int
1313a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1314a27d9013SAlfredo Cardigliano {
1315a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1316a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1317a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1318a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1319a27d9013SAlfredo Cardigliano 		.pending_work = true,
1320a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1321a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1322a27d9013SAlfredo Cardigliano 			.lif_index = lif->index,
1323a27d9013SAlfredo Cardigliano 			.type = q->type,
1324a27d9013SAlfredo Cardigliano 			.index = q->index,
1325a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1326a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1327a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1328a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1329a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1330a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1331a27d9013SAlfredo Cardigliano 		},
1332a27d9013SAlfredo Cardigliano 	};
1333a27d9013SAlfredo Cardigliano 	int err;
1334a27d9013SAlfredo Cardigliano 
1335a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1336a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1337a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1338a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1339a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
1340*4ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "txq_init.ver %u", ctx.cmd.q_init.ver);
1341a27d9013SAlfredo Cardigliano 
1342a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1343a27d9013SAlfredo Cardigliano 	if (err)
1344a27d9013SAlfredo Cardigliano 		return err;
1345a27d9013SAlfredo Cardigliano 
1346a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1347a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1348a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1349a27d9013SAlfredo Cardigliano 
1350a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1351a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1352a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1353a27d9013SAlfredo Cardigliano 
1354a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1355a27d9013SAlfredo Cardigliano 
1356a27d9013SAlfredo Cardigliano 	return 0;
1357a27d9013SAlfredo Cardigliano }
1358a27d9013SAlfredo Cardigliano 
1359a27d9013SAlfredo Cardigliano int
1360a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1361a27d9013SAlfredo Cardigliano {
1362a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1363a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1364a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1365a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1366a27d9013SAlfredo Cardigliano 		.pending_work = true,
1367a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1368a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1369a27d9013SAlfredo Cardigliano 			.lif_index = lif->index,
1370a27d9013SAlfredo Cardigliano 			.type = q->type,
1371a27d9013SAlfredo Cardigliano 			.index = q->index,
1372a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1373a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1374a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1375a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1376a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1377a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1378a27d9013SAlfredo Cardigliano 		},
1379a27d9013SAlfredo Cardigliano 	};
1380a27d9013SAlfredo Cardigliano 	int err;
1381a27d9013SAlfredo Cardigliano 
1382a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1383a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1384a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1385a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1386a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
1387*4ae96cb8SAndrew Boyer 	IONIC_PRINT(DEBUG, "rxq_init.ver %u", ctx.cmd.q_init.ver);
1388a27d9013SAlfredo Cardigliano 
1389a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1390a27d9013SAlfredo Cardigliano 	if (err)
1391a27d9013SAlfredo Cardigliano 		return err;
1392a27d9013SAlfredo Cardigliano 
1393a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1394a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1395a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1396a27d9013SAlfredo Cardigliano 
1397a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1398a27d9013SAlfredo Cardigliano 
1399a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1400a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1401a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1402a27d9013SAlfredo Cardigliano 
1403a27d9013SAlfredo Cardigliano 	return 0;
1404a27d9013SAlfredo Cardigliano }
1405a27d9013SAlfredo Cardigliano 
1406598f6726SAlfredo Cardigliano static int
1407598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1408598f6726SAlfredo Cardigliano {
1409598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1410598f6726SAlfredo Cardigliano 		.pending_work = true,
1411598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1412598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1413598f6726SAlfredo Cardigliano 			.index = lif->index,
1414598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1415598f6726SAlfredo Cardigliano 		},
1416598f6726SAlfredo Cardigliano 	};
1417598f6726SAlfredo Cardigliano 	int err;
1418598f6726SAlfredo Cardigliano 
1419598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1420598f6726SAlfredo Cardigliano 
1421598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1422598f6726SAlfredo Cardigliano 	if (err)
1423598f6726SAlfredo Cardigliano 		return err;
1424598f6726SAlfredo Cardigliano 
1425598f6726SAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
1426598f6726SAlfredo Cardigliano 			lif->mac_addr)) {
1427598f6726SAlfredo Cardigliano 		IONIC_PRINT(INFO, "deleting station MAC addr");
1428598f6726SAlfredo Cardigliano 
1429598f6726SAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
1430598f6726SAlfredo Cardigliano 	}
1431598f6726SAlfredo Cardigliano 
1432598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1433598f6726SAlfredo Cardigliano 
1434598f6726SAlfredo Cardigliano 	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
1435598f6726SAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
1436598f6726SAlfredo Cardigliano 		return 0;
1437598f6726SAlfredo Cardigliano 	}
1438598f6726SAlfredo Cardigliano 
1439598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adding station MAC addr");
1440598f6726SAlfredo Cardigliano 
1441598f6726SAlfredo Cardigliano 	ionic_lif_addr_add(lif, lif->mac_addr);
1442598f6726SAlfredo Cardigliano 
1443598f6726SAlfredo Cardigliano 	return 0;
1444598f6726SAlfredo Cardigliano }
1445598f6726SAlfredo Cardigliano 
1446598f6726SAlfredo Cardigliano static void
1447598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1448598f6726SAlfredo Cardigliano {
1449598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1450598f6726SAlfredo Cardigliano 		.pending_work = true,
1451598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1452598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1453598f6726SAlfredo Cardigliano 			.index = lif->index,
1454598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1455598f6726SAlfredo Cardigliano 		},
1456598f6726SAlfredo Cardigliano 	};
1457598f6726SAlfredo Cardigliano 
1458*4ae96cb8SAndrew Boyer 	memcpy(ctx.cmd.lif_setattr.name, lif->name,
1459*4ae96cb8SAndrew Boyer 		sizeof(ctx.cmd.lif_setattr.name) - 1);
1460598f6726SAlfredo Cardigliano 
1461598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1462598f6726SAlfredo Cardigliano }
1463598f6726SAlfredo Cardigliano 
1464598f6726SAlfredo Cardigliano int
1465669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1466669c8de6SAlfredo Cardigliano {
1467669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1468669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1469669c8de6SAlfredo Cardigliano 	int err;
1470669c8de6SAlfredo Cardigliano 
14713cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
14723cdfd905SAlfredo Cardigliano 
1473669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
1474669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1475669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1476669c8de6SAlfredo Cardigliano 	if (err)
1477669c8de6SAlfredo Cardigliano 		return err;
1478669c8de6SAlfredo Cardigliano 
1479669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
1480669c8de6SAlfredo Cardigliano 
148101a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
148201a6c311SAlfredo Cardigliano 	if (err)
148301a6c311SAlfredo Cardigliano 		return err;
148401a6c311SAlfredo Cardigliano 
148527b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
148627b942c8SAlfredo Cardigliano 	if (err)
148727b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
148827b942c8SAlfredo Cardigliano 
1489a27d9013SAlfredo Cardigliano 	lif->features =
1490a27d9013SAlfredo Cardigliano 		  IONIC_ETH_HW_VLAN_TX_TAG
1491a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_STRIP
1492a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_FILTER
1493a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_HASH
1494a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_SG
1495a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_SG
149664b08152SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_CSUM
1497a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_CSUM
1498a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO
1499a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_IPV6
1500a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_ECN;
1501598f6726SAlfredo Cardigliano 
1502598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1503598f6726SAlfredo Cardigliano 	if (err)
1504598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1505598f6726SAlfredo Cardigliano 
150654fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1507598f6726SAlfredo Cardigliano 	if (err)
1508598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1509598f6726SAlfredo Cardigliano 
151054fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
151154fe083fSAlfredo Cardigliano 	if (err)
151254fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
151354fe083fSAlfredo Cardigliano 
1514598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1515598f6726SAlfredo Cardigliano 
1516669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1517669c8de6SAlfredo Cardigliano 
1518669c8de6SAlfredo Cardigliano 	return 0;
151927b942c8SAlfredo Cardigliano 
152054fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
152154fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
152254fe083fSAlfredo Cardigliano 
1523598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
1524598f6726SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1525598f6726SAlfredo Cardigliano 
152627b942c8SAlfredo Cardigliano err_out_adminq_deinit:
152727b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
152827b942c8SAlfredo Cardigliano 
152927b942c8SAlfredo Cardigliano 	return err;
1530669c8de6SAlfredo Cardigliano }
1531669c8de6SAlfredo Cardigliano 
1532669c8de6SAlfredo Cardigliano void
1533669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1534669c8de6SAlfredo Cardigliano {
1535669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1536669c8de6SAlfredo Cardigliano 		return;
1537669c8de6SAlfredo Cardigliano 
153854fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
153922e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
154027b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
154101a6c311SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
154201a6c311SAlfredo Cardigliano 
1543669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1544669c8de6SAlfredo Cardigliano }
1545669c8de6SAlfredo Cardigliano 
1546669c8de6SAlfredo Cardigliano int
1547598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1548598f6726SAlfredo Cardigliano {
154922e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
155022e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
155122e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
155222e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
155322e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
155422e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
155522e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
155622e7171bSAlfredo Cardigliano 
1557598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1558598f6726SAlfredo Cardigliano 
155922e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
156022e7171bSAlfredo Cardigliano 		lif->port_id);
156122e7171bSAlfredo Cardigliano 
156222e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
156322e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
156422e7171bSAlfredo Cardigliano 
156522e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
156622e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
156722e7171bSAlfredo Cardigliano 
156822e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
156922e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1570a27d9013SAlfredo Cardigliano 
1571598f6726SAlfredo Cardigliano 	return 0;
1572598f6726SAlfredo Cardigliano }
1573598f6726SAlfredo Cardigliano 
1574598f6726SAlfredo Cardigliano int
1575598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1576598f6726SAlfredo Cardigliano {
1577598f6726SAlfredo Cardigliano 	uint32_t rx_mode = 0;
1578a27d9013SAlfredo Cardigliano 	uint32_t i;
1579a27d9013SAlfredo Cardigliano 	int err;
1580598f6726SAlfredo Cardigliano 
158122e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Setting RSS configuration on port %u",
158222e7171bSAlfredo Cardigliano 		lif->port_id);
158322e7171bSAlfredo Cardigliano 
158422e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
158522e7171bSAlfredo Cardigliano 	if (err)
158622e7171bSAlfredo Cardigliano 		return err;
158722e7171bSAlfredo Cardigliano 
1588598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Setting RX mode on port %u",
1589598f6726SAlfredo Cardigliano 		lif->port_id);
1590598f6726SAlfredo Cardigliano 
1591598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_UNICAST;
1592598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1593598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1594598f6726SAlfredo Cardigliano 
1595598f6726SAlfredo Cardigliano 	lif->rx_mode = 0; /* set by ionic_set_rx_mode */
1596598f6726SAlfredo Cardigliano 
1597598f6726SAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
1598598f6726SAlfredo Cardigliano 
1599a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1600a27d9013SAlfredo Cardigliano 		"on port %u",
1601a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1602a27d9013SAlfredo Cardigliano 
1603a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1604a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
160502eabf57SAndrew Boyer 		if (!(rxq->flags & IONIC_QCQ_F_DEFERRED)) {
1606a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1607a27d9013SAlfredo Cardigliano 
1608a27d9013SAlfredo Cardigliano 			if (err)
1609a27d9013SAlfredo Cardigliano 				return err;
1610a27d9013SAlfredo Cardigliano 		}
1611a27d9013SAlfredo Cardigliano 	}
1612a27d9013SAlfredo Cardigliano 
1613a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1614a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
161502eabf57SAndrew Boyer 		if (!(txq->flags & IONIC_QCQ_F_DEFERRED)) {
1616a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1617a27d9013SAlfredo Cardigliano 
1618a27d9013SAlfredo Cardigliano 			if (err)
1619a27d9013SAlfredo Cardigliano 				return err;
1620a27d9013SAlfredo Cardigliano 		}
1621a27d9013SAlfredo Cardigliano 	}
1622a27d9013SAlfredo Cardigliano 
1623598f6726SAlfredo Cardigliano 	ionic_link_status_check(lif);
1624598f6726SAlfredo Cardigliano 
1625598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1626598f6726SAlfredo Cardigliano 
1627598f6726SAlfredo Cardigliano 	return 0;
1628598f6726SAlfredo Cardigliano }
1629598f6726SAlfredo Cardigliano 
1630598f6726SAlfredo Cardigliano int
1631669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1632669c8de6SAlfredo Cardigliano {
1633669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1634669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1635669c8de6SAlfredo Cardigliano 	int err;
1636669c8de6SAlfredo Cardigliano 	unsigned int i;
1637669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1638669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1639669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1640669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1641669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1642669c8de6SAlfredo Cardigliano 
1643669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1644669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1645669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1646669c8de6SAlfredo Cardigliano 	if (err)
1647669c8de6SAlfredo Cardigliano 		return (err);
1648669c8de6SAlfredo Cardigliano 
1649669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1650669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1651669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1652669c8de6SAlfredo Cardigliano 
1653669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1654669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
1655669c8de6SAlfredo Cardigliano 
1656669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1657669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
1658669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1659669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
1660669c8de6SAlfredo Cardigliano 
1661669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1662669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
1663669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1664669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1665669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1666669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1667669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1668669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1669669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1670669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1671669c8de6SAlfredo Cardigliano 
1672669c8de6SAlfredo Cardigliano 	return 0;
1673669c8de6SAlfredo Cardigliano }
1674669c8de6SAlfredo Cardigliano 
1675669c8de6SAlfredo Cardigliano int
1676669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1677669c8de6SAlfredo Cardigliano {
1678669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1679669c8de6SAlfredo Cardigliano 	uint32_t nlifs = ident->dev.nlifs;
1680669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1681669c8de6SAlfredo Cardigliano 
1682669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1683669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1684669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1685669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1686669c8de6SAlfredo Cardigliano 
1687669c8de6SAlfredo Cardigliano 	nintrs = nlifs * 1 /* notifyq */;
1688669c8de6SAlfredo Cardigliano 
1689669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
1690*4ae96cb8SAndrew Boyer 		IONIC_PRINT(ERR,
1691*4ae96cb8SAndrew Boyer 			"At most %d intr supported, minimum req'd is %u",
1692669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1693669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1694669c8de6SAlfredo Cardigliano 	}
1695669c8de6SAlfredo Cardigliano 
1696669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1697669c8de6SAlfredo Cardigliano 
1698669c8de6SAlfredo Cardigliano 	return 0;
1699669c8de6SAlfredo Cardigliano }
1700