xref: /f-stack/dpdk/drivers/net/ionic/ionic_lif.c (revision 2d9fd380)
1*2d9fd380Sjfb8856606 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2*2d9fd380Sjfb8856606  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3*2d9fd380Sjfb8856606  */
4*2d9fd380Sjfb8856606 
5*2d9fd380Sjfb8856606 #include <rte_malloc.h>
6*2d9fd380Sjfb8856606 #include <rte_ethdev_driver.h>
7*2d9fd380Sjfb8856606 
8*2d9fd380Sjfb8856606 #include "ionic.h"
9*2d9fd380Sjfb8856606 #include "ionic_logs.h"
10*2d9fd380Sjfb8856606 #include "ionic_lif.h"
11*2d9fd380Sjfb8856606 #include "ionic_ethdev.h"
12*2d9fd380Sjfb8856606 #include "ionic_rx_filter.h"
13*2d9fd380Sjfb8856606 #include "ionic_rxtx.h"
14*2d9fd380Sjfb8856606 
15*2d9fd380Sjfb8856606 static int ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr);
16*2d9fd380Sjfb8856606 static int ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr);
17*2d9fd380Sjfb8856606 
18*2d9fd380Sjfb8856606 int
ionic_qcq_enable(struct ionic_qcq * qcq)19*2d9fd380Sjfb8856606 ionic_qcq_enable(struct ionic_qcq *qcq)
20*2d9fd380Sjfb8856606 {
21*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
22*2d9fd380Sjfb8856606 	struct ionic_lif *lif = q->lif;
23*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
24*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
25*2d9fd380Sjfb8856606 		.pending_work = true,
26*2d9fd380Sjfb8856606 		.cmd.q_control = {
27*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_Q_CONTROL,
28*2d9fd380Sjfb8856606 			.lif_index = lif->index,
29*2d9fd380Sjfb8856606 			.type = q->type,
30*2d9fd380Sjfb8856606 			.index = q->index,
31*2d9fd380Sjfb8856606 			.oper = IONIC_Q_ENABLE,
32*2d9fd380Sjfb8856606 		},
33*2d9fd380Sjfb8856606 	};
34*2d9fd380Sjfb8856606 
35*2d9fd380Sjfb8856606 	if (qcq->flags & IONIC_QCQ_F_INTR) {
36*2d9fd380Sjfb8856606 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
37*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_CLEAR);
38*2d9fd380Sjfb8856606 	}
39*2d9fd380Sjfb8856606 
40*2d9fd380Sjfb8856606 	return ionic_adminq_post_wait(lif, &ctx);
41*2d9fd380Sjfb8856606 }
42*2d9fd380Sjfb8856606 
43*2d9fd380Sjfb8856606 int
ionic_qcq_disable(struct ionic_qcq * qcq)44*2d9fd380Sjfb8856606 ionic_qcq_disable(struct ionic_qcq *qcq)
45*2d9fd380Sjfb8856606 {
46*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
47*2d9fd380Sjfb8856606 	struct ionic_lif *lif = q->lif;
48*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
49*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
50*2d9fd380Sjfb8856606 		.pending_work = true,
51*2d9fd380Sjfb8856606 		.cmd.q_control = {
52*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_Q_CONTROL,
53*2d9fd380Sjfb8856606 			.lif_index = lif->index,
54*2d9fd380Sjfb8856606 			.type = q->type,
55*2d9fd380Sjfb8856606 			.index = q->index,
56*2d9fd380Sjfb8856606 			.oper = IONIC_Q_DISABLE,
57*2d9fd380Sjfb8856606 		},
58*2d9fd380Sjfb8856606 	};
59*2d9fd380Sjfb8856606 
60*2d9fd380Sjfb8856606 	if (qcq->flags & IONIC_QCQ_F_INTR) {
61*2d9fd380Sjfb8856606 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
62*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_SET);
63*2d9fd380Sjfb8856606 	}
64*2d9fd380Sjfb8856606 
65*2d9fd380Sjfb8856606 	return ionic_adminq_post_wait(lif, &ctx);
66*2d9fd380Sjfb8856606 }
67*2d9fd380Sjfb8856606 
68*2d9fd380Sjfb8856606 int
ionic_lif_stop(struct ionic_lif * lif __rte_unused)69*2d9fd380Sjfb8856606 ionic_lif_stop(struct ionic_lif *lif __rte_unused)
70*2d9fd380Sjfb8856606 {
71*2d9fd380Sjfb8856606 	/* Carrier OFF here */
72*2d9fd380Sjfb8856606 
73*2d9fd380Sjfb8856606 	return 0;
74*2d9fd380Sjfb8856606 }
75*2d9fd380Sjfb8856606 
76*2d9fd380Sjfb8856606 void
ionic_lif_reset(struct ionic_lif * lif)77*2d9fd380Sjfb8856606 ionic_lif_reset(struct ionic_lif *lif)
78*2d9fd380Sjfb8856606 {
79*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
80*2d9fd380Sjfb8856606 
81*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
82*2d9fd380Sjfb8856606 
83*2d9fd380Sjfb8856606 	ionic_dev_cmd_lif_reset(idev, lif->index);
84*2d9fd380Sjfb8856606 	ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
85*2d9fd380Sjfb8856606 }
86*2d9fd380Sjfb8856606 
87*2d9fd380Sjfb8856606 static void
ionic_lif_get_abs_stats(const struct ionic_lif * lif,struct rte_eth_stats * stats)88*2d9fd380Sjfb8856606 ionic_lif_get_abs_stats(const struct ionic_lif *lif, struct rte_eth_stats *stats)
89*2d9fd380Sjfb8856606 {
90*2d9fd380Sjfb8856606 	struct ionic_lif_stats *ls = &lif->info->stats;
91*2d9fd380Sjfb8856606 	uint32_t i;
92*2d9fd380Sjfb8856606 	uint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)
93*2d9fd380Sjfb8856606 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
94*2d9fd380Sjfb8856606 	uint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)
95*2d9fd380Sjfb8856606 			RTE_ETHDEV_QUEUE_STAT_CNTRS);
96*2d9fd380Sjfb8856606 
97*2d9fd380Sjfb8856606 	memset(stats, 0, sizeof(*stats));
98*2d9fd380Sjfb8856606 
99*2d9fd380Sjfb8856606 	if (ls == NULL) {
100*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "Stats on port %u not yet initialized",
101*2d9fd380Sjfb8856606 			lif->port_id);
102*2d9fd380Sjfb8856606 		return;
103*2d9fd380Sjfb8856606 	}
104*2d9fd380Sjfb8856606 
105*2d9fd380Sjfb8856606 	/* RX */
106*2d9fd380Sjfb8856606 
107*2d9fd380Sjfb8856606 	stats->ipackets = ls->rx_ucast_packets +
108*2d9fd380Sjfb8856606 		ls->rx_mcast_packets +
109*2d9fd380Sjfb8856606 		ls->rx_bcast_packets;
110*2d9fd380Sjfb8856606 
111*2d9fd380Sjfb8856606 	stats->ibytes = ls->rx_ucast_bytes +
112*2d9fd380Sjfb8856606 		ls->rx_mcast_bytes +
113*2d9fd380Sjfb8856606 		ls->rx_bcast_bytes;
114*2d9fd380Sjfb8856606 
115*2d9fd380Sjfb8856606 	for (i = 0; i < lif->nrxqcqs; i++) {
116*2d9fd380Sjfb8856606 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
117*2d9fd380Sjfb8856606 		stats->imissed +=
118*2d9fd380Sjfb8856606 			rx_stats->no_cb_arg +
119*2d9fd380Sjfb8856606 			rx_stats->bad_cq_status +
120*2d9fd380Sjfb8856606 			rx_stats->no_room +
121*2d9fd380Sjfb8856606 			rx_stats->bad_len;
122*2d9fd380Sjfb8856606 	}
123*2d9fd380Sjfb8856606 
124*2d9fd380Sjfb8856606 	stats->imissed +=
125*2d9fd380Sjfb8856606 		ls->rx_ucast_drop_packets +
126*2d9fd380Sjfb8856606 		ls->rx_mcast_drop_packets +
127*2d9fd380Sjfb8856606 		ls->rx_bcast_drop_packets;
128*2d9fd380Sjfb8856606 
129*2d9fd380Sjfb8856606 	stats->imissed +=
130*2d9fd380Sjfb8856606 		ls->rx_queue_empty +
131*2d9fd380Sjfb8856606 		ls->rx_dma_error +
132*2d9fd380Sjfb8856606 		ls->rx_queue_disabled +
133*2d9fd380Sjfb8856606 		ls->rx_desc_fetch_error +
134*2d9fd380Sjfb8856606 		ls->rx_desc_data_error;
135*2d9fd380Sjfb8856606 
136*2d9fd380Sjfb8856606 	for (i = 0; i < num_rx_q_counters; i++) {
137*2d9fd380Sjfb8856606 		struct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;
138*2d9fd380Sjfb8856606 		stats->q_ipackets[i] = rx_stats->packets;
139*2d9fd380Sjfb8856606 		stats->q_ibytes[i] = rx_stats->bytes;
140*2d9fd380Sjfb8856606 		stats->q_errors[i] =
141*2d9fd380Sjfb8856606 			rx_stats->no_cb_arg +
142*2d9fd380Sjfb8856606 			rx_stats->bad_cq_status +
143*2d9fd380Sjfb8856606 			rx_stats->no_room +
144*2d9fd380Sjfb8856606 			rx_stats->bad_len;
145*2d9fd380Sjfb8856606 	}
146*2d9fd380Sjfb8856606 
147*2d9fd380Sjfb8856606 	/* TX */
148*2d9fd380Sjfb8856606 
149*2d9fd380Sjfb8856606 	stats->opackets = ls->tx_ucast_packets +
150*2d9fd380Sjfb8856606 		ls->tx_mcast_packets +
151*2d9fd380Sjfb8856606 		ls->tx_bcast_packets;
152*2d9fd380Sjfb8856606 
153*2d9fd380Sjfb8856606 	stats->obytes = ls->tx_ucast_bytes +
154*2d9fd380Sjfb8856606 		ls->tx_mcast_bytes +
155*2d9fd380Sjfb8856606 		ls->tx_bcast_bytes;
156*2d9fd380Sjfb8856606 
157*2d9fd380Sjfb8856606 	for (i = 0; i < lif->ntxqcqs; i++) {
158*2d9fd380Sjfb8856606 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
159*2d9fd380Sjfb8856606 		stats->oerrors += tx_stats->drop;
160*2d9fd380Sjfb8856606 	}
161*2d9fd380Sjfb8856606 
162*2d9fd380Sjfb8856606 	stats->oerrors +=
163*2d9fd380Sjfb8856606 		ls->tx_ucast_drop_packets +
164*2d9fd380Sjfb8856606 		ls->tx_mcast_drop_packets +
165*2d9fd380Sjfb8856606 		ls->tx_bcast_drop_packets;
166*2d9fd380Sjfb8856606 
167*2d9fd380Sjfb8856606 	stats->oerrors +=
168*2d9fd380Sjfb8856606 		ls->tx_dma_error +
169*2d9fd380Sjfb8856606 		ls->tx_queue_disabled +
170*2d9fd380Sjfb8856606 		ls->tx_desc_fetch_error +
171*2d9fd380Sjfb8856606 		ls->tx_desc_data_error;
172*2d9fd380Sjfb8856606 
173*2d9fd380Sjfb8856606 	for (i = 0; i < num_tx_q_counters; i++) {
174*2d9fd380Sjfb8856606 		struct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;
175*2d9fd380Sjfb8856606 		stats->q_opackets[i] = tx_stats->packets;
176*2d9fd380Sjfb8856606 		stats->q_obytes[i] = tx_stats->bytes;
177*2d9fd380Sjfb8856606 	}
178*2d9fd380Sjfb8856606 }
179*2d9fd380Sjfb8856606 
180*2d9fd380Sjfb8856606 void
ionic_lif_get_stats(const struct ionic_lif * lif,struct rte_eth_stats * stats)181*2d9fd380Sjfb8856606 ionic_lif_get_stats(const struct ionic_lif *lif,
182*2d9fd380Sjfb8856606 		struct rte_eth_stats *stats)
183*2d9fd380Sjfb8856606 {
184*2d9fd380Sjfb8856606 	ionic_lif_get_abs_stats(lif, stats);
185*2d9fd380Sjfb8856606 
186*2d9fd380Sjfb8856606 	stats->ipackets  -= lif->stats_base.ipackets;
187*2d9fd380Sjfb8856606 	stats->opackets  -= lif->stats_base.opackets;
188*2d9fd380Sjfb8856606 	stats->ibytes    -= lif->stats_base.ibytes;
189*2d9fd380Sjfb8856606 	stats->obytes    -= lif->stats_base.obytes;
190*2d9fd380Sjfb8856606 	stats->imissed   -= lif->stats_base.imissed;
191*2d9fd380Sjfb8856606 	stats->ierrors   -= lif->stats_base.ierrors;
192*2d9fd380Sjfb8856606 	stats->oerrors   -= lif->stats_base.oerrors;
193*2d9fd380Sjfb8856606 	stats->rx_nombuf -= lif->stats_base.rx_nombuf;
194*2d9fd380Sjfb8856606 }
195*2d9fd380Sjfb8856606 
196*2d9fd380Sjfb8856606 void
ionic_lif_reset_stats(struct ionic_lif * lif)197*2d9fd380Sjfb8856606 ionic_lif_reset_stats(struct ionic_lif *lif)
198*2d9fd380Sjfb8856606 {
199*2d9fd380Sjfb8856606 	uint32_t i;
200*2d9fd380Sjfb8856606 
201*2d9fd380Sjfb8856606 	for (i = 0; i < lif->nrxqcqs; i++) {
202*2d9fd380Sjfb8856606 		memset(&lif->rxqcqs[i]->stats.rx, 0,
203*2d9fd380Sjfb8856606 			sizeof(struct ionic_rx_stats));
204*2d9fd380Sjfb8856606 		memset(&lif->txqcqs[i]->stats.tx, 0,
205*2d9fd380Sjfb8856606 			sizeof(struct ionic_tx_stats));
206*2d9fd380Sjfb8856606 	}
207*2d9fd380Sjfb8856606 
208*2d9fd380Sjfb8856606 	ionic_lif_get_abs_stats(lif, &lif->stats_base);
209*2d9fd380Sjfb8856606 }
210*2d9fd380Sjfb8856606 
211*2d9fd380Sjfb8856606 void
ionic_lif_get_hw_stats(struct ionic_lif * lif,struct ionic_lif_stats * stats)212*2d9fd380Sjfb8856606 ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)
213*2d9fd380Sjfb8856606 {
214*2d9fd380Sjfb8856606 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
215*2d9fd380Sjfb8856606 	uint64_t *stats64 = (uint64_t *)stats;
216*2d9fd380Sjfb8856606 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
217*2d9fd380Sjfb8856606 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
218*2d9fd380Sjfb8856606 
219*2d9fd380Sjfb8856606 	for (i = 0; i < count; i++)
220*2d9fd380Sjfb8856606 		stats64[i] = lif_stats64[i] - lif_stats64_base[i];
221*2d9fd380Sjfb8856606 }
222*2d9fd380Sjfb8856606 
223*2d9fd380Sjfb8856606 void
ionic_lif_reset_hw_stats(struct ionic_lif * lif)224*2d9fd380Sjfb8856606 ionic_lif_reset_hw_stats(struct ionic_lif *lif)
225*2d9fd380Sjfb8856606 {
226*2d9fd380Sjfb8856606 	uint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);
227*2d9fd380Sjfb8856606 	uint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;
228*2d9fd380Sjfb8856606 	uint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;
229*2d9fd380Sjfb8856606 
230*2d9fd380Sjfb8856606 	for (i = 0; i < count; i++)
231*2d9fd380Sjfb8856606 		lif_stats64_base[i] = lif_stats64[i];
232*2d9fd380Sjfb8856606 }
233*2d9fd380Sjfb8856606 
234*2d9fd380Sjfb8856606 static int
ionic_lif_addr_add(struct ionic_lif * lif,const uint8_t * addr)235*2d9fd380Sjfb8856606 ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)
236*2d9fd380Sjfb8856606 {
237*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
238*2d9fd380Sjfb8856606 		.pending_work = true,
239*2d9fd380Sjfb8856606 		.cmd.rx_filter_add = {
240*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_RX_FILTER_ADD,
241*2d9fd380Sjfb8856606 			.match = IONIC_RX_FILTER_MATCH_MAC,
242*2d9fd380Sjfb8856606 		},
243*2d9fd380Sjfb8856606 	};
244*2d9fd380Sjfb8856606 	int err;
245*2d9fd380Sjfb8856606 
246*2d9fd380Sjfb8856606 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, RTE_ETHER_ADDR_LEN);
247*2d9fd380Sjfb8856606 
248*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
249*2d9fd380Sjfb8856606 	if (err)
250*2d9fd380Sjfb8856606 		return err;
251*2d9fd380Sjfb8856606 
252*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "rx_filter add (id %d)",
253*2d9fd380Sjfb8856606 		ctx.comp.rx_filter_add.filter_id);
254*2d9fd380Sjfb8856606 
255*2d9fd380Sjfb8856606 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
256*2d9fd380Sjfb8856606 }
257*2d9fd380Sjfb8856606 
258*2d9fd380Sjfb8856606 static int
ionic_lif_addr_del(struct ionic_lif * lif,const uint8_t * addr)259*2d9fd380Sjfb8856606 ionic_lif_addr_del(struct ionic_lif *lif, const uint8_t *addr)
260*2d9fd380Sjfb8856606 {
261*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
262*2d9fd380Sjfb8856606 		.pending_work = true,
263*2d9fd380Sjfb8856606 		.cmd.rx_filter_del = {
264*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_RX_FILTER_DEL,
265*2d9fd380Sjfb8856606 		},
266*2d9fd380Sjfb8856606 	};
267*2d9fd380Sjfb8856606 	struct ionic_rx_filter *f;
268*2d9fd380Sjfb8856606 	int err;
269*2d9fd380Sjfb8856606 
270*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
271*2d9fd380Sjfb8856606 
272*2d9fd380Sjfb8856606 	rte_spinlock_lock(&lif->rx_filters.lock);
273*2d9fd380Sjfb8856606 
274*2d9fd380Sjfb8856606 	f = ionic_rx_filter_by_addr(lif, addr);
275*2d9fd380Sjfb8856606 	if (!f) {
276*2d9fd380Sjfb8856606 		rte_spinlock_unlock(&lif->rx_filters.lock);
277*2d9fd380Sjfb8856606 		return -ENOENT;
278*2d9fd380Sjfb8856606 	}
279*2d9fd380Sjfb8856606 
280*2d9fd380Sjfb8856606 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
281*2d9fd380Sjfb8856606 	ionic_rx_filter_free(f);
282*2d9fd380Sjfb8856606 
283*2d9fd380Sjfb8856606 	rte_spinlock_unlock(&lif->rx_filters.lock);
284*2d9fd380Sjfb8856606 
285*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
286*2d9fd380Sjfb8856606 	if (err)
287*2d9fd380Sjfb8856606 		return err;
288*2d9fd380Sjfb8856606 
289*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "rx_filter del (id %d)",
290*2d9fd380Sjfb8856606 		ctx.cmd.rx_filter_del.filter_id);
291*2d9fd380Sjfb8856606 
292*2d9fd380Sjfb8856606 	return 0;
293*2d9fd380Sjfb8856606 }
294*2d9fd380Sjfb8856606 
295*2d9fd380Sjfb8856606 int
ionic_dev_add_mac(struct rte_eth_dev * eth_dev,struct rte_ether_addr * mac_addr,uint32_t index __rte_unused,uint32_t pool __rte_unused)296*2d9fd380Sjfb8856606 ionic_dev_add_mac(struct rte_eth_dev *eth_dev,
297*2d9fd380Sjfb8856606 		struct rte_ether_addr *mac_addr,
298*2d9fd380Sjfb8856606 		uint32_t index __rte_unused, uint32_t pool __rte_unused)
299*2d9fd380Sjfb8856606 {
300*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
301*2d9fd380Sjfb8856606 
302*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
303*2d9fd380Sjfb8856606 
304*2d9fd380Sjfb8856606 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
305*2d9fd380Sjfb8856606 }
306*2d9fd380Sjfb8856606 
307*2d9fd380Sjfb8856606 void
ionic_dev_remove_mac(struct rte_eth_dev * eth_dev,uint32_t index __rte_unused)308*2d9fd380Sjfb8856606 ionic_dev_remove_mac(struct rte_eth_dev *eth_dev, uint32_t index __rte_unused)
309*2d9fd380Sjfb8856606 {
310*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
311*2d9fd380Sjfb8856606 	struct ionic_adapter *adapter = lif->adapter;
312*2d9fd380Sjfb8856606 
313*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
314*2d9fd380Sjfb8856606 
315*2d9fd380Sjfb8856606 	if (index >= adapter->max_mac_addrs) {
316*2d9fd380Sjfb8856606 		IONIC_PRINT(WARNING,
317*2d9fd380Sjfb8856606 			"Index %u is above MAC filter limit %u",
318*2d9fd380Sjfb8856606 			index, adapter->max_mac_addrs);
319*2d9fd380Sjfb8856606 		return;
320*2d9fd380Sjfb8856606 	}
321*2d9fd380Sjfb8856606 
322*2d9fd380Sjfb8856606 	if (!rte_is_valid_assigned_ether_addr(&eth_dev->data->mac_addrs[index]))
323*2d9fd380Sjfb8856606 		return;
324*2d9fd380Sjfb8856606 
325*2d9fd380Sjfb8856606 	ionic_lif_addr_del(lif, (const uint8_t *)
326*2d9fd380Sjfb8856606 		&eth_dev->data->mac_addrs[index]);
327*2d9fd380Sjfb8856606 }
328*2d9fd380Sjfb8856606 
329*2d9fd380Sjfb8856606 int
ionic_dev_set_mac(struct rte_eth_dev * eth_dev,struct rte_ether_addr * mac_addr)330*2d9fd380Sjfb8856606 ionic_dev_set_mac(struct rte_eth_dev *eth_dev, struct rte_ether_addr *mac_addr)
331*2d9fd380Sjfb8856606 {
332*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
333*2d9fd380Sjfb8856606 
334*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
335*2d9fd380Sjfb8856606 
336*2d9fd380Sjfb8856606 	if (mac_addr == NULL) {
337*2d9fd380Sjfb8856606 		IONIC_PRINT(NOTICE, "New mac is null");
338*2d9fd380Sjfb8856606 		return -1;
339*2d9fd380Sjfb8856606 	}
340*2d9fd380Sjfb8856606 
341*2d9fd380Sjfb8856606 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
342*2d9fd380Sjfb8856606 		IONIC_PRINT(INFO, "Deleting mac addr %pM",
343*2d9fd380Sjfb8856606 			lif->mac_addr);
344*2d9fd380Sjfb8856606 		ionic_lif_addr_del(lif, lif->mac_addr);
345*2d9fd380Sjfb8856606 		memset(lif->mac_addr, 0, RTE_ETHER_ADDR_LEN);
346*2d9fd380Sjfb8856606 	}
347*2d9fd380Sjfb8856606 
348*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "Updating mac addr");
349*2d9fd380Sjfb8856606 
350*2d9fd380Sjfb8856606 	rte_ether_addr_copy(mac_addr, (struct rte_ether_addr *)lif->mac_addr);
351*2d9fd380Sjfb8856606 
352*2d9fd380Sjfb8856606 	return ionic_lif_addr_add(lif, (const uint8_t *)mac_addr);
353*2d9fd380Sjfb8856606 }
354*2d9fd380Sjfb8856606 
355*2d9fd380Sjfb8856606 static int
ionic_vlan_rx_add_vid(struct ionic_lif * lif,uint16_t vid)356*2d9fd380Sjfb8856606 ionic_vlan_rx_add_vid(struct ionic_lif *lif, uint16_t vid)
357*2d9fd380Sjfb8856606 {
358*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
359*2d9fd380Sjfb8856606 		.pending_work = true,
360*2d9fd380Sjfb8856606 		.cmd.rx_filter_add = {
361*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_RX_FILTER_ADD,
362*2d9fd380Sjfb8856606 			.match = IONIC_RX_FILTER_MATCH_VLAN,
363*2d9fd380Sjfb8856606 			.vlan.vlan = vid,
364*2d9fd380Sjfb8856606 		},
365*2d9fd380Sjfb8856606 	};
366*2d9fd380Sjfb8856606 	int err;
367*2d9fd380Sjfb8856606 
368*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
369*2d9fd380Sjfb8856606 	if (err)
370*2d9fd380Sjfb8856606 		return err;
371*2d9fd380Sjfb8856606 
372*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "rx_filter add VLAN %d (id %d)", vid,
373*2d9fd380Sjfb8856606 		ctx.comp.rx_filter_add.filter_id);
374*2d9fd380Sjfb8856606 
375*2d9fd380Sjfb8856606 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, &ctx);
376*2d9fd380Sjfb8856606 }
377*2d9fd380Sjfb8856606 
378*2d9fd380Sjfb8856606 static int
ionic_vlan_rx_kill_vid(struct ionic_lif * lif,uint16_t vid)379*2d9fd380Sjfb8856606 ionic_vlan_rx_kill_vid(struct ionic_lif *lif, uint16_t vid)
380*2d9fd380Sjfb8856606 {
381*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
382*2d9fd380Sjfb8856606 		.pending_work = true,
383*2d9fd380Sjfb8856606 		.cmd.rx_filter_del = {
384*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_RX_FILTER_DEL,
385*2d9fd380Sjfb8856606 		},
386*2d9fd380Sjfb8856606 	};
387*2d9fd380Sjfb8856606 	struct ionic_rx_filter *f;
388*2d9fd380Sjfb8856606 	int err;
389*2d9fd380Sjfb8856606 
390*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
391*2d9fd380Sjfb8856606 
392*2d9fd380Sjfb8856606 	rte_spinlock_lock(&lif->rx_filters.lock);
393*2d9fd380Sjfb8856606 
394*2d9fd380Sjfb8856606 	f = ionic_rx_filter_by_vlan(lif, vid);
395*2d9fd380Sjfb8856606 	if (!f) {
396*2d9fd380Sjfb8856606 		rte_spinlock_unlock(&lif->rx_filters.lock);
397*2d9fd380Sjfb8856606 		return -ENOENT;
398*2d9fd380Sjfb8856606 	}
399*2d9fd380Sjfb8856606 
400*2d9fd380Sjfb8856606 	ctx.cmd.rx_filter_del.filter_id = f->filter_id;
401*2d9fd380Sjfb8856606 	ionic_rx_filter_free(f);
402*2d9fd380Sjfb8856606 	rte_spinlock_unlock(&lif->rx_filters.lock);
403*2d9fd380Sjfb8856606 
404*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
405*2d9fd380Sjfb8856606 	if (err)
406*2d9fd380Sjfb8856606 		return err;
407*2d9fd380Sjfb8856606 
408*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "rx_filter del VLAN %d (id %d)", vid,
409*2d9fd380Sjfb8856606 		ctx.cmd.rx_filter_del.filter_id);
410*2d9fd380Sjfb8856606 
411*2d9fd380Sjfb8856606 	return 0;
412*2d9fd380Sjfb8856606 }
413*2d9fd380Sjfb8856606 
414*2d9fd380Sjfb8856606 int
ionic_dev_vlan_filter_set(struct rte_eth_dev * eth_dev,uint16_t vlan_id,int on)415*2d9fd380Sjfb8856606 ionic_dev_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
416*2d9fd380Sjfb8856606 		int on)
417*2d9fd380Sjfb8856606 {
418*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
419*2d9fd380Sjfb8856606 	int err;
420*2d9fd380Sjfb8856606 
421*2d9fd380Sjfb8856606 	if (on)
422*2d9fd380Sjfb8856606 		err = ionic_vlan_rx_add_vid(lif, vlan_id);
423*2d9fd380Sjfb8856606 	else
424*2d9fd380Sjfb8856606 		err = ionic_vlan_rx_kill_vid(lif, vlan_id);
425*2d9fd380Sjfb8856606 
426*2d9fd380Sjfb8856606 	return err;
427*2d9fd380Sjfb8856606 }
428*2d9fd380Sjfb8856606 
429*2d9fd380Sjfb8856606 static void
ionic_lif_rx_mode(struct ionic_lif * lif,uint32_t rx_mode)430*2d9fd380Sjfb8856606 ionic_lif_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
431*2d9fd380Sjfb8856606 {
432*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
433*2d9fd380Sjfb8856606 		.pending_work = true,
434*2d9fd380Sjfb8856606 		.cmd.rx_mode_set = {
435*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_RX_MODE_SET,
436*2d9fd380Sjfb8856606 			.lif_index = lif->index,
437*2d9fd380Sjfb8856606 			.rx_mode = rx_mode,
438*2d9fd380Sjfb8856606 		},
439*2d9fd380Sjfb8856606 	};
440*2d9fd380Sjfb8856606 	int err;
441*2d9fd380Sjfb8856606 
442*2d9fd380Sjfb8856606 	if (rx_mode & IONIC_RX_MODE_F_UNICAST)
443*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_UNICAST");
444*2d9fd380Sjfb8856606 	if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
445*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_MULTICAST");
446*2d9fd380Sjfb8856606 	if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
447*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_BROADCAST");
448*2d9fd380Sjfb8856606 	if (rx_mode & IONIC_RX_MODE_F_PROMISC)
449*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_PROMISC");
450*2d9fd380Sjfb8856606 	if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
451*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "rx_mode IONIC_RX_MODE_F_ALLMULTI");
452*2d9fd380Sjfb8856606 
453*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
454*2d9fd380Sjfb8856606 	if (err)
455*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Failure setting RX mode");
456*2d9fd380Sjfb8856606 }
457*2d9fd380Sjfb8856606 
458*2d9fd380Sjfb8856606 static void
ionic_set_rx_mode(struct ionic_lif * lif,uint32_t rx_mode)459*2d9fd380Sjfb8856606 ionic_set_rx_mode(struct ionic_lif *lif, uint32_t rx_mode)
460*2d9fd380Sjfb8856606 {
461*2d9fd380Sjfb8856606 	if (lif->rx_mode != rx_mode) {
462*2d9fd380Sjfb8856606 		lif->rx_mode = rx_mode;
463*2d9fd380Sjfb8856606 		ionic_lif_rx_mode(lif, rx_mode);
464*2d9fd380Sjfb8856606 	}
465*2d9fd380Sjfb8856606 }
466*2d9fd380Sjfb8856606 
467*2d9fd380Sjfb8856606 int
ionic_dev_promiscuous_enable(struct rte_eth_dev * eth_dev)468*2d9fd380Sjfb8856606 ionic_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
469*2d9fd380Sjfb8856606 {
470*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
471*2d9fd380Sjfb8856606 	uint32_t rx_mode = lif->rx_mode;
472*2d9fd380Sjfb8856606 
473*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
474*2d9fd380Sjfb8856606 
475*2d9fd380Sjfb8856606 	rx_mode |= IONIC_RX_MODE_F_PROMISC;
476*2d9fd380Sjfb8856606 
477*2d9fd380Sjfb8856606 	ionic_set_rx_mode(lif, rx_mode);
478*2d9fd380Sjfb8856606 
479*2d9fd380Sjfb8856606 	return 0;
480*2d9fd380Sjfb8856606 }
481*2d9fd380Sjfb8856606 
482*2d9fd380Sjfb8856606 int
ionic_dev_promiscuous_disable(struct rte_eth_dev * eth_dev)483*2d9fd380Sjfb8856606 ionic_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
484*2d9fd380Sjfb8856606 {
485*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
486*2d9fd380Sjfb8856606 	uint32_t rx_mode = lif->rx_mode;
487*2d9fd380Sjfb8856606 
488*2d9fd380Sjfb8856606 	rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
489*2d9fd380Sjfb8856606 
490*2d9fd380Sjfb8856606 	ionic_set_rx_mode(lif, rx_mode);
491*2d9fd380Sjfb8856606 
492*2d9fd380Sjfb8856606 	return 0;
493*2d9fd380Sjfb8856606 }
494*2d9fd380Sjfb8856606 
495*2d9fd380Sjfb8856606 int
ionic_dev_allmulticast_enable(struct rte_eth_dev * eth_dev)496*2d9fd380Sjfb8856606 ionic_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
497*2d9fd380Sjfb8856606 {
498*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
499*2d9fd380Sjfb8856606 	uint32_t rx_mode = lif->rx_mode;
500*2d9fd380Sjfb8856606 
501*2d9fd380Sjfb8856606 	rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
502*2d9fd380Sjfb8856606 
503*2d9fd380Sjfb8856606 	ionic_set_rx_mode(lif, rx_mode);
504*2d9fd380Sjfb8856606 
505*2d9fd380Sjfb8856606 	return 0;
506*2d9fd380Sjfb8856606 }
507*2d9fd380Sjfb8856606 
508*2d9fd380Sjfb8856606 int
ionic_dev_allmulticast_disable(struct rte_eth_dev * eth_dev)509*2d9fd380Sjfb8856606 ionic_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
510*2d9fd380Sjfb8856606 {
511*2d9fd380Sjfb8856606 	struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
512*2d9fd380Sjfb8856606 	uint32_t rx_mode = lif->rx_mode;
513*2d9fd380Sjfb8856606 
514*2d9fd380Sjfb8856606 	rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
515*2d9fd380Sjfb8856606 
516*2d9fd380Sjfb8856606 	ionic_set_rx_mode(lif, rx_mode);
517*2d9fd380Sjfb8856606 
518*2d9fd380Sjfb8856606 	return 0;
519*2d9fd380Sjfb8856606 }
520*2d9fd380Sjfb8856606 
521*2d9fd380Sjfb8856606 int
ionic_lif_change_mtu(struct ionic_lif * lif,int new_mtu)522*2d9fd380Sjfb8856606 ionic_lif_change_mtu(struct ionic_lif *lif, int new_mtu)
523*2d9fd380Sjfb8856606 {
524*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
525*2d9fd380Sjfb8856606 		.pending_work = true,
526*2d9fd380Sjfb8856606 		.cmd.lif_setattr = {
527*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_LIF_SETATTR,
528*2d9fd380Sjfb8856606 			.index = lif->index,
529*2d9fd380Sjfb8856606 			.attr = IONIC_LIF_ATTR_MTU,
530*2d9fd380Sjfb8856606 			.mtu = new_mtu,
531*2d9fd380Sjfb8856606 		},
532*2d9fd380Sjfb8856606 	};
533*2d9fd380Sjfb8856606 	int err;
534*2d9fd380Sjfb8856606 
535*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
536*2d9fd380Sjfb8856606 	if (err)
537*2d9fd380Sjfb8856606 		return err;
538*2d9fd380Sjfb8856606 
539*2d9fd380Sjfb8856606 	lif->mtu = new_mtu;
540*2d9fd380Sjfb8856606 
541*2d9fd380Sjfb8856606 	return 0;
542*2d9fd380Sjfb8856606 }
543*2d9fd380Sjfb8856606 
544*2d9fd380Sjfb8856606 int
ionic_intr_alloc(struct ionic_lif * lif,struct ionic_intr_info * intr)545*2d9fd380Sjfb8856606 ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)
546*2d9fd380Sjfb8856606 {
547*2d9fd380Sjfb8856606 	struct ionic_adapter *adapter = lif->adapter;
548*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &adapter->idev;
549*2d9fd380Sjfb8856606 	unsigned long index;
550*2d9fd380Sjfb8856606 
551*2d9fd380Sjfb8856606 	/*
552*2d9fd380Sjfb8856606 	 * Note: interrupt handler is called for index = 0 only
553*2d9fd380Sjfb8856606 	 * (we use interrupts for the notifyq only anyway,
554*2d9fd380Sjfb8856606 	 * which hash index = 0)
555*2d9fd380Sjfb8856606 	 */
556*2d9fd380Sjfb8856606 
557*2d9fd380Sjfb8856606 	for (index = 0; index < adapter->nintrs; index++)
558*2d9fd380Sjfb8856606 		if (!adapter->intrs[index])
559*2d9fd380Sjfb8856606 			break;
560*2d9fd380Sjfb8856606 
561*2d9fd380Sjfb8856606 	if (index == adapter->nintrs)
562*2d9fd380Sjfb8856606 		return -ENOSPC;
563*2d9fd380Sjfb8856606 
564*2d9fd380Sjfb8856606 	adapter->intrs[index] = true;
565*2d9fd380Sjfb8856606 
566*2d9fd380Sjfb8856606 	ionic_intr_init(idev, intr, index);
567*2d9fd380Sjfb8856606 
568*2d9fd380Sjfb8856606 	return 0;
569*2d9fd380Sjfb8856606 }
570*2d9fd380Sjfb8856606 
571*2d9fd380Sjfb8856606 void
ionic_intr_free(struct ionic_lif * lif,struct ionic_intr_info * intr)572*2d9fd380Sjfb8856606 ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)
573*2d9fd380Sjfb8856606 {
574*2d9fd380Sjfb8856606 	if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)
575*2d9fd380Sjfb8856606 		lif->adapter->intrs[intr->index] = false;
576*2d9fd380Sjfb8856606 }
577*2d9fd380Sjfb8856606 
578*2d9fd380Sjfb8856606 static int
ionic_qcq_alloc(struct ionic_lif * lif,uint8_t type,uint32_t index,const char * base,uint32_t flags,uint32_t num_descs,uint32_t desc_size,uint32_t cq_desc_size,uint32_t sg_desc_size,uint32_t pid,struct ionic_qcq ** qcq)579*2d9fd380Sjfb8856606 ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,
580*2d9fd380Sjfb8856606 		uint32_t index,
581*2d9fd380Sjfb8856606 		const char *base, uint32_t flags,
582*2d9fd380Sjfb8856606 		uint32_t num_descs,
583*2d9fd380Sjfb8856606 		uint32_t desc_size,
584*2d9fd380Sjfb8856606 		uint32_t cq_desc_size,
585*2d9fd380Sjfb8856606 		uint32_t sg_desc_size,
586*2d9fd380Sjfb8856606 		uint32_t pid, struct ionic_qcq **qcq)
587*2d9fd380Sjfb8856606 {
588*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
589*2d9fd380Sjfb8856606 	struct ionic_qcq *new;
590*2d9fd380Sjfb8856606 	uint32_t q_size, cq_size, sg_size, total_size;
591*2d9fd380Sjfb8856606 	void *q_base, *cq_base, *sg_base;
592*2d9fd380Sjfb8856606 	rte_iova_t q_base_pa = 0;
593*2d9fd380Sjfb8856606 	rte_iova_t cq_base_pa = 0;
594*2d9fd380Sjfb8856606 	rte_iova_t sg_base_pa = 0;
595*2d9fd380Sjfb8856606 	uint32_t socket_id = rte_socket_id();
596*2d9fd380Sjfb8856606 	int err;
597*2d9fd380Sjfb8856606 
598*2d9fd380Sjfb8856606 	*qcq = NULL;
599*2d9fd380Sjfb8856606 
600*2d9fd380Sjfb8856606 	q_size  = num_descs * desc_size;
601*2d9fd380Sjfb8856606 	cq_size = num_descs * cq_desc_size;
602*2d9fd380Sjfb8856606 	sg_size = num_descs * sg_desc_size;
603*2d9fd380Sjfb8856606 
604*2d9fd380Sjfb8856606 	total_size = RTE_ALIGN(q_size, PAGE_SIZE) +
605*2d9fd380Sjfb8856606 		RTE_ALIGN(cq_size, PAGE_SIZE);
606*2d9fd380Sjfb8856606 	/*
607*2d9fd380Sjfb8856606 	 * Note: aligning q_size/cq_size is not enough due to cq_base address
608*2d9fd380Sjfb8856606 	 * aligning as q_base could be not aligned to the page.
609*2d9fd380Sjfb8856606 	 * Adding PAGE_SIZE.
610*2d9fd380Sjfb8856606 	 */
611*2d9fd380Sjfb8856606 	total_size += PAGE_SIZE;
612*2d9fd380Sjfb8856606 
613*2d9fd380Sjfb8856606 	if (flags & IONIC_QCQ_F_SG) {
614*2d9fd380Sjfb8856606 		total_size += RTE_ALIGN(sg_size, PAGE_SIZE);
615*2d9fd380Sjfb8856606 		total_size += PAGE_SIZE;
616*2d9fd380Sjfb8856606 	}
617*2d9fd380Sjfb8856606 
618*2d9fd380Sjfb8856606 	new = rte_zmalloc("ionic", sizeof(*new), 0);
619*2d9fd380Sjfb8856606 	if (!new) {
620*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate queue structure");
621*2d9fd380Sjfb8856606 		return -ENOMEM;
622*2d9fd380Sjfb8856606 	}
623*2d9fd380Sjfb8856606 
624*2d9fd380Sjfb8856606 	new->lif = lif;
625*2d9fd380Sjfb8856606 	new->flags = flags;
626*2d9fd380Sjfb8856606 
627*2d9fd380Sjfb8856606 	new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0);
628*2d9fd380Sjfb8856606 	if (!new->q.info) {
629*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate queue info");
630*2d9fd380Sjfb8856606 		return -ENOMEM;
631*2d9fd380Sjfb8856606 	}
632*2d9fd380Sjfb8856606 
633*2d9fd380Sjfb8856606 	new->q.type = type;
634*2d9fd380Sjfb8856606 
635*2d9fd380Sjfb8856606 	err = ionic_q_init(lif, idev, &new->q, index, num_descs,
636*2d9fd380Sjfb8856606 		desc_size, sg_desc_size, pid);
637*2d9fd380Sjfb8856606 	if (err) {
638*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Queue initialization failed");
639*2d9fd380Sjfb8856606 		return err;
640*2d9fd380Sjfb8856606 	}
641*2d9fd380Sjfb8856606 
642*2d9fd380Sjfb8856606 	if (flags & IONIC_QCQ_F_INTR) {
643*2d9fd380Sjfb8856606 		err = ionic_intr_alloc(lif, &new->intr);
644*2d9fd380Sjfb8856606 		if (err)
645*2d9fd380Sjfb8856606 			return err;
646*2d9fd380Sjfb8856606 
647*2d9fd380Sjfb8856606 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
648*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_SET);
649*2d9fd380Sjfb8856606 	} else {
650*2d9fd380Sjfb8856606 		new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;
651*2d9fd380Sjfb8856606 	}
652*2d9fd380Sjfb8856606 
653*2d9fd380Sjfb8856606 	err = ionic_cq_init(lif, &new->cq, &new->intr,
654*2d9fd380Sjfb8856606 		num_descs, cq_desc_size);
655*2d9fd380Sjfb8856606 	if (err) {
656*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Completion queue initialization failed");
657*2d9fd380Sjfb8856606 		goto err_out_free_intr;
658*2d9fd380Sjfb8856606 	}
659*2d9fd380Sjfb8856606 
660*2d9fd380Sjfb8856606 	new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,
661*2d9fd380Sjfb8856606 		base /* name */, index /* queue_idx */,
662*2d9fd380Sjfb8856606 		total_size, IONIC_ALIGN, socket_id);
663*2d9fd380Sjfb8856606 
664*2d9fd380Sjfb8856606 	if (!new->base_z) {
665*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot reserve queue DMA memory");
666*2d9fd380Sjfb8856606 		err = -ENOMEM;
667*2d9fd380Sjfb8856606 		goto err_out_free_intr;
668*2d9fd380Sjfb8856606 	}
669*2d9fd380Sjfb8856606 
670*2d9fd380Sjfb8856606 	new->base = new->base_z->addr;
671*2d9fd380Sjfb8856606 	new->base_pa = new->base_z->iova;
672*2d9fd380Sjfb8856606 	new->total_size = total_size;
673*2d9fd380Sjfb8856606 
674*2d9fd380Sjfb8856606 	q_base = new->base;
675*2d9fd380Sjfb8856606 	q_base_pa = new->base_pa;
676*2d9fd380Sjfb8856606 
677*2d9fd380Sjfb8856606 	cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);
678*2d9fd380Sjfb8856606 	cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);
679*2d9fd380Sjfb8856606 
680*2d9fd380Sjfb8856606 	if (flags & IONIC_QCQ_F_SG) {
681*2d9fd380Sjfb8856606 		sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,
682*2d9fd380Sjfb8856606 			PAGE_SIZE);
683*2d9fd380Sjfb8856606 		sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);
684*2d9fd380Sjfb8856606 		ionic_q_sg_map(&new->q, sg_base, sg_base_pa);
685*2d9fd380Sjfb8856606 	}
686*2d9fd380Sjfb8856606 
687*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Q-Base-PA = %ju CQ-Base-PA = %ju "
688*2d9fd380Sjfb8856606 		"SG-base-PA = %ju",
689*2d9fd380Sjfb8856606 		q_base_pa, cq_base_pa, sg_base_pa);
690*2d9fd380Sjfb8856606 
691*2d9fd380Sjfb8856606 	ionic_q_map(&new->q, q_base, q_base_pa);
692*2d9fd380Sjfb8856606 	ionic_cq_map(&new->cq, cq_base, cq_base_pa);
693*2d9fd380Sjfb8856606 	ionic_cq_bind(&new->cq, &new->q);
694*2d9fd380Sjfb8856606 
695*2d9fd380Sjfb8856606 	*qcq = new;
696*2d9fd380Sjfb8856606 
697*2d9fd380Sjfb8856606 	return 0;
698*2d9fd380Sjfb8856606 
699*2d9fd380Sjfb8856606 err_out_free_intr:
700*2d9fd380Sjfb8856606 	if (flags & IONIC_QCQ_F_INTR)
701*2d9fd380Sjfb8856606 		ionic_intr_free(lif, &new->intr);
702*2d9fd380Sjfb8856606 
703*2d9fd380Sjfb8856606 	return err;
704*2d9fd380Sjfb8856606 }
705*2d9fd380Sjfb8856606 
706*2d9fd380Sjfb8856606 void
ionic_qcq_free(struct ionic_qcq * qcq)707*2d9fd380Sjfb8856606 ionic_qcq_free(struct ionic_qcq *qcq)
708*2d9fd380Sjfb8856606 {
709*2d9fd380Sjfb8856606 	if (qcq->base_z) {
710*2d9fd380Sjfb8856606 		qcq->base = NULL;
711*2d9fd380Sjfb8856606 		qcq->base_pa = 0;
712*2d9fd380Sjfb8856606 		rte_memzone_free(qcq->base_z);
713*2d9fd380Sjfb8856606 		qcq->base_z = NULL;
714*2d9fd380Sjfb8856606 	}
715*2d9fd380Sjfb8856606 
716*2d9fd380Sjfb8856606 	if (qcq->q.info) {
717*2d9fd380Sjfb8856606 		rte_free(qcq->q.info);
718*2d9fd380Sjfb8856606 		qcq->q.info = NULL;
719*2d9fd380Sjfb8856606 	}
720*2d9fd380Sjfb8856606 
721*2d9fd380Sjfb8856606 	rte_free(qcq);
722*2d9fd380Sjfb8856606 }
723*2d9fd380Sjfb8856606 
724*2d9fd380Sjfb8856606 int
ionic_rx_qcq_alloc(struct ionic_lif * lif,uint32_t index,uint16_t nrxq_descs,struct ionic_qcq ** qcq)725*2d9fd380Sjfb8856606 ionic_rx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t nrxq_descs,
726*2d9fd380Sjfb8856606 		struct ionic_qcq **qcq)
727*2d9fd380Sjfb8856606 {
728*2d9fd380Sjfb8856606 	uint32_t flags;
729*2d9fd380Sjfb8856606 	int err = -ENOMEM;
730*2d9fd380Sjfb8856606 
731*2d9fd380Sjfb8856606 	flags = IONIC_QCQ_F_SG;
732*2d9fd380Sjfb8856606 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, index, "rx", flags,
733*2d9fd380Sjfb8856606 		nrxq_descs,
734*2d9fd380Sjfb8856606 		sizeof(struct ionic_rxq_desc),
735*2d9fd380Sjfb8856606 		sizeof(struct ionic_rxq_comp),
736*2d9fd380Sjfb8856606 		sizeof(struct ionic_rxq_sg_desc),
737*2d9fd380Sjfb8856606 		lif->kern_pid, &lif->rxqcqs[index]);
738*2d9fd380Sjfb8856606 	if (err)
739*2d9fd380Sjfb8856606 		return err;
740*2d9fd380Sjfb8856606 
741*2d9fd380Sjfb8856606 	*qcq = lif->rxqcqs[index];
742*2d9fd380Sjfb8856606 
743*2d9fd380Sjfb8856606 	return 0;
744*2d9fd380Sjfb8856606 }
745*2d9fd380Sjfb8856606 
746*2d9fd380Sjfb8856606 int
ionic_tx_qcq_alloc(struct ionic_lif * lif,uint32_t index,uint16_t ntxq_descs,struct ionic_qcq ** qcq)747*2d9fd380Sjfb8856606 ionic_tx_qcq_alloc(struct ionic_lif *lif, uint32_t index, uint16_t ntxq_descs,
748*2d9fd380Sjfb8856606 		struct ionic_qcq **qcq)
749*2d9fd380Sjfb8856606 {
750*2d9fd380Sjfb8856606 	uint32_t flags;
751*2d9fd380Sjfb8856606 	int err = -ENOMEM;
752*2d9fd380Sjfb8856606 
753*2d9fd380Sjfb8856606 	flags = IONIC_QCQ_F_SG;
754*2d9fd380Sjfb8856606 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, index, "tx", flags,
755*2d9fd380Sjfb8856606 		ntxq_descs,
756*2d9fd380Sjfb8856606 		sizeof(struct ionic_txq_desc),
757*2d9fd380Sjfb8856606 		sizeof(struct ionic_txq_comp),
758*2d9fd380Sjfb8856606 		sizeof(struct ionic_txq_sg_desc),
759*2d9fd380Sjfb8856606 		lif->kern_pid, &lif->txqcqs[index]);
760*2d9fd380Sjfb8856606 	if (err)
761*2d9fd380Sjfb8856606 		return err;
762*2d9fd380Sjfb8856606 
763*2d9fd380Sjfb8856606 	*qcq = lif->txqcqs[index];
764*2d9fd380Sjfb8856606 
765*2d9fd380Sjfb8856606 	return 0;
766*2d9fd380Sjfb8856606 }
767*2d9fd380Sjfb8856606 
768*2d9fd380Sjfb8856606 static int
ionic_admin_qcq_alloc(struct ionic_lif * lif)769*2d9fd380Sjfb8856606 ionic_admin_qcq_alloc(struct ionic_lif *lif)
770*2d9fd380Sjfb8856606 {
771*2d9fd380Sjfb8856606 	uint32_t flags;
772*2d9fd380Sjfb8856606 	int err = -ENOMEM;
773*2d9fd380Sjfb8856606 
774*2d9fd380Sjfb8856606 	flags = 0;
775*2d9fd380Sjfb8856606 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
776*2d9fd380Sjfb8856606 		IONIC_ADMINQ_LENGTH,
777*2d9fd380Sjfb8856606 		sizeof(struct ionic_admin_cmd),
778*2d9fd380Sjfb8856606 		sizeof(struct ionic_admin_comp),
779*2d9fd380Sjfb8856606 		0,
780*2d9fd380Sjfb8856606 		lif->kern_pid, &lif->adminqcq);
781*2d9fd380Sjfb8856606 	if (err)
782*2d9fd380Sjfb8856606 		return err;
783*2d9fd380Sjfb8856606 
784*2d9fd380Sjfb8856606 	return 0;
785*2d9fd380Sjfb8856606 }
786*2d9fd380Sjfb8856606 
787*2d9fd380Sjfb8856606 static int
ionic_notify_qcq_alloc(struct ionic_lif * lif)788*2d9fd380Sjfb8856606 ionic_notify_qcq_alloc(struct ionic_lif *lif)
789*2d9fd380Sjfb8856606 {
790*2d9fd380Sjfb8856606 	uint32_t flags;
791*2d9fd380Sjfb8856606 	int err = -ENOMEM;
792*2d9fd380Sjfb8856606 
793*2d9fd380Sjfb8856606 	flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR;
794*2d9fd380Sjfb8856606 
795*2d9fd380Sjfb8856606 	err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify",
796*2d9fd380Sjfb8856606 		flags,
797*2d9fd380Sjfb8856606 		IONIC_NOTIFYQ_LENGTH,
798*2d9fd380Sjfb8856606 		sizeof(struct ionic_notifyq_cmd),
799*2d9fd380Sjfb8856606 		sizeof(union ionic_notifyq_comp),
800*2d9fd380Sjfb8856606 		0,
801*2d9fd380Sjfb8856606 		lif->kern_pid, &lif->notifyqcq);
802*2d9fd380Sjfb8856606 	if (err)
803*2d9fd380Sjfb8856606 		return err;
804*2d9fd380Sjfb8856606 
805*2d9fd380Sjfb8856606 	return 0;
806*2d9fd380Sjfb8856606 }
807*2d9fd380Sjfb8856606 
808*2d9fd380Sjfb8856606 static void *
ionic_bus_map_dbpage(struct ionic_adapter * adapter,int page_num)809*2d9fd380Sjfb8856606 ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)
810*2d9fd380Sjfb8856606 {
811*2d9fd380Sjfb8856606 	char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr;
812*2d9fd380Sjfb8856606 
813*2d9fd380Sjfb8856606 	if (adapter->num_bars <= IONIC_PCI_BAR_DBELL)
814*2d9fd380Sjfb8856606 		return NULL;
815*2d9fd380Sjfb8856606 
816*2d9fd380Sjfb8856606 	return (void *)&vaddr[page_num << PAGE_SHIFT];
817*2d9fd380Sjfb8856606 }
818*2d9fd380Sjfb8856606 
819*2d9fd380Sjfb8856606 int
ionic_lif_alloc(struct ionic_lif * lif)820*2d9fd380Sjfb8856606 ionic_lif_alloc(struct ionic_lif *lif)
821*2d9fd380Sjfb8856606 {
822*2d9fd380Sjfb8856606 	struct ionic_adapter *adapter = lif->adapter;
823*2d9fd380Sjfb8856606 	uint32_t socket_id = rte_socket_id();
824*2d9fd380Sjfb8856606 	int dbpage_num;
825*2d9fd380Sjfb8856606 	int err;
826*2d9fd380Sjfb8856606 
827*2d9fd380Sjfb8856606 	snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index);
828*2d9fd380Sjfb8856606 
829*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
830*2d9fd380Sjfb8856606 
831*2d9fd380Sjfb8856606 	rte_spinlock_init(&lif->adminq_lock);
832*2d9fd380Sjfb8856606 	rte_spinlock_init(&lif->adminq_service_lock);
833*2d9fd380Sjfb8856606 
834*2d9fd380Sjfb8856606 	lif->kern_pid = 0;
835*2d9fd380Sjfb8856606 
836*2d9fd380Sjfb8856606 	dbpage_num = ionic_db_page_num(lif, 0);
837*2d9fd380Sjfb8856606 
838*2d9fd380Sjfb8856606 	lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num);
839*2d9fd380Sjfb8856606 	if (!lif->kern_dbpage) {
840*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot map dbpage, aborting");
841*2d9fd380Sjfb8856606 		return -ENOMEM;
842*2d9fd380Sjfb8856606 	}
843*2d9fd380Sjfb8856606 
844*2d9fd380Sjfb8856606 	lif->txqcqs = rte_zmalloc("ionic", sizeof(*lif->txqcqs) *
845*2d9fd380Sjfb8856606 		adapter->max_ntxqs_per_lif, 0);
846*2d9fd380Sjfb8856606 
847*2d9fd380Sjfb8856606 	if (!lif->txqcqs) {
848*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate tx queues array");
849*2d9fd380Sjfb8856606 		return -ENOMEM;
850*2d9fd380Sjfb8856606 	}
851*2d9fd380Sjfb8856606 
852*2d9fd380Sjfb8856606 	lif->rxqcqs = rte_zmalloc("ionic", sizeof(*lif->rxqcqs) *
853*2d9fd380Sjfb8856606 		adapter->max_nrxqs_per_lif, 0);
854*2d9fd380Sjfb8856606 
855*2d9fd380Sjfb8856606 	if (!lif->rxqcqs) {
856*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate rx queues array");
857*2d9fd380Sjfb8856606 		return -ENOMEM;
858*2d9fd380Sjfb8856606 	}
859*2d9fd380Sjfb8856606 
860*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Allocating Notify Queue");
861*2d9fd380Sjfb8856606 
862*2d9fd380Sjfb8856606 	err = ionic_notify_qcq_alloc(lif);
863*2d9fd380Sjfb8856606 	if (err) {
864*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate notify queue");
865*2d9fd380Sjfb8856606 		return err;
866*2d9fd380Sjfb8856606 	}
867*2d9fd380Sjfb8856606 
868*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
869*2d9fd380Sjfb8856606 
870*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Allocating Admin Queue");
871*2d9fd380Sjfb8856606 
872*2d9fd380Sjfb8856606 	err = ionic_admin_qcq_alloc(lif);
873*2d9fd380Sjfb8856606 	if (err) {
874*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate admin queue");
875*2d9fd380Sjfb8856606 		return err;
876*2d9fd380Sjfb8856606 	}
877*2d9fd380Sjfb8856606 
878*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Allocating Lif Info");
879*2d9fd380Sjfb8856606 
880*2d9fd380Sjfb8856606 	lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);
881*2d9fd380Sjfb8856606 
882*2d9fd380Sjfb8856606 	lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,
883*2d9fd380Sjfb8856606 		"lif_info", 0 /* queue_idx*/,
884*2d9fd380Sjfb8856606 		lif->info_sz, IONIC_ALIGN, socket_id);
885*2d9fd380Sjfb8856606 	if (!lif->info_z) {
886*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "Cannot allocate lif info memory");
887*2d9fd380Sjfb8856606 		return -ENOMEM;
888*2d9fd380Sjfb8856606 	}
889*2d9fd380Sjfb8856606 
890*2d9fd380Sjfb8856606 	lif->info = lif->info_z->addr;
891*2d9fd380Sjfb8856606 	lif->info_pa = lif->info_z->iova;
892*2d9fd380Sjfb8856606 
893*2d9fd380Sjfb8856606 	return 0;
894*2d9fd380Sjfb8856606 }
895*2d9fd380Sjfb8856606 
896*2d9fd380Sjfb8856606 void
ionic_lif_free(struct ionic_lif * lif)897*2d9fd380Sjfb8856606 ionic_lif_free(struct ionic_lif *lif)
898*2d9fd380Sjfb8856606 {
899*2d9fd380Sjfb8856606 	if (lif->notifyqcq) {
900*2d9fd380Sjfb8856606 		ionic_qcq_free(lif->notifyqcq);
901*2d9fd380Sjfb8856606 		lif->notifyqcq = NULL;
902*2d9fd380Sjfb8856606 	}
903*2d9fd380Sjfb8856606 
904*2d9fd380Sjfb8856606 	if (lif->adminqcq) {
905*2d9fd380Sjfb8856606 		ionic_qcq_free(lif->adminqcq);
906*2d9fd380Sjfb8856606 		lif->adminqcq = NULL;
907*2d9fd380Sjfb8856606 	}
908*2d9fd380Sjfb8856606 
909*2d9fd380Sjfb8856606 	if (lif->txqcqs) {
910*2d9fd380Sjfb8856606 		rte_free(lif->txqcqs);
911*2d9fd380Sjfb8856606 		lif->txqcqs = NULL;
912*2d9fd380Sjfb8856606 	}
913*2d9fd380Sjfb8856606 
914*2d9fd380Sjfb8856606 	if (lif->rxqcqs) {
915*2d9fd380Sjfb8856606 		rte_free(lif->rxqcqs);
916*2d9fd380Sjfb8856606 		lif->rxqcqs = NULL;
917*2d9fd380Sjfb8856606 	}
918*2d9fd380Sjfb8856606 
919*2d9fd380Sjfb8856606 	if (lif->info) {
920*2d9fd380Sjfb8856606 		rte_memzone_free(lif->info_z);
921*2d9fd380Sjfb8856606 		lif->info = NULL;
922*2d9fd380Sjfb8856606 	}
923*2d9fd380Sjfb8856606 }
924*2d9fd380Sjfb8856606 
925*2d9fd380Sjfb8856606 int
ionic_lif_rss_config(struct ionic_lif * lif,const uint16_t types,const uint8_t * key,const uint32_t * indir)926*2d9fd380Sjfb8856606 ionic_lif_rss_config(struct ionic_lif *lif,
927*2d9fd380Sjfb8856606 		const uint16_t types, const uint8_t *key, const uint32_t *indir)
928*2d9fd380Sjfb8856606 {
929*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
930*2d9fd380Sjfb8856606 		.pending_work = true,
931*2d9fd380Sjfb8856606 		.cmd.lif_setattr = {
932*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_LIF_SETATTR,
933*2d9fd380Sjfb8856606 			.attr = IONIC_LIF_ATTR_RSS,
934*2d9fd380Sjfb8856606 			.rss.types = types,
935*2d9fd380Sjfb8856606 			.rss.addr = lif->rss_ind_tbl_pa,
936*2d9fd380Sjfb8856606 		},
937*2d9fd380Sjfb8856606 	};
938*2d9fd380Sjfb8856606 	unsigned int i;
939*2d9fd380Sjfb8856606 
940*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
941*2d9fd380Sjfb8856606 
942*2d9fd380Sjfb8856606 	lif->rss_types = types;
943*2d9fd380Sjfb8856606 
944*2d9fd380Sjfb8856606 	if (key)
945*2d9fd380Sjfb8856606 		memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
946*2d9fd380Sjfb8856606 
947*2d9fd380Sjfb8856606 	if (indir)
948*2d9fd380Sjfb8856606 		for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
949*2d9fd380Sjfb8856606 			lif->rss_ind_tbl[i] = indir[i];
950*2d9fd380Sjfb8856606 
951*2d9fd380Sjfb8856606 	memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
952*2d9fd380Sjfb8856606 	       IONIC_RSS_HASH_KEY_SIZE);
953*2d9fd380Sjfb8856606 
954*2d9fd380Sjfb8856606 	return ionic_adminq_post_wait(lif, &ctx);
955*2d9fd380Sjfb8856606 }
956*2d9fd380Sjfb8856606 
957*2d9fd380Sjfb8856606 static int
ionic_lif_rss_setup(struct ionic_lif * lif)958*2d9fd380Sjfb8856606 ionic_lif_rss_setup(struct ionic_lif *lif)
959*2d9fd380Sjfb8856606 {
960*2d9fd380Sjfb8856606 	size_t tbl_size = sizeof(*lif->rss_ind_tbl) *
961*2d9fd380Sjfb8856606 		lif->adapter->ident.lif.eth.rss_ind_tbl_sz;
962*2d9fd380Sjfb8856606 	static const uint8_t toeplitz_symmetric_key[] = {
963*2d9fd380Sjfb8856606 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
964*2d9fd380Sjfb8856606 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
965*2d9fd380Sjfb8856606 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
966*2d9fd380Sjfb8856606 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
967*2d9fd380Sjfb8856606 		0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
968*2d9fd380Sjfb8856606 	};
969*2d9fd380Sjfb8856606 	uint32_t socket_id = rte_socket_id();
970*2d9fd380Sjfb8856606 	uint32_t i;
971*2d9fd380Sjfb8856606 	int err;
972*2d9fd380Sjfb8856606 
973*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
974*2d9fd380Sjfb8856606 
975*2d9fd380Sjfb8856606 	lif->rss_ind_tbl_z = rte_eth_dma_zone_reserve(lif->eth_dev,
976*2d9fd380Sjfb8856606 		"rss_ind_tbl",
977*2d9fd380Sjfb8856606 		0 /* queue_idx*/, tbl_size, IONIC_ALIGN, socket_id);
978*2d9fd380Sjfb8856606 
979*2d9fd380Sjfb8856606 	if (!lif->rss_ind_tbl_z) {
980*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "OOM");
981*2d9fd380Sjfb8856606 		return -ENOMEM;
982*2d9fd380Sjfb8856606 	}
983*2d9fd380Sjfb8856606 
984*2d9fd380Sjfb8856606 	lif->rss_ind_tbl = lif->rss_ind_tbl_z->addr;
985*2d9fd380Sjfb8856606 	lif->rss_ind_tbl_pa = lif->rss_ind_tbl_z->iova;
986*2d9fd380Sjfb8856606 
987*2d9fd380Sjfb8856606 	/* Fill indirection table with 'default' values */
988*2d9fd380Sjfb8856606 	for (i = 0; i < lif->adapter->ident.lif.eth.rss_ind_tbl_sz; i++)
989*2d9fd380Sjfb8856606 		lif->rss_ind_tbl[i] = i % lif->nrxqcqs;
990*2d9fd380Sjfb8856606 
991*2d9fd380Sjfb8856606 	err = ionic_lif_rss_config(lif, IONIC_RSS_OFFLOAD_ALL,
992*2d9fd380Sjfb8856606 		toeplitz_symmetric_key, NULL);
993*2d9fd380Sjfb8856606 	if (err)
994*2d9fd380Sjfb8856606 		return err;
995*2d9fd380Sjfb8856606 
996*2d9fd380Sjfb8856606 	return 0;
997*2d9fd380Sjfb8856606 }
998*2d9fd380Sjfb8856606 
999*2d9fd380Sjfb8856606 static void
ionic_lif_rss_teardown(struct ionic_lif * lif)1000*2d9fd380Sjfb8856606 ionic_lif_rss_teardown(struct ionic_lif *lif)
1001*2d9fd380Sjfb8856606 {
1002*2d9fd380Sjfb8856606 	if (!lif->rss_ind_tbl)
1003*2d9fd380Sjfb8856606 		return;
1004*2d9fd380Sjfb8856606 
1005*2d9fd380Sjfb8856606 	if (lif->rss_ind_tbl_z) {
1006*2d9fd380Sjfb8856606 		/* Disable RSS on the NIC */
1007*2d9fd380Sjfb8856606 		ionic_lif_rss_config(lif, 0x0, NULL, NULL);
1008*2d9fd380Sjfb8856606 
1009*2d9fd380Sjfb8856606 		lif->rss_ind_tbl = NULL;
1010*2d9fd380Sjfb8856606 		lif->rss_ind_tbl_pa = 0;
1011*2d9fd380Sjfb8856606 		rte_memzone_free(lif->rss_ind_tbl_z);
1012*2d9fd380Sjfb8856606 		lif->rss_ind_tbl_z = NULL;
1013*2d9fd380Sjfb8856606 	}
1014*2d9fd380Sjfb8856606 }
1015*2d9fd380Sjfb8856606 
1016*2d9fd380Sjfb8856606 static void
ionic_lif_qcq_deinit(struct ionic_lif * lif,struct ionic_qcq * qcq)1017*2d9fd380Sjfb8856606 ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
1018*2d9fd380Sjfb8856606 {
1019*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
1020*2d9fd380Sjfb8856606 
1021*2d9fd380Sjfb8856606 	if (!(qcq->flags & IONIC_QCQ_F_INITED))
1022*2d9fd380Sjfb8856606 		return;
1023*2d9fd380Sjfb8856606 
1024*2d9fd380Sjfb8856606 	if (qcq->flags & IONIC_QCQ_F_INTR)
1025*2d9fd380Sjfb8856606 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
1026*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_SET);
1027*2d9fd380Sjfb8856606 
1028*2d9fd380Sjfb8856606 	qcq->flags &= ~IONIC_QCQ_F_INITED;
1029*2d9fd380Sjfb8856606 }
1030*2d9fd380Sjfb8856606 
1031*2d9fd380Sjfb8856606 void
ionic_lif_txq_deinit(struct ionic_qcq * qcq)1032*2d9fd380Sjfb8856606 ionic_lif_txq_deinit(struct ionic_qcq *qcq)
1033*2d9fd380Sjfb8856606 {
1034*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1035*2d9fd380Sjfb8856606 }
1036*2d9fd380Sjfb8856606 
1037*2d9fd380Sjfb8856606 void
ionic_lif_rxq_deinit(struct ionic_qcq * qcq)1038*2d9fd380Sjfb8856606 ionic_lif_rxq_deinit(struct ionic_qcq *qcq)
1039*2d9fd380Sjfb8856606 {
1040*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(qcq->lif, qcq);
1041*2d9fd380Sjfb8856606 }
1042*2d9fd380Sjfb8856606 
1043*2d9fd380Sjfb8856606 bool
ionic_adminq_service(struct ionic_cq * cq,uint32_t cq_desc_index,void * cb_arg __rte_unused)1044*2d9fd380Sjfb8856606 ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,
1045*2d9fd380Sjfb8856606 		void *cb_arg __rte_unused)
1046*2d9fd380Sjfb8856606 {
1047*2d9fd380Sjfb8856606 	struct ionic_admin_comp *cq_desc_base = cq->base;
1048*2d9fd380Sjfb8856606 	struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];
1049*2d9fd380Sjfb8856606 
1050*2d9fd380Sjfb8856606 	if (!color_match(cq_desc->color, cq->done_color))
1051*2d9fd380Sjfb8856606 		return false;
1052*2d9fd380Sjfb8856606 
1053*2d9fd380Sjfb8856606 	ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);
1054*2d9fd380Sjfb8856606 
1055*2d9fd380Sjfb8856606 	return true;
1056*2d9fd380Sjfb8856606 }
1057*2d9fd380Sjfb8856606 
1058*2d9fd380Sjfb8856606 /* This acts like ionic_napi */
1059*2d9fd380Sjfb8856606 int
ionic_qcq_service(struct ionic_qcq * qcq,int budget,ionic_cq_cb cb,void * cb_arg)1060*2d9fd380Sjfb8856606 ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,
1061*2d9fd380Sjfb8856606 		void *cb_arg)
1062*2d9fd380Sjfb8856606 {
1063*2d9fd380Sjfb8856606 	struct ionic_cq *cq = &qcq->cq;
1064*2d9fd380Sjfb8856606 	uint32_t work_done;
1065*2d9fd380Sjfb8856606 
1066*2d9fd380Sjfb8856606 	work_done = ionic_cq_service(cq, budget, cb, cb_arg);
1067*2d9fd380Sjfb8856606 
1068*2d9fd380Sjfb8856606 	return work_done;
1069*2d9fd380Sjfb8856606 }
1070*2d9fd380Sjfb8856606 
1071*2d9fd380Sjfb8856606 static void
ionic_link_status_check(struct ionic_lif * lif)1072*2d9fd380Sjfb8856606 ionic_link_status_check(struct ionic_lif *lif)
1073*2d9fd380Sjfb8856606 {
1074*2d9fd380Sjfb8856606 	struct ionic_adapter *adapter = lif->adapter;
1075*2d9fd380Sjfb8856606 	bool link_up;
1076*2d9fd380Sjfb8856606 
1077*2d9fd380Sjfb8856606 	lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED;
1078*2d9fd380Sjfb8856606 
1079*2d9fd380Sjfb8856606 	if (!lif->info)
1080*2d9fd380Sjfb8856606 		return;
1081*2d9fd380Sjfb8856606 
1082*2d9fd380Sjfb8856606 	link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP);
1083*2d9fd380Sjfb8856606 
1084*2d9fd380Sjfb8856606 	if ((link_up  && adapter->link_up) ||
1085*2d9fd380Sjfb8856606 	    (!link_up && !adapter->link_up))
1086*2d9fd380Sjfb8856606 		return;
1087*2d9fd380Sjfb8856606 
1088*2d9fd380Sjfb8856606 	if (link_up) {
1089*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "Link up - %d Gbps",
1090*2d9fd380Sjfb8856606 			lif->info->status.link_speed);
1091*2d9fd380Sjfb8856606 		adapter->link_speed = lif->info->status.link_speed;
1092*2d9fd380Sjfb8856606 	} else {
1093*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "Link down");
1094*2d9fd380Sjfb8856606 	}
1095*2d9fd380Sjfb8856606 
1096*2d9fd380Sjfb8856606 	adapter->link_up = link_up;
1097*2d9fd380Sjfb8856606 }
1098*2d9fd380Sjfb8856606 
1099*2d9fd380Sjfb8856606 static bool
ionic_notifyq_cb(struct ionic_cq * cq,uint32_t cq_desc_index,void * cb_arg)1100*2d9fd380Sjfb8856606 ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg)
1101*2d9fd380Sjfb8856606 {
1102*2d9fd380Sjfb8856606 	union ionic_notifyq_comp *cq_desc_base = cq->base;
1103*2d9fd380Sjfb8856606 	union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index];
1104*2d9fd380Sjfb8856606 	struct ionic_lif *lif = cb_arg;
1105*2d9fd380Sjfb8856606 
1106*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d",
1107*2d9fd380Sjfb8856606 		cq_desc->event.eid, cq_desc->event.ecode);
1108*2d9fd380Sjfb8856606 
1109*2d9fd380Sjfb8856606 	/* Have we run out of new completions to process? */
1110*2d9fd380Sjfb8856606 	if (!(cq_desc->event.eid > lif->last_eid))
1111*2d9fd380Sjfb8856606 		return false;
1112*2d9fd380Sjfb8856606 
1113*2d9fd380Sjfb8856606 	lif->last_eid = cq_desc->event.eid;
1114*2d9fd380Sjfb8856606 
1115*2d9fd380Sjfb8856606 	switch (cq_desc->event.ecode) {
1116*2d9fd380Sjfb8856606 	case IONIC_EVENT_LINK_CHANGE:
1117*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG,
1118*2d9fd380Sjfb8856606 			"Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d",
1119*2d9fd380Sjfb8856606 			cq_desc->event.eid,
1120*2d9fd380Sjfb8856606 			cq_desc->link_change.link_status,
1121*2d9fd380Sjfb8856606 			cq_desc->link_change.link_speed);
1122*2d9fd380Sjfb8856606 
1123*2d9fd380Sjfb8856606 		lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED;
1124*2d9fd380Sjfb8856606 
1125*2d9fd380Sjfb8856606 		break;
1126*2d9fd380Sjfb8856606 	default:
1127*2d9fd380Sjfb8856606 		IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd",
1128*2d9fd380Sjfb8856606 			cq_desc->event.ecode, cq_desc->event.eid);
1129*2d9fd380Sjfb8856606 		break;
1130*2d9fd380Sjfb8856606 	}
1131*2d9fd380Sjfb8856606 
1132*2d9fd380Sjfb8856606 	return true;
1133*2d9fd380Sjfb8856606 }
1134*2d9fd380Sjfb8856606 
1135*2d9fd380Sjfb8856606 int
ionic_notifyq_handler(struct ionic_lif * lif,int budget)1136*2d9fd380Sjfb8856606 ionic_notifyq_handler(struct ionic_lif *lif, int budget)
1137*2d9fd380Sjfb8856606 {
1138*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
1139*2d9fd380Sjfb8856606 	struct ionic_qcq *qcq = lif->notifyqcq;
1140*2d9fd380Sjfb8856606 	uint32_t work_done;
1141*2d9fd380Sjfb8856606 
1142*2d9fd380Sjfb8856606 	if (!(qcq->flags & IONIC_QCQ_F_INITED)) {
1143*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "Notifyq not yet initialized");
1144*2d9fd380Sjfb8856606 		return -1;
1145*2d9fd380Sjfb8856606 	}
1146*2d9fd380Sjfb8856606 
1147*2d9fd380Sjfb8856606 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
1148*2d9fd380Sjfb8856606 		IONIC_INTR_MASK_SET);
1149*2d9fd380Sjfb8856606 
1150*2d9fd380Sjfb8856606 	work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif);
1151*2d9fd380Sjfb8856606 
1152*2d9fd380Sjfb8856606 	if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED)
1153*2d9fd380Sjfb8856606 		ionic_link_status_check(lif);
1154*2d9fd380Sjfb8856606 
1155*2d9fd380Sjfb8856606 	ionic_intr_credits(idev->intr_ctrl, qcq->intr.index,
1156*2d9fd380Sjfb8856606 		work_done, IONIC_INTR_CRED_RESET_COALESCE);
1157*2d9fd380Sjfb8856606 
1158*2d9fd380Sjfb8856606 	ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
1159*2d9fd380Sjfb8856606 		IONIC_INTR_MASK_CLEAR);
1160*2d9fd380Sjfb8856606 
1161*2d9fd380Sjfb8856606 	return 0;
1162*2d9fd380Sjfb8856606 }
1163*2d9fd380Sjfb8856606 
1164*2d9fd380Sjfb8856606 static int
ionic_lif_adminq_init(struct ionic_lif * lif)1165*2d9fd380Sjfb8856606 ionic_lif_adminq_init(struct ionic_lif *lif)
1166*2d9fd380Sjfb8856606 {
1167*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
1168*2d9fd380Sjfb8856606 	struct ionic_qcq *qcq = lif->adminqcq;
1169*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
1170*2d9fd380Sjfb8856606 	struct ionic_q_init_comp comp;
1171*2d9fd380Sjfb8856606 	int err;
1172*2d9fd380Sjfb8856606 
1173*2d9fd380Sjfb8856606 	ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);
1174*2d9fd380Sjfb8856606 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1175*2d9fd380Sjfb8856606 	if (err)
1176*2d9fd380Sjfb8856606 		return err;
1177*2d9fd380Sjfb8856606 
1178*2d9fd380Sjfb8856606 	ionic_dev_cmd_comp(idev, &comp);
1179*2d9fd380Sjfb8856606 
1180*2d9fd380Sjfb8856606 	q->hw_type = comp.hw_type;
1181*2d9fd380Sjfb8856606 	q->hw_index = comp.hw_index;
1182*2d9fd380Sjfb8856606 	q->db = ionic_db_map(lif, q);
1183*2d9fd380Sjfb8856606 
1184*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type);
1185*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index);
1186*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "adminq->db %p", q->db);
1187*2d9fd380Sjfb8856606 
1188*2d9fd380Sjfb8856606 	if (qcq->flags & IONIC_QCQ_F_INTR)
1189*2d9fd380Sjfb8856606 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
1190*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_CLEAR);
1191*2d9fd380Sjfb8856606 
1192*2d9fd380Sjfb8856606 	qcq->flags |= IONIC_QCQ_F_INITED;
1193*2d9fd380Sjfb8856606 
1194*2d9fd380Sjfb8856606 	return 0;
1195*2d9fd380Sjfb8856606 }
1196*2d9fd380Sjfb8856606 
1197*2d9fd380Sjfb8856606 static int
ionic_lif_notifyq_init(struct ionic_lif * lif)1198*2d9fd380Sjfb8856606 ionic_lif_notifyq_init(struct ionic_lif *lif)
1199*2d9fd380Sjfb8856606 {
1200*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
1201*2d9fd380Sjfb8856606 	struct ionic_qcq *qcq = lif->notifyqcq;
1202*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
1203*2d9fd380Sjfb8856606 	int err;
1204*2d9fd380Sjfb8856606 
1205*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1206*2d9fd380Sjfb8856606 		.pending_work = true,
1207*2d9fd380Sjfb8856606 		.cmd.q_init = {
1208*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_Q_INIT,
1209*2d9fd380Sjfb8856606 			.lif_index = lif->index,
1210*2d9fd380Sjfb8856606 			.type = q->type,
1211*2d9fd380Sjfb8856606 			.index = q->index,
1212*2d9fd380Sjfb8856606 			.flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA),
1213*2d9fd380Sjfb8856606 			.intr_index = qcq->intr.index,
1214*2d9fd380Sjfb8856606 			.pid = q->pid,
1215*2d9fd380Sjfb8856606 			.ring_size = rte_log2_u32(q->num_descs),
1216*2d9fd380Sjfb8856606 			.ring_base = q->base_pa,
1217*2d9fd380Sjfb8856606 		}
1218*2d9fd380Sjfb8856606 	};
1219*2d9fd380Sjfb8856606 
1220*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq_init.pid %d", ctx.cmd.q_init.pid);
1221*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq_init.index %d",
1222*2d9fd380Sjfb8856606 		ctx.cmd.q_init.index);
1223*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "",
1224*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_base);
1225*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d",
1226*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_size);
1227*2d9fd380Sjfb8856606 
1228*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
1229*2d9fd380Sjfb8856606 	if (err)
1230*2d9fd380Sjfb8856606 		return err;
1231*2d9fd380Sjfb8856606 
1232*2d9fd380Sjfb8856606 	q->hw_type = ctx.comp.q_init.hw_type;
1233*2d9fd380Sjfb8856606 	q->hw_index = ctx.comp.q_init.hw_index;
1234*2d9fd380Sjfb8856606 	q->db = NULL;
1235*2d9fd380Sjfb8856606 
1236*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type);
1237*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index);
1238*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "notifyq->db %p", q->db);
1239*2d9fd380Sjfb8856606 
1240*2d9fd380Sjfb8856606 	if (qcq->flags & IONIC_QCQ_F_INTR)
1241*2d9fd380Sjfb8856606 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
1242*2d9fd380Sjfb8856606 			IONIC_INTR_MASK_CLEAR);
1243*2d9fd380Sjfb8856606 
1244*2d9fd380Sjfb8856606 	qcq->flags |= IONIC_QCQ_F_INITED;
1245*2d9fd380Sjfb8856606 
1246*2d9fd380Sjfb8856606 	return 0;
1247*2d9fd380Sjfb8856606 }
1248*2d9fd380Sjfb8856606 
1249*2d9fd380Sjfb8856606 int
ionic_lif_set_features(struct ionic_lif * lif)1250*2d9fd380Sjfb8856606 ionic_lif_set_features(struct ionic_lif *lif)
1251*2d9fd380Sjfb8856606 {
1252*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1253*2d9fd380Sjfb8856606 		.pending_work = true,
1254*2d9fd380Sjfb8856606 		.cmd.lif_setattr = {
1255*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_LIF_SETATTR,
1256*2d9fd380Sjfb8856606 			.index = lif->index,
1257*2d9fd380Sjfb8856606 			.attr = IONIC_LIF_ATTR_FEATURES,
1258*2d9fd380Sjfb8856606 			.features = lif->features,
1259*2d9fd380Sjfb8856606 		},
1260*2d9fd380Sjfb8856606 	};
1261*2d9fd380Sjfb8856606 	int err;
1262*2d9fd380Sjfb8856606 
1263*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
1264*2d9fd380Sjfb8856606 	if (err)
1265*2d9fd380Sjfb8856606 		return err;
1266*2d9fd380Sjfb8856606 
1267*2d9fd380Sjfb8856606 	lif->hw_features = (ctx.cmd.lif_setattr.features &
1268*2d9fd380Sjfb8856606 		ctx.comp.lif_setattr.features);
1269*2d9fd380Sjfb8856606 
1270*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_VLAN_TX_TAG)
1271*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_TX_TAG");
1272*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_STRIP)
1273*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_STRIP");
1274*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_VLAN_RX_FILTER)
1275*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_VLAN_RX_FILTER");
1276*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_RX_HASH)
1277*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_HASH");
1278*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TX_SG)
1279*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_SG");
1280*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_RX_SG)
1281*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_SG");
1282*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TX_CSUM)
1283*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TX_CSUM");
1284*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_RX_CSUM)
1285*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_RX_CSUM");
1286*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO)
1287*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO");
1288*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPV6)
1289*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPV6");
1290*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_ECN)
1291*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_ECN");
1292*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE)
1293*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE");
1294*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_GRE_CSUM)
1295*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_GRE_CSUM");
1296*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP4)
1297*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP4");
1298*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_IPXIP6)
1299*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_IPXIP6");
1300*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP)
1301*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP");
1302*2d9fd380Sjfb8856606 	if (lif->hw_features & IONIC_ETH_HW_TSO_UDP_CSUM)
1303*2d9fd380Sjfb8856606 		IONIC_PRINT(DEBUG, "feature IONIC_ETH_HW_TSO_UDP_CSUM");
1304*2d9fd380Sjfb8856606 
1305*2d9fd380Sjfb8856606 	return 0;
1306*2d9fd380Sjfb8856606 }
1307*2d9fd380Sjfb8856606 
1308*2d9fd380Sjfb8856606 int
ionic_lif_txq_init(struct ionic_qcq * qcq)1309*2d9fd380Sjfb8856606 ionic_lif_txq_init(struct ionic_qcq *qcq)
1310*2d9fd380Sjfb8856606 {
1311*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
1312*2d9fd380Sjfb8856606 	struct ionic_lif *lif = qcq->lif;
1313*2d9fd380Sjfb8856606 	struct ionic_cq *cq = &qcq->cq;
1314*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1315*2d9fd380Sjfb8856606 		.pending_work = true,
1316*2d9fd380Sjfb8856606 		.cmd.q_init = {
1317*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_Q_INIT,
1318*2d9fd380Sjfb8856606 			.lif_index = lif->index,
1319*2d9fd380Sjfb8856606 			.type = q->type,
1320*2d9fd380Sjfb8856606 			.index = q->index,
1321*2d9fd380Sjfb8856606 			.flags = IONIC_QINIT_F_SG,
1322*2d9fd380Sjfb8856606 			.intr_index = cq->bound_intr->index,
1323*2d9fd380Sjfb8856606 			.pid = q->pid,
1324*2d9fd380Sjfb8856606 			.ring_size = rte_log2_u32(q->num_descs),
1325*2d9fd380Sjfb8856606 			.ring_base = q->base_pa,
1326*2d9fd380Sjfb8856606 			.cq_ring_base = cq->base_pa,
1327*2d9fd380Sjfb8856606 			.sg_ring_base = q->sg_base_pa,
1328*2d9fd380Sjfb8856606 		},
1329*2d9fd380Sjfb8856606 	};
1330*2d9fd380Sjfb8856606 	int err;
1331*2d9fd380Sjfb8856606 
1332*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq_init.pid %d", ctx.cmd.q_init.pid);
1333*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq_init.index %d", ctx.cmd.q_init.index);
1334*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq_init.ring_base 0x%" PRIx64 "",
1335*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_base);
1336*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq_init.ring_size %d",
1337*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_size);
1338*2d9fd380Sjfb8856606 
1339*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1340*2d9fd380Sjfb8856606 	if (err)
1341*2d9fd380Sjfb8856606 		return err;
1342*2d9fd380Sjfb8856606 
1343*2d9fd380Sjfb8856606 	q->hw_type = ctx.comp.q_init.hw_type;
1344*2d9fd380Sjfb8856606 	q->hw_index = ctx.comp.q_init.hw_index;
1345*2d9fd380Sjfb8856606 	q->db = ionic_db_map(lif, q);
1346*2d9fd380Sjfb8856606 
1347*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq->hw_type %d", q->hw_type);
1348*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq->hw_index %d", q->hw_index);
1349*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "txq->db %p", q->db);
1350*2d9fd380Sjfb8856606 
1351*2d9fd380Sjfb8856606 	qcq->flags |= IONIC_QCQ_F_INITED;
1352*2d9fd380Sjfb8856606 
1353*2d9fd380Sjfb8856606 	return 0;
1354*2d9fd380Sjfb8856606 }
1355*2d9fd380Sjfb8856606 
1356*2d9fd380Sjfb8856606 int
ionic_lif_rxq_init(struct ionic_qcq * qcq)1357*2d9fd380Sjfb8856606 ionic_lif_rxq_init(struct ionic_qcq *qcq)
1358*2d9fd380Sjfb8856606 {
1359*2d9fd380Sjfb8856606 	struct ionic_queue *q = &qcq->q;
1360*2d9fd380Sjfb8856606 	struct ionic_lif *lif = qcq->lif;
1361*2d9fd380Sjfb8856606 	struct ionic_cq *cq = &qcq->cq;
1362*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1363*2d9fd380Sjfb8856606 		.pending_work = true,
1364*2d9fd380Sjfb8856606 		.cmd.q_init = {
1365*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_Q_INIT,
1366*2d9fd380Sjfb8856606 			.lif_index = lif->index,
1367*2d9fd380Sjfb8856606 			.type = q->type,
1368*2d9fd380Sjfb8856606 			.index = q->index,
1369*2d9fd380Sjfb8856606 			.flags = IONIC_QINIT_F_SG,
1370*2d9fd380Sjfb8856606 			.intr_index = cq->bound_intr->index,
1371*2d9fd380Sjfb8856606 			.pid = q->pid,
1372*2d9fd380Sjfb8856606 			.ring_size = rte_log2_u32(q->num_descs),
1373*2d9fd380Sjfb8856606 			.ring_base = q->base_pa,
1374*2d9fd380Sjfb8856606 			.cq_ring_base = cq->base_pa,
1375*2d9fd380Sjfb8856606 			.sg_ring_base = q->sg_base_pa,
1376*2d9fd380Sjfb8856606 		},
1377*2d9fd380Sjfb8856606 	};
1378*2d9fd380Sjfb8856606 	int err;
1379*2d9fd380Sjfb8856606 
1380*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq_init.pid %d", ctx.cmd.q_init.pid);
1381*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq_init.index %d", ctx.cmd.q_init.index);
1382*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq_init.ring_base 0x%" PRIx64 "",
1383*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_base);
1384*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq_init.ring_size %d",
1385*2d9fd380Sjfb8856606 		ctx.cmd.q_init.ring_size);
1386*2d9fd380Sjfb8856606 
1387*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(qcq->lif, &ctx);
1388*2d9fd380Sjfb8856606 	if (err)
1389*2d9fd380Sjfb8856606 		return err;
1390*2d9fd380Sjfb8856606 
1391*2d9fd380Sjfb8856606 	q->hw_type = ctx.comp.q_init.hw_type;
1392*2d9fd380Sjfb8856606 	q->hw_index = ctx.comp.q_init.hw_index;
1393*2d9fd380Sjfb8856606 	q->db = ionic_db_map(lif, q);
1394*2d9fd380Sjfb8856606 
1395*2d9fd380Sjfb8856606 	qcq->flags |= IONIC_QCQ_F_INITED;
1396*2d9fd380Sjfb8856606 
1397*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq->hw_type %d", q->hw_type);
1398*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq->hw_index %d", q->hw_index);
1399*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "rxq->db %p", q->db);
1400*2d9fd380Sjfb8856606 
1401*2d9fd380Sjfb8856606 	return 0;
1402*2d9fd380Sjfb8856606 }
1403*2d9fd380Sjfb8856606 
1404*2d9fd380Sjfb8856606 static int
ionic_station_set(struct ionic_lif * lif)1405*2d9fd380Sjfb8856606 ionic_station_set(struct ionic_lif *lif)
1406*2d9fd380Sjfb8856606 {
1407*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1408*2d9fd380Sjfb8856606 		.pending_work = true,
1409*2d9fd380Sjfb8856606 		.cmd.lif_getattr = {
1410*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_LIF_GETATTR,
1411*2d9fd380Sjfb8856606 			.index = lif->index,
1412*2d9fd380Sjfb8856606 			.attr = IONIC_LIF_ATTR_MAC,
1413*2d9fd380Sjfb8856606 		},
1414*2d9fd380Sjfb8856606 	};
1415*2d9fd380Sjfb8856606 	int err;
1416*2d9fd380Sjfb8856606 
1417*2d9fd380Sjfb8856606 	IONIC_PRINT_CALL();
1418*2d9fd380Sjfb8856606 
1419*2d9fd380Sjfb8856606 	err = ionic_adminq_post_wait(lif, &ctx);
1420*2d9fd380Sjfb8856606 	if (err)
1421*2d9fd380Sjfb8856606 		return err;
1422*2d9fd380Sjfb8856606 
1423*2d9fd380Sjfb8856606 	if (!rte_is_zero_ether_addr((struct rte_ether_addr *)
1424*2d9fd380Sjfb8856606 			lif->mac_addr)) {
1425*2d9fd380Sjfb8856606 		IONIC_PRINT(INFO, "deleting station MAC addr");
1426*2d9fd380Sjfb8856606 
1427*2d9fd380Sjfb8856606 		ionic_lif_addr_del(lif, lif->mac_addr);
1428*2d9fd380Sjfb8856606 	}
1429*2d9fd380Sjfb8856606 
1430*2d9fd380Sjfb8856606 	memcpy(lif->mac_addr, ctx.comp.lif_getattr.mac, RTE_ETHER_ADDR_LEN);
1431*2d9fd380Sjfb8856606 
1432*2d9fd380Sjfb8856606 	if (rte_is_zero_ether_addr((struct rte_ether_addr *)lif->mac_addr)) {
1433*2d9fd380Sjfb8856606 		IONIC_PRINT(NOTICE, "empty MAC addr (VF?)");
1434*2d9fd380Sjfb8856606 		return 0;
1435*2d9fd380Sjfb8856606 	}
1436*2d9fd380Sjfb8856606 
1437*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "adding station MAC addr");
1438*2d9fd380Sjfb8856606 
1439*2d9fd380Sjfb8856606 	ionic_lif_addr_add(lif, lif->mac_addr);
1440*2d9fd380Sjfb8856606 
1441*2d9fd380Sjfb8856606 	return 0;
1442*2d9fd380Sjfb8856606 }
1443*2d9fd380Sjfb8856606 
1444*2d9fd380Sjfb8856606 static void
ionic_lif_set_name(struct ionic_lif * lif)1445*2d9fd380Sjfb8856606 ionic_lif_set_name(struct ionic_lif *lif)
1446*2d9fd380Sjfb8856606 {
1447*2d9fd380Sjfb8856606 	struct ionic_admin_ctx ctx = {
1448*2d9fd380Sjfb8856606 		.pending_work = true,
1449*2d9fd380Sjfb8856606 		.cmd.lif_setattr = {
1450*2d9fd380Sjfb8856606 			.opcode = IONIC_CMD_LIF_SETATTR,
1451*2d9fd380Sjfb8856606 			.index = lif->index,
1452*2d9fd380Sjfb8856606 			.attr = IONIC_LIF_ATTR_NAME,
1453*2d9fd380Sjfb8856606 		},
1454*2d9fd380Sjfb8856606 	};
1455*2d9fd380Sjfb8856606 
1456*2d9fd380Sjfb8856606 	snprintf(ctx.cmd.lif_setattr.name, sizeof(ctx.cmd.lif_setattr.name),
1457*2d9fd380Sjfb8856606 		"%d", lif->port_id);
1458*2d9fd380Sjfb8856606 
1459*2d9fd380Sjfb8856606 	ionic_adminq_post_wait(lif, &ctx);
1460*2d9fd380Sjfb8856606 }
1461*2d9fd380Sjfb8856606 
1462*2d9fd380Sjfb8856606 int
ionic_lif_init(struct ionic_lif * lif)1463*2d9fd380Sjfb8856606 ionic_lif_init(struct ionic_lif *lif)
1464*2d9fd380Sjfb8856606 {
1465*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &lif->adapter->idev;
1466*2d9fd380Sjfb8856606 	struct ionic_q_init_comp comp;
1467*2d9fd380Sjfb8856606 	int err;
1468*2d9fd380Sjfb8856606 
1469*2d9fd380Sjfb8856606 	memset(&lif->stats_base, 0, sizeof(lif->stats_base));
1470*2d9fd380Sjfb8856606 
1471*2d9fd380Sjfb8856606 	ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);
1472*2d9fd380Sjfb8856606 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1473*2d9fd380Sjfb8856606 	ionic_dev_cmd_comp(idev, &comp);
1474*2d9fd380Sjfb8856606 	if (err)
1475*2d9fd380Sjfb8856606 		return err;
1476*2d9fd380Sjfb8856606 
1477*2d9fd380Sjfb8856606 	lif->hw_index = comp.hw_index;
1478*2d9fd380Sjfb8856606 
1479*2d9fd380Sjfb8856606 	err = ionic_lif_adminq_init(lif);
1480*2d9fd380Sjfb8856606 	if (err)
1481*2d9fd380Sjfb8856606 		return err;
1482*2d9fd380Sjfb8856606 
1483*2d9fd380Sjfb8856606 	err = ionic_lif_notifyq_init(lif);
1484*2d9fd380Sjfb8856606 	if (err)
1485*2d9fd380Sjfb8856606 		goto err_out_adminq_deinit;
1486*2d9fd380Sjfb8856606 
1487*2d9fd380Sjfb8856606 	lif->features =
1488*2d9fd380Sjfb8856606 		  IONIC_ETH_HW_VLAN_TX_TAG
1489*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_VLAN_RX_STRIP
1490*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_VLAN_RX_FILTER
1491*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_RX_HASH
1492*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_TX_SG
1493*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_RX_SG
1494*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_TX_CSUM
1495*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_RX_CSUM
1496*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_TSO
1497*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_TSO_IPV6
1498*2d9fd380Sjfb8856606 		| IONIC_ETH_HW_TSO_ECN;
1499*2d9fd380Sjfb8856606 
1500*2d9fd380Sjfb8856606 	err = ionic_lif_set_features(lif);
1501*2d9fd380Sjfb8856606 	if (err)
1502*2d9fd380Sjfb8856606 		goto err_out_notifyq_deinit;
1503*2d9fd380Sjfb8856606 
1504*2d9fd380Sjfb8856606 	err = ionic_rx_filters_init(lif);
1505*2d9fd380Sjfb8856606 	if (err)
1506*2d9fd380Sjfb8856606 		goto err_out_notifyq_deinit;
1507*2d9fd380Sjfb8856606 
1508*2d9fd380Sjfb8856606 	err = ionic_station_set(lif);
1509*2d9fd380Sjfb8856606 	if (err)
1510*2d9fd380Sjfb8856606 		goto err_out_rx_filter_deinit;
1511*2d9fd380Sjfb8856606 
1512*2d9fd380Sjfb8856606 	ionic_lif_set_name(lif);
1513*2d9fd380Sjfb8856606 
1514*2d9fd380Sjfb8856606 	lif->state |= IONIC_LIF_F_INITED;
1515*2d9fd380Sjfb8856606 
1516*2d9fd380Sjfb8856606 	return 0;
1517*2d9fd380Sjfb8856606 
1518*2d9fd380Sjfb8856606 err_out_rx_filter_deinit:
1519*2d9fd380Sjfb8856606 	ionic_rx_filters_deinit(lif);
1520*2d9fd380Sjfb8856606 
1521*2d9fd380Sjfb8856606 err_out_notifyq_deinit:
1522*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1523*2d9fd380Sjfb8856606 
1524*2d9fd380Sjfb8856606 err_out_adminq_deinit:
1525*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
1526*2d9fd380Sjfb8856606 
1527*2d9fd380Sjfb8856606 	return err;
1528*2d9fd380Sjfb8856606 }
1529*2d9fd380Sjfb8856606 
1530*2d9fd380Sjfb8856606 void
ionic_lif_deinit(struct ionic_lif * lif)1531*2d9fd380Sjfb8856606 ionic_lif_deinit(struct ionic_lif *lif)
1532*2d9fd380Sjfb8856606 {
1533*2d9fd380Sjfb8856606 	if (!(lif->state & IONIC_LIF_F_INITED))
1534*2d9fd380Sjfb8856606 		return;
1535*2d9fd380Sjfb8856606 
1536*2d9fd380Sjfb8856606 	ionic_rx_filters_deinit(lif);
1537*2d9fd380Sjfb8856606 	ionic_lif_rss_teardown(lif);
1538*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(lif, lif->notifyqcq);
1539*2d9fd380Sjfb8856606 	ionic_lif_qcq_deinit(lif, lif->adminqcq);
1540*2d9fd380Sjfb8856606 
1541*2d9fd380Sjfb8856606 	lif->state &= ~IONIC_LIF_F_INITED;
1542*2d9fd380Sjfb8856606 }
1543*2d9fd380Sjfb8856606 
1544*2d9fd380Sjfb8856606 int
ionic_lif_configure(struct ionic_lif * lif)1545*2d9fd380Sjfb8856606 ionic_lif_configure(struct ionic_lif *lif)
1546*2d9fd380Sjfb8856606 {
1547*2d9fd380Sjfb8856606 	struct ionic_identity *ident = &lif->adapter->ident;
1548*2d9fd380Sjfb8856606 	uint32_t ntxqs_per_lif =
1549*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1550*2d9fd380Sjfb8856606 	uint32_t nrxqs_per_lif =
1551*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1552*2d9fd380Sjfb8856606 	uint32_t nrxqs = lif->eth_dev->data->nb_rx_queues;
1553*2d9fd380Sjfb8856606 	uint32_t ntxqs = lif->eth_dev->data->nb_tx_queues;
1554*2d9fd380Sjfb8856606 
1555*2d9fd380Sjfb8856606 	lif->port_id = lif->eth_dev->data->port_id;
1556*2d9fd380Sjfb8856606 
1557*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Configuring LIF on port %u",
1558*2d9fd380Sjfb8856606 		lif->port_id);
1559*2d9fd380Sjfb8856606 
1560*2d9fd380Sjfb8856606 	if (nrxqs > 0)
1561*2d9fd380Sjfb8856606 		nrxqs_per_lif = RTE_MIN(nrxqs_per_lif, nrxqs);
1562*2d9fd380Sjfb8856606 
1563*2d9fd380Sjfb8856606 	if (ntxqs > 0)
1564*2d9fd380Sjfb8856606 		ntxqs_per_lif = RTE_MIN(ntxqs_per_lif, ntxqs);
1565*2d9fd380Sjfb8856606 
1566*2d9fd380Sjfb8856606 	lif->nrxqcqs = nrxqs_per_lif;
1567*2d9fd380Sjfb8856606 	lif->ntxqcqs = ntxqs_per_lif;
1568*2d9fd380Sjfb8856606 
1569*2d9fd380Sjfb8856606 	return 0;
1570*2d9fd380Sjfb8856606 }
1571*2d9fd380Sjfb8856606 
1572*2d9fd380Sjfb8856606 int
ionic_lif_start(struct ionic_lif * lif)1573*2d9fd380Sjfb8856606 ionic_lif_start(struct ionic_lif *lif)
1574*2d9fd380Sjfb8856606 {
1575*2d9fd380Sjfb8856606 	uint32_t rx_mode = 0;
1576*2d9fd380Sjfb8856606 	uint32_t i;
1577*2d9fd380Sjfb8856606 	int err;
1578*2d9fd380Sjfb8856606 
1579*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Setting RSS configuration on port %u",
1580*2d9fd380Sjfb8856606 		lif->port_id);
1581*2d9fd380Sjfb8856606 
1582*2d9fd380Sjfb8856606 	err = ionic_lif_rss_setup(lif);
1583*2d9fd380Sjfb8856606 	if (err)
1584*2d9fd380Sjfb8856606 		return err;
1585*2d9fd380Sjfb8856606 
1586*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Setting RX mode on port %u",
1587*2d9fd380Sjfb8856606 		lif->port_id);
1588*2d9fd380Sjfb8856606 
1589*2d9fd380Sjfb8856606 	rx_mode |= IONIC_RX_MODE_F_UNICAST;
1590*2d9fd380Sjfb8856606 	rx_mode |= IONIC_RX_MODE_F_MULTICAST;
1591*2d9fd380Sjfb8856606 	rx_mode |= IONIC_RX_MODE_F_BROADCAST;
1592*2d9fd380Sjfb8856606 
1593*2d9fd380Sjfb8856606 	lif->rx_mode = 0; /* set by ionic_set_rx_mode */
1594*2d9fd380Sjfb8856606 
1595*2d9fd380Sjfb8856606 	ionic_set_rx_mode(lif, rx_mode);
1596*2d9fd380Sjfb8856606 
1597*2d9fd380Sjfb8856606 	IONIC_PRINT(DEBUG, "Starting %u RX queues and %u TX queues "
1598*2d9fd380Sjfb8856606 		"on port %u",
1599*2d9fd380Sjfb8856606 		lif->nrxqcqs, lif->ntxqcqs, lif->port_id);
1600*2d9fd380Sjfb8856606 
1601*2d9fd380Sjfb8856606 	for (i = 0; i < lif->nrxqcqs; i++) {
1602*2d9fd380Sjfb8856606 		struct ionic_qcq *rxq = lif->rxqcqs[i];
1603*2d9fd380Sjfb8856606 		if (!rxq->deferred_start) {
1604*2d9fd380Sjfb8856606 			err = ionic_dev_rx_queue_start(lif->eth_dev, i);
1605*2d9fd380Sjfb8856606 
1606*2d9fd380Sjfb8856606 			if (err)
1607*2d9fd380Sjfb8856606 				return err;
1608*2d9fd380Sjfb8856606 		}
1609*2d9fd380Sjfb8856606 	}
1610*2d9fd380Sjfb8856606 
1611*2d9fd380Sjfb8856606 	for (i = 0; i < lif->ntxqcqs; i++) {
1612*2d9fd380Sjfb8856606 		struct ionic_qcq *txq = lif->txqcqs[i];
1613*2d9fd380Sjfb8856606 		if (!txq->deferred_start) {
1614*2d9fd380Sjfb8856606 			err = ionic_dev_tx_queue_start(lif->eth_dev, i);
1615*2d9fd380Sjfb8856606 
1616*2d9fd380Sjfb8856606 			if (err)
1617*2d9fd380Sjfb8856606 				return err;
1618*2d9fd380Sjfb8856606 		}
1619*2d9fd380Sjfb8856606 	}
1620*2d9fd380Sjfb8856606 
1621*2d9fd380Sjfb8856606 	ionic_link_status_check(lif);
1622*2d9fd380Sjfb8856606 
1623*2d9fd380Sjfb8856606 	/* Carrier ON here */
1624*2d9fd380Sjfb8856606 
1625*2d9fd380Sjfb8856606 	return 0;
1626*2d9fd380Sjfb8856606 }
1627*2d9fd380Sjfb8856606 
1628*2d9fd380Sjfb8856606 int
ionic_lif_identify(struct ionic_adapter * adapter)1629*2d9fd380Sjfb8856606 ionic_lif_identify(struct ionic_adapter *adapter)
1630*2d9fd380Sjfb8856606 {
1631*2d9fd380Sjfb8856606 	struct ionic_dev *idev = &adapter->idev;
1632*2d9fd380Sjfb8856606 	struct ionic_identity *ident = &adapter->ident;
1633*2d9fd380Sjfb8856606 	int err;
1634*2d9fd380Sjfb8856606 	unsigned int i;
1635*2d9fd380Sjfb8856606 	unsigned int lif_words = sizeof(ident->lif.words) /
1636*2d9fd380Sjfb8856606 		sizeof(ident->lif.words[0]);
1637*2d9fd380Sjfb8856606 	unsigned int cmd_words = sizeof(idev->dev_cmd->data) /
1638*2d9fd380Sjfb8856606 		sizeof(idev->dev_cmd->data[0]);
1639*2d9fd380Sjfb8856606 	unsigned int nwords;
1640*2d9fd380Sjfb8856606 
1641*2d9fd380Sjfb8856606 	ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC,
1642*2d9fd380Sjfb8856606 		IONIC_IDENTITY_VERSION_1);
1643*2d9fd380Sjfb8856606 	err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
1644*2d9fd380Sjfb8856606 	if (err)
1645*2d9fd380Sjfb8856606 		return (err);
1646*2d9fd380Sjfb8856606 
1647*2d9fd380Sjfb8856606 	nwords = RTE_MIN(lif_words, cmd_words);
1648*2d9fd380Sjfb8856606 	for (i = 0; i < nwords; i++)
1649*2d9fd380Sjfb8856606 		ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]);
1650*2d9fd380Sjfb8856606 
1651*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ",
1652*2d9fd380Sjfb8856606 		ident->lif.capabilities);
1653*2d9fd380Sjfb8856606 
1654*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ",
1655*2d9fd380Sjfb8856606 		ident->lif.eth.max_ucast_filters);
1656*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ",
1657*2d9fd380Sjfb8856606 		ident->lif.eth.max_mcast_filters);
1658*2d9fd380Sjfb8856606 
1659*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ",
1660*2d9fd380Sjfb8856606 		ident->lif.eth.config.features);
1661*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ",
1662*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]);
1663*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ",
1664*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]);
1665*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ",
1666*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]);
1667*2d9fd380Sjfb8856606 	IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ",
1668*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]);
1669*2d9fd380Sjfb8856606 
1670*2d9fd380Sjfb8856606 	return 0;
1671*2d9fd380Sjfb8856606 }
1672*2d9fd380Sjfb8856606 
1673*2d9fd380Sjfb8856606 int
ionic_lifs_size(struct ionic_adapter * adapter)1674*2d9fd380Sjfb8856606 ionic_lifs_size(struct ionic_adapter *adapter)
1675*2d9fd380Sjfb8856606 {
1676*2d9fd380Sjfb8856606 	struct ionic_identity *ident = &adapter->ident;
1677*2d9fd380Sjfb8856606 	uint32_t nlifs = ident->dev.nlifs;
1678*2d9fd380Sjfb8856606 	uint32_t nintrs, dev_nintrs = ident->dev.nintrs;
1679*2d9fd380Sjfb8856606 
1680*2d9fd380Sjfb8856606 	adapter->max_ntxqs_per_lif =
1681*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ];
1682*2d9fd380Sjfb8856606 	adapter->max_nrxqs_per_lif =
1683*2d9fd380Sjfb8856606 		ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ];
1684*2d9fd380Sjfb8856606 
1685*2d9fd380Sjfb8856606 	nintrs = nlifs * 1 /* notifyq */;
1686*2d9fd380Sjfb8856606 
1687*2d9fd380Sjfb8856606 	if (nintrs > dev_nintrs) {
1688*2d9fd380Sjfb8856606 		IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u",
1689*2d9fd380Sjfb8856606 			dev_nintrs, nintrs);
1690*2d9fd380Sjfb8856606 		return -ENOSPC;
1691*2d9fd380Sjfb8856606 	}
1692*2d9fd380Sjfb8856606 
1693*2d9fd380Sjfb8856606 	adapter->nintrs = nintrs;
1694*2d9fd380Sjfb8856606 
1695*2d9fd380Sjfb8856606 	return 0;
1696*2d9fd380Sjfb8856606 }
1697