xref: /dpdk/drivers/net/ionic/ionic_lif.c (revision 3cdfd90579e74902003d368cbf02c51c4782e3eb)
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;
80598f6726SAlfredo Cardigliano 
81598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
82598f6726SAlfredo Cardigliano 
83598f6726SAlfredo Cardigliano 	ionic_dev_cmd_lif_reset(idev, lif->index);
84598f6726SAlfredo Cardigliano 	ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
85598f6726SAlfredo Cardigliano }
86598f6726SAlfredo Cardigliano 
87*3cdfd905SAlfredo Cardigliano static void
88*3cdfd905SAlfredo Cardigliano ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
89*3cdfd905SAlfredo Cardigliano {
90*3cdfd905SAlfredo Cardigliano 	struct ionic_lif_stats *ls = &lif->info->stats;
91*3cdfd905SAlfredo Cardigliano 	uint32_t i;
92*3cdfd905SAlfredo Cardigliano 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
93*3cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
94*3cdfd905SAlfredo Cardigliano 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
95*3cdfd905SAlfredo Cardigliano 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
96*3cdfd905SAlfredo Cardigliano 
97*3cdfd905SAlfredo Cardigliano 	memset(stats, 0, sizeof(*stats));
98*3cdfd905SAlfredo Cardigliano 
99*3cdfd905SAlfredo Cardigliano 	if (ls == NULL) {
100*3cdfd905SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
101*3cdfd905SAlfredo Cardigliano 			lif->port_id);
102*3cdfd905SAlfredo Cardigliano 		return;
103*3cdfd905SAlfredo Cardigliano 	}
104*3cdfd905SAlfredo Cardigliano 
105*3cdfd905SAlfredo Cardigliano 	/* RX */
106*3cdfd905SAlfredo Cardigliano 
107*3cdfd905SAlfredo Cardigliano 	stats->ipackets = ls->rx_ucast_packets +
108*3cdfd905SAlfredo Cardigliano 		ls->rx_mcast_packets +
109*3cdfd905SAlfredo Cardigliano 		ls->rx_bcast_packets;
110*3cdfd905SAlfredo Cardigliano 
111*3cdfd905SAlfredo Cardigliano 	stats->ibytes = ls->rx_ucast_bytes +
112*3cdfd905SAlfredo Cardigliano 		ls->rx_mcast_bytes +
113*3cdfd905SAlfredo Cardigliano 		ls->rx_bcast_bytes;
114*3cdfd905SAlfredo Cardigliano 
115*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
116*3cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
117*3cdfd905SAlfredo Cardigliano 		stats->imissed +=
118*3cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
119*3cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
120*3cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
121*3cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
122*3cdfd905SAlfredo Cardigliano 	}
123*3cdfd905SAlfredo Cardigliano 
124*3cdfd905SAlfredo Cardigliano 	stats->imissed +=
125*3cdfd905SAlfredo Cardigliano 		ls->rx_ucast_drop_packets +
126*3cdfd905SAlfredo Cardigliano 		ls->rx_mcast_drop_packets +
127*3cdfd905SAlfredo Cardigliano 		ls->rx_bcast_drop_packets;
128*3cdfd905SAlfredo Cardigliano 
129*3cdfd905SAlfredo Cardigliano 	stats->imissed +=
130*3cdfd905SAlfredo Cardigliano 		ls->rx_queue_empty +
131*3cdfd905SAlfredo Cardigliano 		ls->rx_dma_error +
132*3cdfd905SAlfredo Cardigliano 		ls->rx_queue_disabled +
133*3cdfd905SAlfredo Cardigliano 		ls->rx_desc_fetch_error +
134*3cdfd905SAlfredo Cardigliano 		ls->rx_desc_data_error;
135*3cdfd905SAlfredo Cardigliano 
136*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_rx_q_counters; i++) {
137*3cdfd905SAlfredo Cardigliano 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
138*3cdfd905SAlfredo Cardigliano 		stats->q_ipackets[i] = rx_stats->packets;
139*3cdfd905SAlfredo Cardigliano 		stats->q_ibytes[i] = rx_stats->bytes;
140*3cdfd905SAlfredo Cardigliano 		stats->q_errors[i] =
141*3cdfd905SAlfredo Cardigliano 			rx_stats->no_cb_arg +
142*3cdfd905SAlfredo Cardigliano 			rx_stats->bad_cq_status +
143*3cdfd905SAlfredo Cardigliano 			rx_stats->no_room +
144*3cdfd905SAlfredo Cardigliano 			rx_stats->bad_len;
145*3cdfd905SAlfredo Cardigliano 	}
146*3cdfd905SAlfredo Cardigliano 
147*3cdfd905SAlfredo Cardigliano 	/* TX */
148*3cdfd905SAlfredo Cardigliano 
149*3cdfd905SAlfredo Cardigliano 	stats->opackets = ls->tx_ucast_packets +
150*3cdfd905SAlfredo Cardigliano 		ls->tx_mcast_packets +
151*3cdfd905SAlfredo Cardigliano 		ls->tx_bcast_packets;
152*3cdfd905SAlfredo Cardigliano 
153*3cdfd905SAlfredo Cardigliano 	stats->obytes = ls->tx_ucast_bytes +
154*3cdfd905SAlfredo Cardigliano 		ls->tx_mcast_bytes +
155*3cdfd905SAlfredo Cardigliano 		ls->tx_bcast_bytes;
156*3cdfd905SAlfredo Cardigliano 
157*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
158*3cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
159*3cdfd905SAlfredo Cardigliano 		stats->oerrors += tx_stats->drop;
160*3cdfd905SAlfredo Cardigliano 	}
161*3cdfd905SAlfredo Cardigliano 
162*3cdfd905SAlfredo Cardigliano 	stats->oerrors +=
163*3cdfd905SAlfredo Cardigliano 		ls->tx_ucast_drop_packets +
164*3cdfd905SAlfredo Cardigliano 		ls->tx_mcast_drop_packets +
165*3cdfd905SAlfredo Cardigliano 		ls->tx_bcast_drop_packets;
166*3cdfd905SAlfredo Cardigliano 
167*3cdfd905SAlfredo Cardigliano 	stats->oerrors +=
168*3cdfd905SAlfredo Cardigliano 		ls->tx_dma_error +
169*3cdfd905SAlfredo Cardigliano 		ls->tx_queue_disabled +
170*3cdfd905SAlfredo Cardigliano 		ls->tx_desc_fetch_error +
171*3cdfd905SAlfredo Cardigliano 		ls->tx_desc_data_error;
172*3cdfd905SAlfredo Cardigliano 
173*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < num_tx_q_counters; i++) {
174*3cdfd905SAlfredo Cardigliano 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
175*3cdfd905SAlfredo Cardigliano 		stats->q_opackets[i] = tx_stats->packets;
176*3cdfd905SAlfredo Cardigliano 		stats->q_obytes[i] = tx_stats->bytes;
177*3cdfd905SAlfredo Cardigliano 	}
178*3cdfd905SAlfredo Cardigliano }
179*3cdfd905SAlfredo Cardigliano 
180*3cdfd905SAlfredo Cardigliano void
181*3cdfd905SAlfredo Cardigliano ionic_lif_get_stats(const struct ionic_lif *lif,
182*3cdfd905SAlfredo Cardigliano 		struct rte_eth_stats *stats)
183*3cdfd905SAlfredo Cardigliano {
184*3cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, stats);
185*3cdfd905SAlfredo Cardigliano 
186*3cdfd905SAlfredo Cardigliano 	stats->ipackets  -= lif->stats_base.ipackets;
187*3cdfd905SAlfredo Cardigliano 	stats->opackets  -= lif->stats_base.opackets;
188*3cdfd905SAlfredo Cardigliano 	stats->ibytes    -= lif->stats_base.ibytes;
189*3cdfd905SAlfredo Cardigliano 	stats->obytes    -= lif->stats_base.obytes;
190*3cdfd905SAlfredo Cardigliano 	stats->imissed   -= lif->stats_base.imissed;
191*3cdfd905SAlfredo Cardigliano 	stats->ierrors   -= lif->stats_base.ierrors;
192*3cdfd905SAlfredo Cardigliano 	stats->oerrors   -= lif->stats_base.oerrors;
193*3cdfd905SAlfredo Cardigliano 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
194*3cdfd905SAlfredo Cardigliano }
195*3cdfd905SAlfredo Cardigliano 
196*3cdfd905SAlfredo Cardigliano void
197*3cdfd905SAlfredo Cardigliano ionic_lif_reset_stats(struct ionic_lif *lif)
198*3cdfd905SAlfredo Cardigliano {
199*3cdfd905SAlfredo Cardigliano 	uint32_t i;
200*3cdfd905SAlfredo Cardigliano 
201*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
202*3cdfd905SAlfredo Cardigliano 		memset(&lif->rxqcqs[i]->stats.rx, 0,
203*3cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_rx_stats));
204*3cdfd905SAlfredo Cardigliano 		memset(&lif->txqcqs[i]->stats.tx, 0,
205*3cdfd905SAlfredo Cardigliano 			sizeof(struct ionic_tx_stats));
206*3cdfd905SAlfredo Cardigliano 	}
207*3cdfd905SAlfredo Cardigliano 
208*3cdfd905SAlfredo Cardigliano 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
209*3cdfd905SAlfredo Cardigliano }
210*3cdfd905SAlfredo Cardigliano 
211*3cdfd905SAlfredo Cardigliano void
212*3cdfd905SAlfredo Cardigliano ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
213*3cdfd905SAlfredo Cardigliano {
214*3cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
215*3cdfd905SAlfredo Cardigliano 	uint64_t *stats64 = (uint64_t *)stats;
216*3cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
217*3cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
218*3cdfd905SAlfredo Cardigliano 
219*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
220*3cdfd905SAlfredo Cardigliano 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
221*3cdfd905SAlfredo Cardigliano }
222*3cdfd905SAlfredo Cardigliano 
223*3cdfd905SAlfredo Cardigliano void
224*3cdfd905SAlfredo Cardigliano ionic_lif_reset_hw_stats(struct ionic_lif *lif)
225*3cdfd905SAlfredo Cardigliano {
226*3cdfd905SAlfredo Cardigliano 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
227*3cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
228*3cdfd905SAlfredo Cardigliano 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
229*3cdfd905SAlfredo Cardigliano 
230*3cdfd905SAlfredo Cardigliano 	for (i = 0; i < count; i++)
231*3cdfd905SAlfredo Cardigliano 		lif_stats64_base[i] = lif_stats64[i];
232*3cdfd905SAlfredo Cardigliano }
233*3cdfd905SAlfredo Cardigliano 
234598f6726SAlfredo Cardigliano static int
23554fe083fSAlfredo Cardigliano ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
236598f6726SAlfredo Cardigliano {
23754fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
23854fe083fSAlfredo Cardigliano 		.pending_work = true,
23954fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
24054fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
24154fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_MAC,
24254fe083fSAlfredo Cardigliano 		},
24354fe083fSAlfredo Cardigliano 	};
24454fe083fSAlfredo Cardigliano 	int err;
24554fe083fSAlfredo Cardigliano 
24654fe083fSAlfredo Cardigliano 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
24754fe083fSAlfredo Cardigliano 
24854fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
24954fe083fSAlfredo Cardigliano 	if (err)
25054fe083fSAlfredo Cardigliano 		return err;
25154fe083fSAlfredo Cardigliano 
25254fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
25354fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
25454fe083fSAlfredo Cardigliano 
25554fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
25654fe083fSAlfredo Cardigliano }
25754fe083fSAlfredo Cardigliano 
25854fe083fSAlfredo Cardigliano static int
25954fe083fSAlfredo Cardigliano ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
26054fe083fSAlfredo Cardigliano {
26154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
26254fe083fSAlfredo Cardigliano 		.pending_work = true,
26354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
26454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
26554fe083fSAlfredo Cardigliano 		},
26654fe083fSAlfredo Cardigliano 	};
26754fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
26854fe083fSAlfredo Cardigliano 	int err;
26954fe083fSAlfredo Cardigliano 
27054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
27154fe083fSAlfredo Cardigliano 
27254fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
27354fe083fSAlfredo Cardigliano 
27454fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_addr(lif, addr);
27554fe083fSAlfredo Cardigliano 	if (!f) {
27654fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
27754fe083fSAlfredo Cardigliano 		return -ENOENT;
27854fe083fSAlfredo Cardigliano 	}
27954fe083fSAlfredo Cardigliano 
28054fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
28154fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
28254fe083fSAlfredo Cardigliano 
28354fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
28454fe083fSAlfredo Cardigliano 
28554fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
28654fe083fSAlfredo Cardigliano 	if (err)
28754fe083fSAlfredo Cardigliano 		return err;
28854fe083fSAlfredo Cardigliano 
28954fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
29054fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
291598f6726SAlfredo Cardigliano 
292598f6726SAlfredo Cardigliano 	return 0;
293598f6726SAlfredo Cardigliano }
294598f6726SAlfredo Cardigliano 
29554fe083fSAlfredo Cardigliano int
29654fe083fSAlfredo Cardigliano ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
29754fe083fSAlfredo Cardigliano 		struct rte_ether_addr *mac_addr,
29854fe083fSAlfredo Cardigliano 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
299598f6726SAlfredo Cardigliano {
30054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
30154fe083fSAlfredo Cardigliano 
30254fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
30354fe083fSAlfredo Cardigliano 
30454fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
30554fe083fSAlfredo Cardigliano }
30654fe083fSAlfredo Cardigliano 
30754fe083fSAlfredo Cardigliano void
30854fe083fSAlfredo Cardigliano ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index __rte_unused)
30954fe083fSAlfredo Cardigliano {
31054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
31154fe083fSAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
31254fe083fSAlfredo Cardigliano 
31354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
31454fe083fSAlfredo Cardigliano 
31554fe083fSAlfredo Cardigliano 	if (index >= adapter->max_mac_addrs) {
31654fe083fSAlfredo Cardigliano 		IONIC_PRINT(WARNING,
31754fe083fSAlfredo Cardigliano 			"Index %u is above MAC filter limit %u",
31854fe083fSAlfredo Cardigliano 			index, adapter->max_mac_addrs);
31954fe083fSAlfredo Cardigliano 		return;
32054fe083fSAlfredo Cardigliano 	}
32154fe083fSAlfredo Cardigliano 
32254fe083fSAlfredo Cardigliano 	if (!rte_is_valid_assigned_ether_addr(&eth_dev->data->mac_addrs[index]))
32354fe083fSAlfredo Cardigliano 		return;
32454fe083fSAlfredo Cardigliano 
32554fe083fSAlfredo Cardigliano 	ionic_lif_addr_del(lif, (const uint8_t *)
32654fe083fSAlfredo Cardigliano 		&eth_dev->data->mac_addrs[index]);
32754fe083fSAlfredo Cardigliano }
32854fe083fSAlfredo Cardigliano 
32954fe083fSAlfredo Cardigliano int
33054fe083fSAlfredo Cardigliano ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
33154fe083fSAlfredo Cardigliano {
33254fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
33354fe083fSAlfredo Cardigliano 
33454fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
33554fe083fSAlfredo Cardigliano 
33654fe083fSAlfredo Cardigliano 	if (mac_addr == NULL) {
33754fe083fSAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "New mac is null");
33854fe083fSAlfredo Cardigliano 		return -1;
33954fe083fSAlfredo Cardigliano 	}
34054fe083fSAlfredo Cardigliano 
34154fe083fSAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
34254fe083fSAlfredo Cardigliano 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
34354fe083fSAlfredo Cardigliano 			lif->mac_addr);
34454fe083fSAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
34554fe083fSAlfredo Cardigliano 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
34654fe083fSAlfredo Cardigliano 	}
34754fe083fSAlfredo Cardigliano 
34854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "Updating mac addr");
34954fe083fSAlfredo Cardigliano 
35054fe083fSAlfredo Cardigliano 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
35154fe083fSAlfredo Cardigliano 
35254fe083fSAlfredo Cardigliano 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
35354fe083fSAlfredo Cardigliano }
35454fe083fSAlfredo Cardigliano 
35554fe083fSAlfredo Cardigliano static int
35654fe083fSAlfredo Cardigliano ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
35754fe083fSAlfredo Cardigliano {
35854fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
35954fe083fSAlfredo Cardigliano 		.pending_work = true,
36054fe083fSAlfredo Cardigliano 		.cmd.rx_filter_add = {
36154fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_ADD,
36254fe083fSAlfredo Cardigliano 			.match = IONIC_RX_FILTER_MATCH_VLAN,
36354fe083fSAlfredo Cardigliano 			.vlan.vlan = vid,
36454fe083fSAlfredo Cardigliano 		},
36554fe083fSAlfredo Cardigliano 	};
36654fe083fSAlfredo Cardigliano 	int err;
36754fe083fSAlfredo Cardigliano 
36854fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
36954fe083fSAlfredo Cardigliano 	if (err)
37054fe083fSAlfredo Cardigliano 		return err;
37154fe083fSAlfredo Cardigliano 
37254fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
37354fe083fSAlfredo Cardigliano 		ctx.comp.rx_filter_add.filter_id);
37454fe083fSAlfredo Cardigliano 
37554fe083fSAlfredo Cardigliano 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
37654fe083fSAlfredo Cardigliano }
37754fe083fSAlfredo Cardigliano 
37854fe083fSAlfredo Cardigliano static int
37954fe083fSAlfredo Cardigliano ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
38054fe083fSAlfredo Cardigliano {
38154fe083fSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
38254fe083fSAlfredo Cardigliano 		.pending_work = true,
38354fe083fSAlfredo Cardigliano 		.cmd.rx_filter_del = {
38454fe083fSAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_FILTER_DEL,
38554fe083fSAlfredo Cardigliano 		},
38654fe083fSAlfredo Cardigliano 	};
38754fe083fSAlfredo Cardigliano 	struct ionic_rx_filter *f;
38854fe083fSAlfredo Cardigliano 	int err;
38954fe083fSAlfredo Cardigliano 
39054fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
39154fe083fSAlfredo Cardigliano 
39254fe083fSAlfredo Cardigliano 	rte_spinlock_lock(&lif->rx_filters.lock);
39354fe083fSAlfredo Cardigliano 
39454fe083fSAlfredo Cardigliano 	f = ionic_rx_filter_by_vlan(lif, vid);
39554fe083fSAlfredo Cardigliano 	if (!f) {
39654fe083fSAlfredo Cardigliano 		rte_spinlock_unlock(&lif->rx_filters.lock);
39754fe083fSAlfredo Cardigliano 		return -ENOENT;
39854fe083fSAlfredo Cardigliano 	}
39954fe083fSAlfredo Cardigliano 
40054fe083fSAlfredo Cardigliano 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
40154fe083fSAlfredo Cardigliano 	ionic_rx_filter_free(f);
40254fe083fSAlfredo Cardigliano 	rte_spinlock_unlock(&lif->rx_filters.lock);
40354fe083fSAlfredo Cardigliano 
40454fe083fSAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
40554fe083fSAlfredo Cardigliano 	if (err)
40654fe083fSAlfredo Cardigliano 		return err;
40754fe083fSAlfredo Cardigliano 
40854fe083fSAlfredo Cardigliano 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
40954fe083fSAlfredo Cardigliano 		ctx.cmd.rx_filter_del.filter_id);
410598f6726SAlfredo Cardigliano 
411598f6726SAlfredo Cardigliano 	return 0;
412598f6726SAlfredo Cardigliano }
413598f6726SAlfredo Cardigliano 
41454fe083fSAlfredo Cardigliano int
41554fe083fSAlfredo Cardigliano ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
41654fe083fSAlfredo Cardigliano 		int on)
41754fe083fSAlfredo Cardigliano {
41854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
41954fe083fSAlfredo Cardigliano 	int err;
42054fe083fSAlfredo Cardigliano 
42154fe083fSAlfredo Cardigliano 	if (on)
42254fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
42354fe083fSAlfredo Cardigliano 	else
42454fe083fSAlfredo Cardigliano 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
42554fe083fSAlfredo Cardigliano 
42654fe083fSAlfredo Cardigliano 	return err;
42754fe083fSAlfredo Cardigliano }
42854fe083fSAlfredo Cardigliano 
429598f6726SAlfredo Cardigliano static void
430598f6726SAlfredo Cardigliano ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
431598f6726SAlfredo Cardigliano {
432598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
433598f6726SAlfredo Cardigliano 		.pending_work = true,
434598f6726SAlfredo Cardigliano 		.cmd.rx_mode_set = {
435598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_RX_MODE_SET,
436598f6726SAlfredo Cardigliano 			.lif_index = lif->index,
437598f6726SAlfredo Cardigliano 			.rx_mode = rx_mode,
438598f6726SAlfredo Cardigliano 		},
439598f6726SAlfredo Cardigliano 	};
440598f6726SAlfredo Cardigliano 	int err;
441598f6726SAlfredo Cardigliano 
442598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
443598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
444598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
445598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
446598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
447598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
448598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
449598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
450598f6726SAlfredo Cardigliano 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
451598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
452598f6726SAlfredo Cardigliano 
453598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
454598f6726SAlfredo Cardigliano 	if (err)
455598f6726SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Failure setting RX mode");
456598f6726SAlfredo Cardigliano }
457598f6726SAlfredo Cardigliano 
458598f6726SAlfredo Cardigliano static void
459598f6726SAlfredo Cardigliano ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
460598f6726SAlfredo Cardigliano {
461598f6726SAlfredo Cardigliano 	if (lif->rx_mode != rx_mode) {
462598f6726SAlfredo Cardigliano 		lif->rx_mode = rx_mode;
463598f6726SAlfredo Cardigliano 		ionic_lif_rx_mode(lif, rx_mode);
464598f6726SAlfredo Cardigliano 	}
465598f6726SAlfredo Cardigliano }
466598f6726SAlfredo Cardigliano 
46754fe083fSAlfredo Cardigliano int
46854fe083fSAlfredo Cardigliano ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
46954fe083fSAlfredo Cardigliano {
47054fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
47154fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
47254fe083fSAlfredo Cardigliano 
47354fe083fSAlfredo Cardigliano 	IONIC_PRINT_CALL();
47454fe083fSAlfredo Cardigliano 
47554fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
47654fe083fSAlfredo Cardigliano 
47754fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
47854fe083fSAlfredo Cardigliano 
47954fe083fSAlfredo Cardigliano 	return 0;
48054fe083fSAlfredo Cardigliano }
48154fe083fSAlfredo Cardigliano 
48254fe083fSAlfredo Cardigliano int
48354fe083fSAlfredo Cardigliano ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
48454fe083fSAlfredo Cardigliano {
48554fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
48654fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
48754fe083fSAlfredo Cardigliano 
48854fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
48954fe083fSAlfredo Cardigliano 
49054fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
49154fe083fSAlfredo Cardigliano 
49254fe083fSAlfredo Cardigliano 	return 0;
49354fe083fSAlfredo Cardigliano }
49454fe083fSAlfredo Cardigliano 
49554fe083fSAlfredo Cardigliano int
49654fe083fSAlfredo Cardigliano ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
49754fe083fSAlfredo Cardigliano {
49854fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
49954fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
50054fe083fSAlfredo Cardigliano 
50154fe083fSAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
50254fe083fSAlfredo Cardigliano 
50354fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
50454fe083fSAlfredo Cardigliano 
50554fe083fSAlfredo Cardigliano 	return 0;
50654fe083fSAlfredo Cardigliano }
50754fe083fSAlfredo Cardigliano 
50854fe083fSAlfredo Cardigliano int
50954fe083fSAlfredo Cardigliano ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
51054fe083fSAlfredo Cardigliano {
51154fe083fSAlfredo Cardigliano 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
51254fe083fSAlfredo Cardigliano 	uint32_t rx_mode = lif->rx_mode;
51354fe083fSAlfredo Cardigliano 
51454fe083fSAlfredo Cardigliano 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
51554fe083fSAlfredo Cardigliano 
51654fe083fSAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
51754fe083fSAlfredo Cardigliano 
51854fe083fSAlfredo Cardigliano 	return 0;
51954fe083fSAlfredo Cardigliano }
520598f6726SAlfredo Cardigliano 
521598f6726SAlfredo Cardigliano int
522598f6726SAlfredo Cardigliano ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
523598f6726SAlfredo Cardigliano {
524598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
525598f6726SAlfredo Cardigliano 		.pending_work = true,
526598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
527598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
528598f6726SAlfredo Cardigliano 			.index = lif->index,
529598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MTU,
530598f6726SAlfredo Cardigliano 			.mtu = new_mtu,
531598f6726SAlfredo Cardigliano 		},
532598f6726SAlfredo Cardigliano 	};
533598f6726SAlfredo Cardigliano 	int err;
534598f6726SAlfredo Cardigliano 
535598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
536598f6726SAlfredo Cardigliano 	if (err)
537598f6726SAlfredo Cardigliano 		return err;
538598f6726SAlfredo Cardigliano 
539598f6726SAlfredo Cardigliano 	lif->mtu = new_mtu;
540598f6726SAlfredo Cardigliano 
541598f6726SAlfredo Cardigliano 	return 0;
542598f6726SAlfredo Cardigliano }
543598f6726SAlfredo Cardigliano 
544598f6726SAlfredo Cardigliano int
54501a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
54601a6c311SAlfredo Cardigliano {
54701a6c311SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
54801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
54901a6c311SAlfredo Cardigliano 	unsigned long index;
55001a6c311SAlfredo Cardigliano 
55101a6c311SAlfredo Cardigliano 	/*
55201a6c311SAlfredo Cardigliano 	 * Note: interrupt handler is called for index = 0 only
55301a6c311SAlfredo Cardigliano 	 * (we use interrupts for the notifyq only anyway,
55401a6c311SAlfredo Cardigliano 	 * which hash index = 0)
55501a6c311SAlfredo Cardigliano 	 */
55601a6c311SAlfredo Cardigliano 
55701a6c311SAlfredo Cardigliano 	for (index = 0; index < adapter->nintrs; index++)
55801a6c311SAlfredo Cardigliano 		if (!adapter->intrs[index])
55901a6c311SAlfredo Cardigliano 			break;
56001a6c311SAlfredo Cardigliano 
56101a6c311SAlfredo Cardigliano 	if (index == adapter->nintrs)
56201a6c311SAlfredo Cardigliano 		return -ENOSPC;
56301a6c311SAlfredo Cardigliano 
56401a6c311SAlfredo Cardigliano 	adapter->intrs[index] = true;
56501a6c311SAlfredo Cardigliano 
56601a6c311SAlfredo Cardigliano 	ionic_intr_init(idev, intr, index);
56701a6c311SAlfredo Cardigliano 
56801a6c311SAlfredo Cardigliano 	return 0;
56901a6c311SAlfredo Cardigliano }
57001a6c311SAlfredo Cardigliano 
57101a6c311SAlfredo Cardigliano void
57201a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
57301a6c311SAlfredo Cardigliano {
57401a6c311SAlfredo Cardigliano 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
57501a6c311SAlfredo Cardigliano 		lif->adapter->intrs[intr->index] = false;
57601a6c311SAlfredo Cardigliano }
57701a6c311SAlfredo Cardigliano 
57801a6c311SAlfredo Cardigliano static int
57901a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
58001a6c311SAlfredo Cardigliano 		uint32_t index,
58101a6c311SAlfredo Cardigliano 		const char *base, uint32_t flags,
58201a6c311SAlfredo Cardigliano 		uint32_t num_descs,
58301a6c311SAlfredo Cardigliano 		uint32_t desc_size,
58401a6c311SAlfredo Cardigliano 		uint32_t cq_desc_size,
58501a6c311SAlfredo Cardigliano 		uint32_t sg_desc_size,
58601a6c311SAlfredo Cardigliano 		uint32_t pid, struct ionic_qcq **qcq)
58701a6c311SAlfredo Cardigliano {
58801a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
58901a6c311SAlfredo Cardigliano 	struct ionic_qcq *new;
59001a6c311SAlfredo Cardigliano 	uint32_t q_size, cq_size, sg_size, total_size;
59101a6c311SAlfredo Cardigliano 	void *q_base, *cq_base, *sg_base;
59201a6c311SAlfredo Cardigliano 	rte_iova_t q_base_pa = 0;
59301a6c311SAlfredo Cardigliano 	rte_iova_t cq_base_pa = 0;
59401a6c311SAlfredo Cardigliano 	rte_iova_t sg_base_pa = 0;
59501a6c311SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
59601a6c311SAlfredo Cardigliano 	int err;
59701a6c311SAlfredo Cardigliano 
59801a6c311SAlfredo Cardigliano 	*qcq = NULL;
59901a6c311SAlfredo Cardigliano 
60001a6c311SAlfredo Cardigliano 	q_size  = num_descs * desc_size;
60101a6c311SAlfredo Cardigliano 	cq_size = num_descs * cq_desc_size;
60201a6c311SAlfredo Cardigliano 	sg_size = num_descs * sg_desc_size;
60301a6c311SAlfredo Cardigliano 
60401a6c311SAlfredo Cardigliano 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
60501a6c311SAlfredo Cardigliano 		RTE_ALIGN(cq_size, PAGE_SIZE);
60601a6c311SAlfredo Cardigliano 	/*
60701a6c311SAlfredo Cardigliano 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
60801a6c311SAlfredo Cardigliano 	 * aligning as q_base could be not aligned to the page.
60901a6c311SAlfredo Cardigliano 	 * Adding PAGE_SIZE.
61001a6c311SAlfredo Cardigliano 	 */
61101a6c311SAlfredo Cardigliano 	total_size += PAGE_SIZE;
61201a6c311SAlfredo Cardigliano 
61301a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
61401a6c311SAlfredo Cardigliano 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
61501a6c311SAlfredo Cardigliano 		total_size += PAGE_SIZE;
61601a6c311SAlfredo Cardigliano 	}
61701a6c311SAlfredo Cardigliano 
61801a6c311SAlfredo Cardigliano 	new = rte_zmalloc("ionic", sizeof(*new), 0);
61901a6c311SAlfredo Cardigliano 	if (!new) {
62001a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
62101a6c311SAlfredo Cardigliano 		return -ENOMEM;
62201a6c311SAlfredo Cardigliano 	}
62301a6c311SAlfredo Cardigliano 
62401a6c311SAlfredo Cardigliano 	new->lif = lif;
62501a6c311SAlfredo Cardigliano 	new->flags = flags;
62601a6c311SAlfredo Cardigliano 
62701a6c311SAlfredo Cardigliano 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
62801a6c311SAlfredo Cardigliano 	if (!new->q.info) {
62901a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate queue info");
63001a6c311SAlfredo Cardigliano 		return -ENOMEM;
63101a6c311SAlfredo Cardigliano 	}
63201a6c311SAlfredo Cardigliano 
63301a6c311SAlfredo Cardigliano 	new->q.type = type;
63401a6c311SAlfredo Cardigliano 
63501a6c311SAlfredo Cardigliano 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
63601a6c311SAlfredo Cardigliano 		desc_size, sg_desc_size, pid);
63701a6c311SAlfredo Cardigliano 	if (err) {
63801a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Queue initialization failed");
63901a6c311SAlfredo Cardigliano 		return err;
64001a6c311SAlfredo Cardigliano 	}
64101a6c311SAlfredo Cardigliano 
64201a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR) {
64301a6c311SAlfredo Cardigliano 		err = ionic_intr_alloc(lif, &new->intr);
64401a6c311SAlfredo Cardigliano 		if (err)
64501a6c311SAlfredo Cardigliano 			return err;
64601a6c311SAlfredo Cardigliano 
64701a6c311SAlfredo Cardigliano 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
64801a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
64901a6c311SAlfredo Cardigliano 	} else {
65001a6c311SAlfredo Cardigliano 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
65101a6c311SAlfredo Cardigliano 	}
65201a6c311SAlfredo Cardigliano 
65301a6c311SAlfredo Cardigliano 	err = ionic_cq_init(lif, &new->cq, &new->intr,
65401a6c311SAlfredo Cardigliano 		num_descs, cq_desc_size);
65501a6c311SAlfredo Cardigliano 	if (err) {
65601a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Completion queue initialization failed");
65701a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
65801a6c311SAlfredo Cardigliano 	}
65901a6c311SAlfredo Cardigliano 
66001a6c311SAlfredo Cardigliano 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
66101a6c311SAlfredo Cardigliano 		base /* name */, index /* queue_idx */,
66201a6c311SAlfredo Cardigliano 		total_size, IONIC_ALIGN, socket_id);
66301a6c311SAlfredo Cardigliano 
66401a6c311SAlfredo Cardigliano 	if (!new->base_z) {
66501a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
66601a6c311SAlfredo Cardigliano 		err = -ENOMEM;
66701a6c311SAlfredo Cardigliano 		goto err_out_free_intr;
66801a6c311SAlfredo Cardigliano 	}
66901a6c311SAlfredo Cardigliano 
67001a6c311SAlfredo Cardigliano 	new->base = new->base_z->addr;
67101a6c311SAlfredo Cardigliano 	new->base_pa = new->base_z->iova;
67201a6c311SAlfredo Cardigliano 	new->total_size = total_size;
67301a6c311SAlfredo Cardigliano 
67401a6c311SAlfredo Cardigliano 	q_base = new->base;
67501a6c311SAlfredo Cardigliano 	q_base_pa = new->base_pa;
67601a6c311SAlfredo Cardigliano 
67701a6c311SAlfredo Cardigliano 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
67801a6c311SAlfredo Cardigliano 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
67901a6c311SAlfredo Cardigliano 
68001a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_SG) {
68101a6c311SAlfredo Cardigliano 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
68201a6c311SAlfredo Cardigliano 			PAGE_SIZE);
68301a6c311SAlfredo Cardigliano 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
68401a6c311SAlfredo Cardigliano 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
68501a6c311SAlfredo Cardigliano 	}
68601a6c311SAlfredo Cardigliano 
68701a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Q-Base-PA = %ju CQ-Base-PA = %ju "
68801a6c311SAlfredo Cardigliano 		"SG-base-PA = %ju",
68901a6c311SAlfredo Cardigliano 		q_base_pa, cq_base_pa, sg_base_pa);
69001a6c311SAlfredo Cardigliano 
69101a6c311SAlfredo Cardigliano 	ionic_q_map(&new->q, q_base, q_base_pa);
69201a6c311SAlfredo Cardigliano 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
69301a6c311SAlfredo Cardigliano 	ionic_cq_bind(&new->cq, &new->q);
69401a6c311SAlfredo Cardigliano 
69501a6c311SAlfredo Cardigliano 	*qcq = new;
69601a6c311SAlfredo Cardigliano 
69701a6c311SAlfredo Cardigliano 	return 0;
69801a6c311SAlfredo Cardigliano 
69901a6c311SAlfredo Cardigliano err_out_free_intr:
70001a6c311SAlfredo Cardigliano 	if (flags & IONIC_QCQ_F_INTR)
70101a6c311SAlfredo Cardigliano 		ionic_intr_free(lif, &new->intr);
70201a6c311SAlfredo Cardigliano 
70301a6c311SAlfredo Cardigliano 	return err;
70401a6c311SAlfredo Cardigliano }
70501a6c311SAlfredo Cardigliano 
70601a6c311SAlfredo Cardigliano void
70701a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq)
70801a6c311SAlfredo Cardigliano {
70901a6c311SAlfredo Cardigliano 	if (qcq->base_z) {
71001a6c311SAlfredo Cardigliano 		qcq->base = NULL;
71101a6c311SAlfredo Cardigliano 		qcq->base_pa = 0;
71201a6c311SAlfredo Cardigliano 		rte_memzone_free(qcq->base_z);
71301a6c311SAlfredo Cardigliano 		qcq->base_z = NULL;
71401a6c311SAlfredo Cardigliano 	}
71501a6c311SAlfredo Cardigliano 
71601a6c311SAlfredo Cardigliano 	if (qcq->q.info) {
71701a6c311SAlfredo Cardigliano 		rte_free(qcq->q.info);
71801a6c311SAlfredo Cardigliano 		qcq->q.info = NULL;
71901a6c311SAlfredo Cardigliano 	}
72001a6c311SAlfredo Cardigliano 
72101a6c311SAlfredo Cardigliano 	rte_free(qcq);
72201a6c311SAlfredo Cardigliano }
72301a6c311SAlfredo Cardigliano 
724a27d9013SAlfredo Cardigliano int
725a27d9013SAlfredo Cardigliano ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
726a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
727a27d9013SAlfredo Cardigliano {
728a27d9013SAlfredo Cardigliano 	uint32_t flags;
729a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
730a27d9013SAlfredo Cardigliano 
731a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
732a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags,
733a27d9013SAlfredo Cardigliano 		nrxq_descs,
734a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_desc),
735a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_comp),
736a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_rxq_sg_desc),
737a27d9013SAlfredo Cardigliano 		lif->kern_pid, &lif->rxqcqs[index]);
738a27d9013SAlfredo Cardigliano 	if (err)
739a27d9013SAlfredo Cardigliano 		return err;
740a27d9013SAlfredo Cardigliano 
741a27d9013SAlfredo Cardigliano 	*qcq = lif->rxqcqs[index];
742a27d9013SAlfredo Cardigliano 
743a27d9013SAlfredo Cardigliano 	return 0;
744a27d9013SAlfredo Cardigliano }
745a27d9013SAlfredo Cardigliano 
746a27d9013SAlfredo Cardigliano int
747a27d9013SAlfredo Cardigliano ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
748a27d9013SAlfredo Cardigliano 		struct ionic_qcq **qcq)
749a27d9013SAlfredo Cardigliano {
750a27d9013SAlfredo Cardigliano 	uint32_t flags;
751a27d9013SAlfredo Cardigliano 	int err = -ENOMEM;
752a27d9013SAlfredo Cardigliano 
753a27d9013SAlfredo Cardigliano 	flags = IONIC_QCQ_F_SG;
754a27d9013SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
755a27d9013SAlfredo Cardigliano 		ntxq_descs,
756a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_desc),
757a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_comp),
758a27d9013SAlfredo Cardigliano 		sizeof(struct ionic_txq_sg_desc),
759a27d9013SAlfredo Cardigliano 		lif->kern_pid, &lif->txqcqs[index]);
760a27d9013SAlfredo Cardigliano 	if (err)
761a27d9013SAlfredo Cardigliano 		return err;
762a27d9013SAlfredo Cardigliano 
763a27d9013SAlfredo Cardigliano 	*qcq = lif->txqcqs[index];
764a27d9013SAlfredo Cardigliano 
765a27d9013SAlfredo Cardigliano 	return 0;
766a27d9013SAlfredo Cardigliano }
767a27d9013SAlfredo Cardigliano 
76801a6c311SAlfredo Cardigliano static int
76901a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif)
77001a6c311SAlfredo Cardigliano {
77101a6c311SAlfredo Cardigliano 	uint32_t flags;
77201a6c311SAlfredo Cardigliano 	int err = -ENOMEM;
77301a6c311SAlfredo Cardigliano 
77401a6c311SAlfredo Cardigliano 	flags = 0;
77501a6c311SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
77601a6c311SAlfredo Cardigliano 		IONIC_ADMINQ_LENGTH,
77701a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_cmd),
77801a6c311SAlfredo Cardigliano 		sizeof(struct ionic_admin_comp),
77901a6c311SAlfredo Cardigliano 		0,
78001a6c311SAlfredo Cardigliano 		lif->kern_pid, &lif->adminqcq);
78127b942c8SAlfredo Cardigliano 	if (err)
78227b942c8SAlfredo Cardigliano 		return err;
78301a6c311SAlfredo Cardigliano 
78427b942c8SAlfredo Cardigliano 	return 0;
78527b942c8SAlfredo Cardigliano }
78627b942c8SAlfredo Cardigliano 
78727b942c8SAlfredo Cardigliano static int
78827b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif)
78927b942c8SAlfredo Cardigliano {
79027b942c8SAlfredo Cardigliano 	uint32_t flags;
79127b942c8SAlfredo Cardigliano 	int err = -ENOMEM;
79227b942c8SAlfredo Cardigliano 
79327b942c8SAlfredo Cardigliano 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
79427b942c8SAlfredo Cardigliano 
79527b942c8SAlfredo Cardigliano 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
79627b942c8SAlfredo Cardigliano 		flags,
79727b942c8SAlfredo Cardigliano 		IONIC_NOTIFYQ_LENGTH,
79827b942c8SAlfredo Cardigliano 		sizeof(struct ionic_notifyq_cmd),
79927b942c8SAlfredo Cardigliano 		sizeof(union ionic_notifyq_comp),
80027b942c8SAlfredo Cardigliano 		0,
80127b942c8SAlfredo Cardigliano 		lif->kern_pid, &lif->notifyqcq);
80201a6c311SAlfredo Cardigliano 	if (err)
80301a6c311SAlfredo Cardigliano 		return err;
80401a6c311SAlfredo Cardigliano 
80501a6c311SAlfredo Cardigliano 	return 0;
80601a6c311SAlfredo Cardigliano }
80701a6c311SAlfredo Cardigliano 
808c67719e1SAlfredo Cardigliano static void *
809c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
810c67719e1SAlfredo Cardigliano {
811c67719e1SAlfredo Cardigliano 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
812c67719e1SAlfredo Cardigliano 
813c67719e1SAlfredo Cardigliano 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
814c67719e1SAlfredo Cardigliano 		return NULL;
815c67719e1SAlfredo Cardigliano 
816c67719e1SAlfredo Cardigliano 	return (void *)&vaddr[page_num << PAGE_SHIFT];
817c67719e1SAlfredo Cardigliano }
818c67719e1SAlfredo Cardigliano 
819669c8de6SAlfredo Cardigliano int
820669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif)
821669c8de6SAlfredo Cardigliano {
822c67719e1SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
823669c8de6SAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
824c67719e1SAlfredo Cardigliano 	int dbpage_num;
82501a6c311SAlfredo Cardigliano 	int err;
826669c8de6SAlfredo Cardigliano 
827669c8de6SAlfredo Cardigliano 	snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index);
828669c8de6SAlfredo Cardigliano 
829669c8de6SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
830669c8de6SAlfredo Cardigliano 
83101a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_lock);
83201a6c311SAlfredo Cardigliano 	rte_spinlock_init(&lif->adminq_service_lock);
83301a6c311SAlfredo Cardigliano 
834c67719e1SAlfredo Cardigliano 	lif->kern_pid = 0;
835c67719e1SAlfredo Cardigliano 
836c67719e1SAlfredo Cardigliano 	dbpage_num = ionic_db_page_num(lif, 0);
837c67719e1SAlfredo Cardigliano 
838c67719e1SAlfredo Cardigliano 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
839c67719e1SAlfredo Cardigliano 	if (!lif->kern_dbpage) {
840c67719e1SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
841c67719e1SAlfredo Cardigliano 		return -ENOMEM;
842c67719e1SAlfredo Cardigliano 	}
843c67719e1SAlfredo Cardigliano 
844a27d9013SAlfredo Cardigliano 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
845a27d9013SAlfredo Cardigliano 		adapter->max_ntxqs_per_lif, 0);
846a27d9013SAlfredo Cardigliano 
847a27d9013SAlfredo Cardigliano 	if (!lif->txqcqs) {
848a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
849a27d9013SAlfredo Cardigliano 		return -ENOMEM;
850a27d9013SAlfredo Cardigliano 	}
851a27d9013SAlfredo Cardigliano 
852a27d9013SAlfredo Cardigliano 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
853a27d9013SAlfredo Cardigliano 		adapter->max_nrxqs_per_lif, 0);
854a27d9013SAlfredo Cardigliano 
855a27d9013SAlfredo Cardigliano 	if (!lif->rxqcqs) {
856a27d9013SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
857a27d9013SAlfredo Cardigliano 		return -ENOMEM;
858a27d9013SAlfredo Cardigliano 	}
859a27d9013SAlfredo Cardigliano 
86027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
86127b942c8SAlfredo Cardigliano 
86227b942c8SAlfredo Cardigliano 	err = ionic_notify_qcq_alloc(lif);
86327b942c8SAlfredo Cardigliano 	if (err) {
86427b942c8SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
86527b942c8SAlfredo Cardigliano 		return err;
86627b942c8SAlfredo Cardigliano 	}
86727b942c8SAlfredo Cardigliano 
86827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
86927b942c8SAlfredo Cardigliano 
87001a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
87101a6c311SAlfredo Cardigliano 
87201a6c311SAlfredo Cardigliano 	err = ionic_admin_qcq_alloc(lif);
87301a6c311SAlfredo Cardigliano 	if (err) {
87401a6c311SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
87501a6c311SAlfredo Cardigliano 		return err;
87601a6c311SAlfredo Cardigliano 	}
87701a6c311SAlfredo Cardigliano 
87801a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
87901a6c311SAlfredo Cardigliano 
880669c8de6SAlfredo Cardigliano 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
881669c8de6SAlfredo Cardigliano 
882669c8de6SAlfredo Cardigliano 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
883669c8de6SAlfredo Cardigliano 		"lif_info", 0 /* queue_idx*/,
884669c8de6SAlfredo Cardigliano 		lif->info_sz, IONIC_ALIGN, socket_id);
885669c8de6SAlfredo Cardigliano 	if (!lif->info_z) {
886669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
887669c8de6SAlfredo Cardigliano 		return -ENOMEM;
888669c8de6SAlfredo Cardigliano 	}
889669c8de6SAlfredo Cardigliano 
890669c8de6SAlfredo Cardigliano 	lif->info = lif->info_z->addr;
891669c8de6SAlfredo Cardigliano 	lif->info_pa = lif->info_z->iova;
892669c8de6SAlfredo Cardigliano 
893669c8de6SAlfredo Cardigliano 	return 0;
894669c8de6SAlfredo Cardigliano }
895669c8de6SAlfredo Cardigliano 
896669c8de6SAlfredo Cardigliano void
897669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif)
898669c8de6SAlfredo Cardigliano {
89927b942c8SAlfredo Cardigliano 	if (lif->notifyqcq) {
90027b942c8SAlfredo Cardigliano 		ionic_qcq_free(lif->notifyqcq);
90127b942c8SAlfredo Cardigliano 		lif->notifyqcq = NULL;
90227b942c8SAlfredo Cardigliano 	}
90327b942c8SAlfredo Cardigliano 
90401a6c311SAlfredo Cardigliano 	if (lif->adminqcq) {
90501a6c311SAlfredo Cardigliano 		ionic_qcq_free(lif->adminqcq);
90601a6c311SAlfredo Cardigliano 		lif->adminqcq = NULL;
90701a6c311SAlfredo Cardigliano 	}
90801a6c311SAlfredo Cardigliano 
909a27d9013SAlfredo Cardigliano 	if (lif->txqcqs) {
910a27d9013SAlfredo Cardigliano 		rte_free(lif->txqcqs);
911a27d9013SAlfredo Cardigliano 		lif->txqcqs = NULL;
912a27d9013SAlfredo Cardigliano 	}
913a27d9013SAlfredo Cardigliano 
914a27d9013SAlfredo Cardigliano 	if (lif->rxqcqs) {
915a27d9013SAlfredo Cardigliano 		rte_free(lif->rxqcqs);
916a27d9013SAlfredo Cardigliano 		lif->rxqcqs = NULL;
917a27d9013SAlfredo Cardigliano 	}
918a27d9013SAlfredo Cardigliano 
919669c8de6SAlfredo Cardigliano 	if (lif->info) {
920669c8de6SAlfredo Cardigliano 		rte_memzone_free(lif->info_z);
921669c8de6SAlfredo Cardigliano 		lif->info = NULL;
922669c8de6SAlfredo Cardigliano 	}
923669c8de6SAlfredo Cardigliano }
924669c8de6SAlfredo Cardigliano 
92522e7171bSAlfredo Cardigliano int
92622e7171bSAlfredo Cardigliano ionic_lif_rss_config(struct ionic_lif *lif,
92722e7171bSAlfredo Cardigliano 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
92822e7171bSAlfredo Cardigliano {
92922e7171bSAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
93022e7171bSAlfredo Cardigliano 		.pending_work = true,
93122e7171bSAlfredo Cardigliano 		.cmd.lif_setattr = {
93222e7171bSAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
93322e7171bSAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_RSS,
93422e7171bSAlfredo Cardigliano 			.rss.types = types,
93522e7171bSAlfredo Cardigliano 			.rss.addr = lif->rss_ind_tbl_pa,
93622e7171bSAlfredo Cardigliano 		},
93722e7171bSAlfredo Cardigliano 	};
93822e7171bSAlfredo Cardigliano 	unsigned int i;
93922e7171bSAlfredo Cardigliano 
94022e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
94122e7171bSAlfredo Cardigliano 
94222e7171bSAlfredo Cardigliano 	lif->rss_types = types;
94322e7171bSAlfredo Cardigliano 
94422e7171bSAlfredo Cardigliano 	if (key)
94522e7171bSAlfredo Cardigliano 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
94622e7171bSAlfredo Cardigliano 
94722e7171bSAlfredo Cardigliano 	if (indir)
94822e7171bSAlfredo Cardigliano 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
94922e7171bSAlfredo Cardigliano 			lif->rss_ind_tbl[i] = indir[i];
95022e7171bSAlfredo Cardigliano 
95122e7171bSAlfredo Cardigliano 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
95222e7171bSAlfredo Cardigliano 	       IONIC_RSS_HASH_KEY_SIZE);
95322e7171bSAlfredo Cardigliano 
95422e7171bSAlfredo Cardigliano 	return ionic_adminq_post_wait(lif, &ctx);
95522e7171bSAlfredo Cardigliano }
95622e7171bSAlfredo Cardigliano 
95722e7171bSAlfredo Cardigliano static int
95822e7171bSAlfredo Cardigliano ionic_lif_rss_setup(struct ionic_lif *lif)
95922e7171bSAlfredo Cardigliano {
96022e7171bSAlfredo Cardigliano 	size_t tbl_size = sizeof(*lif->rss_ind_tbl) *
96122e7171bSAlfredo Cardigliano 		lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
96222e7171bSAlfredo Cardigliano 	static const uint8_t toeplitz_symmetric_key[] = {
96322e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96422e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96522e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96622e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96722e7171bSAlfredo Cardigliano 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
96822e7171bSAlfredo Cardigliano 	};
96922e7171bSAlfredo Cardigliano 	uint32_t socket_id = rte_socket_id();
97022e7171bSAlfredo Cardigliano 	uint32_t i;
97122e7171bSAlfredo Cardigliano 	int err;
97222e7171bSAlfredo Cardigliano 
97322e7171bSAlfredo Cardigliano 	IONIC_PRINT_CALL();
97422e7171bSAlfredo Cardigliano 
97522e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
97622e7171bSAlfredo Cardigliano 		"rss_ind_tbl",
97722e7171bSAlfredo Cardigliano 		0 /* queue_idx*/, tbl_size, IONIC_ALIGN, socket_id);
97822e7171bSAlfredo Cardigliano 
97922e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl_z) {
98022e7171bSAlfredo Cardigliano 		IONIC_PRINT(ERR, "OOM");
98122e7171bSAlfredo Cardigliano 		return -ENOMEM;
98222e7171bSAlfredo Cardigliano 	}
98322e7171bSAlfredo Cardigliano 
98422e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
98522e7171bSAlfredo Cardigliano 	lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
98622e7171bSAlfredo Cardigliano 
98722e7171bSAlfredo Cardigliano 	/* Fill indirection table with 'default' values */
98822e7171bSAlfredo Cardigliano 	for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
98922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
99022e7171bSAlfredo Cardigliano 
99122e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
99222e7171bSAlfredo Cardigliano 		toeplitz_symmetric_key, NULL);
99322e7171bSAlfredo Cardigliano 	if (err)
99422e7171bSAlfredo Cardigliano 		return err;
99522e7171bSAlfredo Cardigliano 
99622e7171bSAlfredo Cardigliano 	return 0;
99722e7171bSAlfredo Cardigliano }
99822e7171bSAlfredo Cardigliano 
99922e7171bSAlfredo Cardigliano static void
100022e7171bSAlfredo Cardigliano ionic_lif_rss_teardown(struct ionic_lif *lif)
100122e7171bSAlfredo Cardigliano {
100222e7171bSAlfredo Cardigliano 	if (!lif->rss_ind_tbl)
100322e7171bSAlfredo Cardigliano 		return;
100422e7171bSAlfredo Cardigliano 
100522e7171bSAlfredo Cardigliano 	if (lif->rss_ind_tbl_z) {
100622e7171bSAlfredo Cardigliano 		/* Disable RSS on the NIC */
100722e7171bSAlfredo Cardigliano 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
100822e7171bSAlfredo Cardigliano 
100922e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl = NULL;
101022e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_pa = 0;
101122e7171bSAlfredo Cardigliano 		rte_memzone_free(lif->rss_ind_tbl_z);
101222e7171bSAlfredo Cardigliano 		lif->rss_ind_tbl_z = NULL;
101322e7171bSAlfredo Cardigliano 	}
101422e7171bSAlfredo Cardigliano }
101522e7171bSAlfredo Cardigliano 
101601a6c311SAlfredo Cardigliano static void
101701a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
101801a6c311SAlfredo Cardigliano {
101901a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
102001a6c311SAlfredo Cardigliano 
102101a6c311SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
102201a6c311SAlfredo Cardigliano 		return;
102301a6c311SAlfredo Cardigliano 
102401a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
102501a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
102601a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_SET);
102701a6c311SAlfredo Cardigliano 
102801a6c311SAlfredo Cardigliano 	qcq->flags &= ~IONIC_QCQ_F_INITED;
102901a6c311SAlfredo Cardigliano }
103001a6c311SAlfredo Cardigliano 
1031a27d9013SAlfredo Cardigliano void
1032a27d9013SAlfredo Cardigliano ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1033a27d9013SAlfredo Cardigliano {
1034a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1035a27d9013SAlfredo Cardigliano }
1036a27d9013SAlfredo Cardigliano 
1037a27d9013SAlfredo Cardigliano void
1038a27d9013SAlfredo Cardigliano ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1039a27d9013SAlfredo Cardigliano {
1040a27d9013SAlfredo Cardigliano 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1041a27d9013SAlfredo Cardigliano }
1042a27d9013SAlfredo Cardigliano 
104301a6c311SAlfredo Cardigliano bool
104401a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
104501a6c311SAlfredo Cardigliano 		void *cb_arg __rte_unused)
104601a6c311SAlfredo Cardigliano {
104701a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc_base = cq->base;
104801a6c311SAlfredo Cardigliano 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
104901a6c311SAlfredo Cardigliano 
105001a6c311SAlfredo Cardigliano 	if (!color_match(cq_desc->color, cq->done_color))
105101a6c311SAlfredo Cardigliano 		return false;
105201a6c311SAlfredo Cardigliano 
105301a6c311SAlfredo Cardigliano 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
105401a6c311SAlfredo Cardigliano 
105501a6c311SAlfredo Cardigliano 	return true;
105601a6c311SAlfredo Cardigliano }
105701a6c311SAlfredo Cardigliano 
105801a6c311SAlfredo Cardigliano /* This acts like ionic_napi */
105901a6c311SAlfredo Cardigliano int
106001a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
106101a6c311SAlfredo Cardigliano 		void *cb_arg)
106201a6c311SAlfredo Cardigliano {
106301a6c311SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
106401a6c311SAlfredo Cardigliano 	uint32_t work_done;
106501a6c311SAlfredo Cardigliano 
106601a6c311SAlfredo Cardigliano 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
106701a6c311SAlfredo Cardigliano 
106801a6c311SAlfredo Cardigliano 	return work_done;
106901a6c311SAlfredo Cardigliano }
107001a6c311SAlfredo Cardigliano 
107127b942c8SAlfredo Cardigliano static void
107227b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif)
107327b942c8SAlfredo Cardigliano {
107427b942c8SAlfredo Cardigliano 	struct ionic_adapter *adapter = lif->adapter;
107527b942c8SAlfredo Cardigliano 	bool link_up;
107627b942c8SAlfredo Cardigliano 
107727b942c8SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
107827b942c8SAlfredo Cardigliano 
107927b942c8SAlfredo Cardigliano 	if (!lif->info)
108027b942c8SAlfredo Cardigliano 		return;
108127b942c8SAlfredo Cardigliano 
108227b942c8SAlfredo Cardigliano 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
108327b942c8SAlfredo Cardigliano 
108427b942c8SAlfredo Cardigliano 	if ((link_up  && adapter->link_up) ||
108527b942c8SAlfredo Cardigliano 	    (!link_up && !adapter->link_up))
108627b942c8SAlfredo Cardigliano 		return;
108727b942c8SAlfredo Cardigliano 
108827b942c8SAlfredo Cardigliano 	if (link_up) {
108927b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
109027b942c8SAlfredo Cardigliano 			lif->info->status.link_speed);
109127b942c8SAlfredo Cardigliano 		adapter->link_speed = lif->info->status.link_speed;
109227b942c8SAlfredo Cardigliano 	} else {
109327b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Link down");
109427b942c8SAlfredo Cardigliano 	}
109527b942c8SAlfredo Cardigliano 
109627b942c8SAlfredo Cardigliano 	adapter->link_up = link_up;
109727b942c8SAlfredo Cardigliano }
109827b942c8SAlfredo Cardigliano 
109927b942c8SAlfredo Cardigliano static bool
110027b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
110127b942c8SAlfredo Cardigliano {
110227b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc_base = cq->base;
110327b942c8SAlfredo Cardigliano 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
110427b942c8SAlfredo Cardigliano 	struct ionic_lif *lif = cb_arg;
110527b942c8SAlfredo Cardigliano 
110627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
110727b942c8SAlfredo Cardigliano 		cq_desc->event.eid, cq_desc->event.ecode);
110827b942c8SAlfredo Cardigliano 
110927b942c8SAlfredo Cardigliano 	/* Have we run out of new completions to process? */
111027b942c8SAlfredo Cardigliano 	if (!(cq_desc->event.eid > lif->last_eid))
111127b942c8SAlfredo Cardigliano 		return false;
111227b942c8SAlfredo Cardigliano 
111327b942c8SAlfredo Cardigliano 	lif->last_eid = cq_desc->event.eid;
111427b942c8SAlfredo Cardigliano 
111527b942c8SAlfredo Cardigliano 	switch (cq_desc->event.ecode) {
111627b942c8SAlfredo Cardigliano 	case IONIC_EVENT_LINK_CHANGE:
111727b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG,
111827b942c8SAlfredo Cardigliano 			"Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
111927b942c8SAlfredo Cardigliano 			cq_desc->event.eid,
112027b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_status,
112127b942c8SAlfredo Cardigliano 			cq_desc->link_change.link_speed);
112227b942c8SAlfredo Cardigliano 
112327b942c8SAlfredo Cardigliano 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
112427b942c8SAlfredo Cardigliano 
112527b942c8SAlfredo Cardigliano 		break;
112627b942c8SAlfredo Cardigliano 	default:
112727b942c8SAlfredo Cardigliano 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
112827b942c8SAlfredo Cardigliano 			cq_desc->event.ecode, cq_desc->event.eid);
112927b942c8SAlfredo Cardigliano 		break;
113027b942c8SAlfredo Cardigliano 	}
113127b942c8SAlfredo Cardigliano 
113227b942c8SAlfredo Cardigliano 	return true;
113327b942c8SAlfredo Cardigliano }
113427b942c8SAlfredo Cardigliano 
113527b942c8SAlfredo Cardigliano int
113627b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget)
113727b942c8SAlfredo Cardigliano {
113827b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
113927b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
114027b942c8SAlfredo Cardigliano 	uint32_t work_done;
114127b942c8SAlfredo Cardigliano 
114227b942c8SAlfredo Cardigliano 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
114327b942c8SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
114427b942c8SAlfredo Cardigliano 		return -1;
114527b942c8SAlfredo Cardigliano 	}
114627b942c8SAlfredo Cardigliano 
114727b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
114827b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_SET);
114927b942c8SAlfredo Cardigliano 
115027b942c8SAlfredo Cardigliano 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
115127b942c8SAlfredo Cardigliano 
115227b942c8SAlfredo Cardigliano 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
115327b942c8SAlfredo Cardigliano 		ionic_link_status_check(lif);
115427b942c8SAlfredo Cardigliano 
115527b942c8SAlfredo Cardigliano 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
115627b942c8SAlfredo Cardigliano 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
115727b942c8SAlfredo Cardigliano 
115827b942c8SAlfredo Cardigliano 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
115927b942c8SAlfredo Cardigliano 		IONIC_INTR_MASK_CLEAR);
116027b942c8SAlfredo Cardigliano 
116127b942c8SAlfredo Cardigliano 	return 0;
116227b942c8SAlfredo Cardigliano }
116327b942c8SAlfredo Cardigliano 
116401a6c311SAlfredo Cardigliano static int
116501a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif)
116601a6c311SAlfredo Cardigliano {
116701a6c311SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
116801a6c311SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->adminqcq;
116901a6c311SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
117001a6c311SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
117101a6c311SAlfredo Cardigliano 	int err;
117201a6c311SAlfredo Cardigliano 
117301a6c311SAlfredo Cardigliano 	ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);
117401a6c311SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
117501a6c311SAlfredo Cardigliano 	if (err)
117601a6c311SAlfredo Cardigliano 		return err;
117701a6c311SAlfredo Cardigliano 
117801a6c311SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
117901a6c311SAlfredo Cardigliano 
118001a6c311SAlfredo Cardigliano 	q->hw_type = comp.hw_type;
118101a6c311SAlfredo Cardigliano 	q->hw_index = comp.hw_index;
118201a6c311SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
118301a6c311SAlfredo Cardigliano 
118401a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
118501a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
118601a6c311SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
118701a6c311SAlfredo Cardigliano 
118801a6c311SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
118901a6c311SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
119001a6c311SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
119101a6c311SAlfredo Cardigliano 
119201a6c311SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
119301a6c311SAlfredo Cardigliano 
119401a6c311SAlfredo Cardigliano 	return 0;
119501a6c311SAlfredo Cardigliano }
119601a6c311SAlfredo Cardigliano 
119727b942c8SAlfredo Cardigliano static int
119827b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif)
119927b942c8SAlfredo Cardigliano {
120027b942c8SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
120127b942c8SAlfredo Cardigliano 	struct ionic_qcq *qcq = lif->notifyqcq;
120227b942c8SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
120327b942c8SAlfredo Cardigliano 	int err;
120427b942c8SAlfredo Cardigliano 
120527b942c8SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
120627b942c8SAlfredo Cardigliano 		.pending_work = true,
120727b942c8SAlfredo Cardigliano 		.cmd.q_init = {
120827b942c8SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
120927b942c8SAlfredo Cardigliano 			.lif_index = lif->index,
121027b942c8SAlfredo Cardigliano 			.type = q->type,
121127b942c8SAlfredo Cardigliano 			.index = q->index,
121227b942c8SAlfredo Cardigliano 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
121327b942c8SAlfredo Cardigliano 			.intr_index = qcq->intr.index,
121427b942c8SAlfredo Cardigliano 			.pid = q->pid,
121527b942c8SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
121627b942c8SAlfredo Cardigliano 			.ring_base = q->base_pa,
121727b942c8SAlfredo Cardigliano 		}
121827b942c8SAlfredo Cardigliano 	};
121927b942c8SAlfredo Cardigliano 
122027b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.pid %d", ctx.cmd.q_init.pid);
122127b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
122227b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.index);
122327b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
122427b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
122527b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
122627b942c8SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
122727b942c8SAlfredo Cardigliano 
122827b942c8SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
122927b942c8SAlfredo Cardigliano 	if (err)
123027b942c8SAlfredo Cardigliano 		return err;
123127b942c8SAlfredo Cardigliano 
123227b942c8SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
123327b942c8SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
123427b942c8SAlfredo Cardigliano 	q->db = NULL;
123527b942c8SAlfredo Cardigliano 
123627b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
123727b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
123827b942c8SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
123927b942c8SAlfredo Cardigliano 
124027b942c8SAlfredo Cardigliano 	if (qcq->flags & IONIC_QCQ_F_INTR)
124127b942c8SAlfredo Cardigliano 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
124227b942c8SAlfredo Cardigliano 			IONIC_INTR_MASK_CLEAR);
124327b942c8SAlfredo Cardigliano 
124427b942c8SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
124527b942c8SAlfredo Cardigliano 
124627b942c8SAlfredo Cardigliano 	return 0;
124727b942c8SAlfredo Cardigliano }
124827b942c8SAlfredo Cardigliano 
1249669c8de6SAlfredo Cardigliano int
1250598f6726SAlfredo Cardigliano ionic_lif_set_features(struct ionic_lif *lif)
1251598f6726SAlfredo Cardigliano {
1252598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1253598f6726SAlfredo Cardigliano 		.pending_work = true,
1254598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1255598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1256598f6726SAlfredo Cardigliano 			.index = lif->index,
1257598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_FEATURES,
1258598f6726SAlfredo Cardigliano 			.features = lif->features,
1259598f6726SAlfredo Cardigliano 		},
1260598f6726SAlfredo Cardigliano 	};
1261598f6726SAlfredo Cardigliano 	int err;
1262598f6726SAlfredo Cardigliano 
1263598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1264598f6726SAlfredo Cardigliano 	if (err)
1265598f6726SAlfredo Cardigliano 		return err;
1266598f6726SAlfredo Cardigliano 
1267598f6726SAlfredo Cardigliano 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1268598f6726SAlfredo Cardigliano 		ctx.comp.lif_setattr.features);
1269598f6726SAlfredo Cardigliano 
1270598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1271598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1272598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1273598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1274598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1275598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1276598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1277598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1278598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1279598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1280598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1281598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1282598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1283598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1284598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1285598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1286598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1287598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1288598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1289598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1290598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1291598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1292598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1293598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1294598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1295598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1296598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1297598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1298598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1299598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1300598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1301598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1302598f6726SAlfredo Cardigliano 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1303598f6726SAlfredo Cardigliano 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1304598f6726SAlfredo Cardigliano 
1305598f6726SAlfredo Cardigliano 	return 0;
1306598f6726SAlfredo Cardigliano }
1307598f6726SAlfredo Cardigliano 
1308a27d9013SAlfredo Cardigliano int
1309a27d9013SAlfredo Cardigliano ionic_lif_txq_init(struct ionic_qcq *qcq)
1310a27d9013SAlfredo Cardigliano {
1311a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1312a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1313a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1314a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1315a27d9013SAlfredo Cardigliano 		.pending_work = true,
1316a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1317a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1318a27d9013SAlfredo Cardigliano 			.lif_index = lif->index,
1319a27d9013SAlfredo Cardigliano 			.type = q->type,
1320a27d9013SAlfredo Cardigliano 			.index = q->index,
1321a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1322a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1323a27d9013SAlfredo Cardigliano 			.pid = q->pid,
1324a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1325a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1326a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1327a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1328a27d9013SAlfredo Cardigliano 		},
1329a27d9013SAlfredo Cardigliano 	};
1330a27d9013SAlfredo Cardigliano 	int err;
1331a27d9013SAlfredo Cardigliano 
1332a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.pid %d", ctx.cmd.q_init.pid);
1333a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1334a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1335a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1336a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1337a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
1338a27d9013SAlfredo Cardigliano 
1339a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1340a27d9013SAlfredo Cardigliano 	if (err)
1341a27d9013SAlfredo Cardigliano 		return err;
1342a27d9013SAlfredo Cardigliano 
1343a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1344a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1345a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1346a27d9013SAlfredo Cardigliano 
1347a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1348a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1349a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1350a27d9013SAlfredo Cardigliano 
1351a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1352a27d9013SAlfredo Cardigliano 
1353a27d9013SAlfredo Cardigliano 	return 0;
1354a27d9013SAlfredo Cardigliano }
1355a27d9013SAlfredo Cardigliano 
1356a27d9013SAlfredo Cardigliano int
1357a27d9013SAlfredo Cardigliano ionic_lif_rxq_init(struct ionic_qcq *qcq)
1358a27d9013SAlfredo Cardigliano {
1359a27d9013SAlfredo Cardigliano 	struct ionic_queue *q = &qcq->q;
1360a27d9013SAlfredo Cardigliano 	struct ionic_lif *lif = qcq->lif;
1361a27d9013SAlfredo Cardigliano 	struct ionic_cq *cq = &qcq->cq;
1362a27d9013SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1363a27d9013SAlfredo Cardigliano 		.pending_work = true,
1364a27d9013SAlfredo Cardigliano 		.cmd.q_init = {
1365a27d9013SAlfredo Cardigliano 			.opcode = IONIC_CMD_Q_INIT,
1366a27d9013SAlfredo Cardigliano 			.lif_index = lif->index,
1367a27d9013SAlfredo Cardigliano 			.type = q->type,
1368a27d9013SAlfredo Cardigliano 			.index = q->index,
1369a27d9013SAlfredo Cardigliano 			.flags = IONIC_QINIT_F_SG,
1370a27d9013SAlfredo Cardigliano 			.intr_index = cq->bound_intr->index,
1371a27d9013SAlfredo Cardigliano 			.pid = q->pid,
1372a27d9013SAlfredo Cardigliano 			.ring_size = rte_log2_u32(q->num_descs),
1373a27d9013SAlfredo Cardigliano 			.ring_base = q->base_pa,
1374a27d9013SAlfredo Cardigliano 			.cq_ring_base = cq->base_pa,
1375a27d9013SAlfredo Cardigliano 			.sg_ring_base = q->sg_base_pa,
1376a27d9013SAlfredo Cardigliano 		},
1377a27d9013SAlfredo Cardigliano 	};
1378a27d9013SAlfredo Cardigliano 	int err;
1379a27d9013SAlfredo Cardigliano 
1380a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.pid %d", ctx.cmd.q_init.pid);
1381a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1382a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1383a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_base);
1384a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1385a27d9013SAlfredo Cardigliano 		ctx.cmd.q_init.ring_size);
1386a27d9013SAlfredo Cardigliano 
1387a27d9013SAlfredo Cardigliano 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1388a27d9013SAlfredo Cardigliano 	if (err)
1389a27d9013SAlfredo Cardigliano 		return err;
1390a27d9013SAlfredo Cardigliano 
1391a27d9013SAlfredo Cardigliano 	q->hw_type = ctx.comp.q_init.hw_type;
1392a27d9013SAlfredo Cardigliano 	q->hw_index = ctx.comp.q_init.hw_index;
1393a27d9013SAlfredo Cardigliano 	q->db = ionic_db_map(lif, q);
1394a27d9013SAlfredo Cardigliano 
1395a27d9013SAlfredo Cardigliano 	qcq->flags |= IONIC_QCQ_F_INITED;
1396a27d9013SAlfredo Cardigliano 
1397a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1398a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1399a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1400a27d9013SAlfredo Cardigliano 
1401a27d9013SAlfredo Cardigliano 	return 0;
1402a27d9013SAlfredo Cardigliano }
1403a27d9013SAlfredo Cardigliano 
1404598f6726SAlfredo Cardigliano static int
1405598f6726SAlfredo Cardigliano ionic_station_set(struct ionic_lif *lif)
1406598f6726SAlfredo Cardigliano {
1407598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1408598f6726SAlfredo Cardigliano 		.pending_work = true,
1409598f6726SAlfredo Cardigliano 		.cmd.lif_getattr = {
1410598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_GETATTR,
1411598f6726SAlfredo Cardigliano 			.index = lif->index,
1412598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_MAC,
1413598f6726SAlfredo Cardigliano 		},
1414598f6726SAlfredo Cardigliano 	};
1415598f6726SAlfredo Cardigliano 	int err;
1416598f6726SAlfredo Cardigliano 
1417598f6726SAlfredo Cardigliano 	IONIC_PRINT_CALL();
1418598f6726SAlfredo Cardigliano 
1419598f6726SAlfredo Cardigliano 	err = ionic_adminq_post_wait(lif, &ctx);
1420598f6726SAlfredo Cardigliano 	if (err)
1421598f6726SAlfredo Cardigliano 		return err;
1422598f6726SAlfredo Cardigliano 
1423598f6726SAlfredo Cardigliano 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
1424598f6726SAlfredo Cardigliano 			lif->mac_addr)) {
1425598f6726SAlfredo Cardigliano 		IONIC_PRINT(INFO, "deleting station MAC addr");
1426598f6726SAlfredo Cardigliano 
1427598f6726SAlfredo Cardigliano 		ionic_lif_addr_del(lif, lif->mac_addr);
1428598f6726SAlfredo Cardigliano 	}
1429598f6726SAlfredo Cardigliano 
1430598f6726SAlfredo Cardigliano 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1431598f6726SAlfredo Cardigliano 
1432598f6726SAlfredo Cardigliano 	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
1433598f6726SAlfredo Cardigliano 		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
1434598f6726SAlfredo Cardigliano 		return 0;
1435598f6726SAlfredo Cardigliano 	}
1436598f6726SAlfredo Cardigliano 
1437598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "adding station MAC addr");
1438598f6726SAlfredo Cardigliano 
1439598f6726SAlfredo Cardigliano 	ionic_lif_addr_add(lif, lif->mac_addr);
1440598f6726SAlfredo Cardigliano 
1441598f6726SAlfredo Cardigliano 	return 0;
1442598f6726SAlfredo Cardigliano }
1443598f6726SAlfredo Cardigliano 
1444598f6726SAlfredo Cardigliano static void
1445598f6726SAlfredo Cardigliano ionic_lif_set_name(struct ionic_lif *lif)
1446598f6726SAlfredo Cardigliano {
1447598f6726SAlfredo Cardigliano 	struct ionic_admin_ctx ctx = {
1448598f6726SAlfredo Cardigliano 		.pending_work = true,
1449598f6726SAlfredo Cardigliano 		.cmd.lif_setattr = {
1450598f6726SAlfredo Cardigliano 			.opcode = IONIC_CMD_LIF_SETATTR,
1451598f6726SAlfredo Cardigliano 			.index = lif->index,
1452598f6726SAlfredo Cardigliano 			.attr = IONIC_LIF_ATTR_NAME,
1453598f6726SAlfredo Cardigliano 		},
1454598f6726SAlfredo Cardigliano 	};
1455598f6726SAlfredo Cardigliano 
1456598f6726SAlfredo Cardigliano 	snprintf(ctx.cmd.lif_setattr.name, sizeof(ctx.cmd.lif_setattr.name),
1457598f6726SAlfredo Cardigliano 		"%d", lif->port_id);
1458598f6726SAlfredo Cardigliano 
1459598f6726SAlfredo Cardigliano 	ionic_adminq_post_wait(lif, &ctx);
1460598f6726SAlfredo Cardigliano }
1461598f6726SAlfredo Cardigliano 
1462598f6726SAlfredo Cardigliano int
1463669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif)
1464669c8de6SAlfredo Cardigliano {
1465669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &lif->adapter->idev;
1466669c8de6SAlfredo Cardigliano 	struct ionic_q_init_comp comp;
1467669c8de6SAlfredo Cardigliano 	int err;
1468669c8de6SAlfredo Cardigliano 
1469*3cdfd905SAlfredo Cardigliano 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
1470*3cdfd905SAlfredo Cardigliano 
1471669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
1472669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1473669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_comp(idev, &comp);
1474669c8de6SAlfredo Cardigliano 	if (err)
1475669c8de6SAlfredo Cardigliano 		return err;
1476669c8de6SAlfredo Cardigliano 
1477669c8de6SAlfredo Cardigliano 	lif->hw_index = comp.hw_index;
1478669c8de6SAlfredo Cardigliano 
147901a6c311SAlfredo Cardigliano 	err = ionic_lif_adminq_init(lif);
148001a6c311SAlfredo Cardigliano 	if (err)
148101a6c311SAlfredo Cardigliano 		return err;
148201a6c311SAlfredo Cardigliano 
148327b942c8SAlfredo Cardigliano 	err = ionic_lif_notifyq_init(lif);
148427b942c8SAlfredo Cardigliano 	if (err)
148527b942c8SAlfredo Cardigliano 		goto err_out_adminq_deinit;
148627b942c8SAlfredo Cardigliano 
1487a27d9013SAlfredo Cardigliano 	lif->features =
1488a27d9013SAlfredo Cardigliano 		  IONIC_ETH_HW_VLAN_TX_TAG
1489a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_STRIP
1490a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_VLAN_RX_FILTER
1491a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_HASH
1492a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TX_SG
1493a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_SG
1494a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_RX_CSUM
1495a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO
1496a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_IPV6
1497a27d9013SAlfredo Cardigliano 		| IONIC_ETH_HW_TSO_ECN;
1498598f6726SAlfredo Cardigliano 
1499598f6726SAlfredo Cardigliano 	err = ionic_lif_set_features(lif);
1500598f6726SAlfredo Cardigliano 	if (err)
1501598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1502598f6726SAlfredo Cardigliano 
150354fe083fSAlfredo Cardigliano 	err = ionic_rx_filters_init(lif);
1504598f6726SAlfredo Cardigliano 	if (err)
1505598f6726SAlfredo Cardigliano 		goto err_out_notifyq_deinit;
1506598f6726SAlfredo Cardigliano 
150754fe083fSAlfredo Cardigliano 	err = ionic_station_set(lif);
150854fe083fSAlfredo Cardigliano 	if (err)
150954fe083fSAlfredo Cardigliano 		goto err_out_rx_filter_deinit;
151054fe083fSAlfredo Cardigliano 
1511598f6726SAlfredo Cardigliano 	ionic_lif_set_name(lif);
1512598f6726SAlfredo Cardigliano 
1513669c8de6SAlfredo Cardigliano 	lif->state |= IONIC_LIF_F_INITED;
1514669c8de6SAlfredo Cardigliano 
1515669c8de6SAlfredo Cardigliano 	return 0;
151627b942c8SAlfredo Cardigliano 
151754fe083fSAlfredo Cardigliano err_out_rx_filter_deinit:
151854fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
151954fe083fSAlfredo Cardigliano 
1520598f6726SAlfredo Cardigliano err_out_notifyq_deinit:
1521598f6726SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1522598f6726SAlfredo Cardigliano 
152327b942c8SAlfredo Cardigliano err_out_adminq_deinit:
152427b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
152527b942c8SAlfredo Cardigliano 
152627b942c8SAlfredo Cardigliano 	return err;
1527669c8de6SAlfredo Cardigliano }
1528669c8de6SAlfredo Cardigliano 
1529669c8de6SAlfredo Cardigliano void
1530669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif)
1531669c8de6SAlfredo Cardigliano {
1532669c8de6SAlfredo Cardigliano 	if (!(lif->state & IONIC_LIF_F_INITED))
1533669c8de6SAlfredo Cardigliano 		return;
1534669c8de6SAlfredo Cardigliano 
153554fe083fSAlfredo Cardigliano 	ionic_rx_filters_deinit(lif);
153622e7171bSAlfredo Cardigliano 	ionic_lif_rss_teardown(lif);
153727b942c8SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
153801a6c311SAlfredo Cardigliano 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
153901a6c311SAlfredo Cardigliano 
1540669c8de6SAlfredo Cardigliano 	lif->state &= ~IONIC_LIF_F_INITED;
1541669c8de6SAlfredo Cardigliano }
1542669c8de6SAlfredo Cardigliano 
1543669c8de6SAlfredo Cardigliano int
1544598f6726SAlfredo Cardigliano ionic_lif_configure(struct ionic_lif *lif)
1545598f6726SAlfredo Cardigliano {
154622e7171bSAlfredo Cardigliano 	struct ionic_identity *ident = &lif->adapter->ident;
154722e7171bSAlfredo Cardigliano 	uint32_t ntxqs_per_lif =
154822e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
154922e7171bSAlfredo Cardigliano 	uint32_t nrxqs_per_lif =
155022e7171bSAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
155122e7171bSAlfredo Cardigliano 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
155222e7171bSAlfredo Cardigliano 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
155322e7171bSAlfredo Cardigliano 
1554598f6726SAlfredo Cardigliano 	lif->port_id = lif->eth_dev->data->port_id;
1555598f6726SAlfredo Cardigliano 
155622e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
155722e7171bSAlfredo Cardigliano 		lif->port_id);
155822e7171bSAlfredo Cardigliano 
155922e7171bSAlfredo Cardigliano 	if (nrxqs > 0)
156022e7171bSAlfredo Cardigliano 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
156122e7171bSAlfredo Cardigliano 
156222e7171bSAlfredo Cardigliano 	if (ntxqs > 0)
156322e7171bSAlfredo Cardigliano 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
156422e7171bSAlfredo Cardigliano 
156522e7171bSAlfredo Cardigliano 	lif->nrxqcqs = nrxqs_per_lif;
156622e7171bSAlfredo Cardigliano 	lif->ntxqcqs = ntxqs_per_lif;
1567a27d9013SAlfredo Cardigliano 
1568598f6726SAlfredo Cardigliano 	return 0;
1569598f6726SAlfredo Cardigliano }
1570598f6726SAlfredo Cardigliano 
1571598f6726SAlfredo Cardigliano int
1572598f6726SAlfredo Cardigliano ionic_lif_start(struct ionic_lif *lif)
1573598f6726SAlfredo Cardigliano {
1574598f6726SAlfredo Cardigliano 	uint32_t rx_mode = 0;
1575a27d9013SAlfredo Cardigliano 	uint32_t i;
1576a27d9013SAlfredo Cardigliano 	int err;
1577598f6726SAlfredo Cardigliano 
157822e7171bSAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Setting RSS configuration on port %u",
157922e7171bSAlfredo Cardigliano 		lif->port_id);
158022e7171bSAlfredo Cardigliano 
158122e7171bSAlfredo Cardigliano 	err = ionic_lif_rss_setup(lif);
158222e7171bSAlfredo Cardigliano 	if (err)
158322e7171bSAlfredo Cardigliano 		return err;
158422e7171bSAlfredo Cardigliano 
1585598f6726SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Setting RX mode on port %u",
1586598f6726SAlfredo Cardigliano 		lif->port_id);
1587598f6726SAlfredo Cardigliano 
1588598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_UNICAST;
1589598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1590598f6726SAlfredo Cardigliano 	rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1591598f6726SAlfredo Cardigliano 
1592598f6726SAlfredo Cardigliano 	lif->rx_mode = 0; /* set by ionic_set_rx_mode */
1593598f6726SAlfredo Cardigliano 
1594598f6726SAlfredo Cardigliano 	ionic_set_rx_mode(lif, rx_mode);
1595598f6726SAlfredo Cardigliano 
1596a27d9013SAlfredo Cardigliano 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1597a27d9013SAlfredo Cardigliano 		"on port %u",
1598a27d9013SAlfredo Cardigliano 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1599a27d9013SAlfredo Cardigliano 
1600a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->nrxqcqs; i++) {
1601a27d9013SAlfredo Cardigliano 		struct ionic_qcq *rxq = lif->rxqcqs[i];
1602a27d9013SAlfredo Cardigliano 		if (!rxq->deferred_start) {
1603a27d9013SAlfredo Cardigliano 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1604a27d9013SAlfredo Cardigliano 
1605a27d9013SAlfredo Cardigliano 			if (err)
1606a27d9013SAlfredo Cardigliano 				return err;
1607a27d9013SAlfredo Cardigliano 		}
1608a27d9013SAlfredo Cardigliano 	}
1609a27d9013SAlfredo Cardigliano 
1610a27d9013SAlfredo Cardigliano 	for (i = 0; i < lif->ntxqcqs; i++) {
1611a27d9013SAlfredo Cardigliano 		struct ionic_qcq *txq = lif->txqcqs[i];
1612a27d9013SAlfredo Cardigliano 		if (!txq->deferred_start) {
1613a27d9013SAlfredo Cardigliano 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1614a27d9013SAlfredo Cardigliano 
1615a27d9013SAlfredo Cardigliano 			if (err)
1616a27d9013SAlfredo Cardigliano 				return err;
1617a27d9013SAlfredo Cardigliano 		}
1618a27d9013SAlfredo Cardigliano 	}
1619a27d9013SAlfredo Cardigliano 
1620598f6726SAlfredo Cardigliano 	ionic_link_status_check(lif);
1621598f6726SAlfredo Cardigliano 
1622598f6726SAlfredo Cardigliano 	/* Carrier ON here */
1623598f6726SAlfredo Cardigliano 
1624598f6726SAlfredo Cardigliano 	return 0;
1625598f6726SAlfredo Cardigliano }
1626598f6726SAlfredo Cardigliano 
1627598f6726SAlfredo Cardigliano int
1628669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter)
1629669c8de6SAlfredo Cardigliano {
1630669c8de6SAlfredo Cardigliano 	struct ionic_dev *idev = &adapter->idev;
1631669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1632669c8de6SAlfredo Cardigliano 	int err;
1633669c8de6SAlfredo Cardigliano 	unsigned int i;
1634669c8de6SAlfredo Cardigliano 	unsigned int lif_words = sizeof(ident->lif.words) /
1635669c8de6SAlfredo Cardigliano 		sizeof(ident->lif.words[0]);
1636669c8de6SAlfredo Cardigliano 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1637669c8de6SAlfredo Cardigliano 		sizeof(idev->dev_cmd->data[0]);
1638669c8de6SAlfredo Cardigliano 	unsigned int nwords;
1639669c8de6SAlfredo Cardigliano 
1640669c8de6SAlfredo Cardigliano 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1641669c8de6SAlfredo Cardigliano 		IONIC_IDENTITY_VERSION_1);
1642669c8de6SAlfredo Cardigliano 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1643669c8de6SAlfredo Cardigliano 	if (err)
1644669c8de6SAlfredo Cardigliano 		return (err);
1645669c8de6SAlfredo Cardigliano 
1646669c8de6SAlfredo Cardigliano 	nwords = RTE_MIN(lif_words, cmd_words);
1647669c8de6SAlfredo Cardigliano 	for (i = 0; i < nwords; i++)
1648669c8de6SAlfredo Cardigliano 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1649669c8de6SAlfredo Cardigliano 
1650669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1651669c8de6SAlfredo Cardigliano 		ident->lif.capabilities);
1652669c8de6SAlfredo Cardigliano 
1653669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1654669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_ucast_filters);
1655669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1656669c8de6SAlfredo Cardigliano 		ident->lif.eth.max_mcast_filters);
1657669c8de6SAlfredo Cardigliano 
1658669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1659669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.features);
1660669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1661669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1662669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1663669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1664669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1665669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1666669c8de6SAlfredo Cardigliano 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1667669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1668669c8de6SAlfredo Cardigliano 
1669669c8de6SAlfredo Cardigliano 	return 0;
1670669c8de6SAlfredo Cardigliano }
1671669c8de6SAlfredo Cardigliano 
1672669c8de6SAlfredo Cardigliano int
1673669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter)
1674669c8de6SAlfredo Cardigliano {
1675669c8de6SAlfredo Cardigliano 	struct ionic_identity *ident = &adapter->ident;
1676669c8de6SAlfredo Cardigliano 	uint32_t nlifs = ident->dev.nlifs;
1677669c8de6SAlfredo Cardigliano 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1678669c8de6SAlfredo Cardigliano 
1679669c8de6SAlfredo Cardigliano 	adapter->max_ntxqs_per_lif =
1680669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1681669c8de6SAlfredo Cardigliano 	adapter->max_nrxqs_per_lif =
1682669c8de6SAlfredo Cardigliano 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1683669c8de6SAlfredo Cardigliano 
1684669c8de6SAlfredo Cardigliano 	nintrs = nlifs * 1 /* notifyq */;
1685669c8de6SAlfredo Cardigliano 
1686669c8de6SAlfredo Cardigliano 	if (nintrs > dev_nintrs) {
1687669c8de6SAlfredo Cardigliano 		IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u",
1688669c8de6SAlfredo Cardigliano 			dev_nintrs, nintrs);
1689669c8de6SAlfredo Cardigliano 		return -ENOSPC;
1690669c8de6SAlfredo Cardigliano 	}
1691669c8de6SAlfredo Cardigliano 
1692669c8de6SAlfredo Cardigliano 	adapter->nintrs = nintrs;
1693669c8de6SAlfredo Cardigliano 
1694669c8de6SAlfredo Cardigliano 	return 0;
1695669c8de6SAlfredo Cardigliano }
1696