xref: /freebsd/sys/dev/ice/ice_iflib_txrx.c (revision 85fb40bad584e7d8c503e5a99bb81cc2d3cf9fee)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2024, Intel Corporation
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above copyright notice,
9  *      this list of conditions and the following disclaimer.
10  *
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *
15  *   3. Neither the name of the Intel Corporation nor the names of its
16  *      contributors may be used to endorse or promote products derived from
17  *      this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *  POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /**
33  * @file ice_iflib_txrx.c
34  * @brief iflib Tx/Rx hotpath
35  *
36  * Main location for the iflib Tx/Rx hotpath implementation.
37  *
38  * Contains the implementation for the iflib function callbacks and the
39  * if_txrx ops structure.
40  */
41 
42 #include "ice_iflib.h"
43 
44 /* Tx/Rx hotpath utility functions */
45 #include "ice_common_txrx.h"
46 
47 /*
48  * Driver private implementations
49  */
50 static int _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi);
51 static int _ice_ift_txd_credits_update(struct ice_softc *sc, struct ice_tx_queue *txq, bool clear);
52 static int _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget);
53 static int _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri);
54 static void _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx,
55 				uint64_t *paddrs, uint16_t count);
56 static void _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq,
57 			       uint32_t pidx);
58 
59 /*
60  * iflib txrx method declarations
61  */
62 static int ice_ift_txd_encap(void *arg, if_pkt_info_t pi);
63 static int ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri);
64 static void ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
65 static int ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear);
66 static int ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget);
67 static void ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx);
68 static void ice_ift_rxd_refill(void *arg, if_rxd_update_t iru);
69 static qidx_t ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi);
70 static int ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear);
71 static int ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi);
72 static void ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx);
73 static int ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget);
74 static int ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri);
75 static void ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru);
76 static void ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx);
77 
78 /* Macro to help extract the NIC mode flexible Rx descriptor fields from the
79  * advanced 32byte Rx descriptors.
80  */
81 #define RX_FLEX_NIC(desc, field) \
82 	(((struct ice_32b_rx_flex_desc_nic *)desc)->field)
83 
84 /**
85  * @var ice_txrx
86  * @brief Tx/Rx operations for the iflib stack
87  *
88  * Structure defining the Tx and Rx related operations that iflib can request
89  * the driver to perform. These are the main entry points for the hot path of
90  * the transmit and receive paths in the iflib driver.
91  */
92 struct if_txrx ice_txrx = {
93 	.ift_txd_encap = ice_ift_txd_encap,
94 	.ift_txd_flush = ice_ift_txd_flush,
95 	.ift_txd_credits_update = ice_ift_txd_credits_update,
96 	.ift_rxd_available = ice_ift_rxd_available,
97 	.ift_rxd_pkt_get = ice_ift_rxd_pkt_get,
98 	.ift_rxd_refill = ice_ift_rxd_refill,
99 	.ift_rxd_flush = ice_ift_rxd_flush,
100 	.ift_txq_select_v2 = ice_ift_queue_select,
101 };
102 
103 /**
104  * @var ice_subif_txrx
105  * @brief Tx/Rx operations for the iflib stack, for subinterfaces
106  *
107  * Structure defining the Tx and Rx related operations that iflib can request
108  * the subinterface driver to perform. These are the main entry points for the
109  * hot path of the transmit and receive paths in the iflib driver.
110  */
111 struct if_txrx ice_subif_txrx = {
112 	.ift_txd_credits_update = ice_ift_txd_credits_update_subif,
113 	.ift_txd_encap = ice_ift_txd_encap_subif,
114 	.ift_txd_flush = ice_ift_txd_flush_subif,
115 	.ift_rxd_available = ice_ift_rxd_available_subif,
116 	.ift_rxd_pkt_get = ice_ift_rxd_pkt_get_subif,
117 	.ift_rxd_refill = ice_ift_rxd_refill_subif,
118 	.ift_rxd_flush = ice_ift_rxd_flush_subif,
119 	.ift_txq_select_v2 = NULL,
120 };
121 
122 /**
123  * _ice_ift_txd_encap - prepare Tx descriptors for a packet
124  * @txq: driver's TX queue context
125  * @pi: packet info
126  *
127  * Prepares and encapsulates the given packet into into Tx descriptors, in
128  * preparation for sending to the transmit engine. Sets the necessary context
129  * descriptors for TSO and other offloads, and prepares the last descriptor
130  * for the writeback status.
131  *
132  * Return 0 on success, non-zero error code on failure.
133  */
134 static int
135 _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi)
136 {
137 	int nsegs = pi->ipi_nsegs;
138 	bus_dma_segment_t *segs = pi->ipi_segs;
139 	struct ice_tx_desc *txd = NULL;
140 	int i, j, mask, pidx_last;
141 	u32 cmd, off, tx_intr, txd_cmd;
142 
143 	cmd = off = 0;
144 	i = pi->ipi_pidx;
145 	tx_intr = pi->ipi_flags & IPI_TX_INTR;
146 	txd_cmd = ICE_TX_DESC_CMD_EOP;
147 	if (tx_intr)
148 		txd_cmd |= ICE_TX_DESC_CMD_RS;
149 
150 	/* Set up the TSO/CSUM offload */
151 	if (pi->ipi_csum_flags & ICE_CSUM_OFFLOAD) {
152 		/* Set up the TSO context descriptor if required */
153 		if (pi->ipi_csum_flags & CSUM_TSO) {
154 			if (ice_tso_detect_sparse(pi))
155 				return (EFBIG);
156 			i = ice_tso_setup(txq, pi);
157 		}
158 		ice_tx_setup_offload(txq, pi, &cmd, &off);
159 	}
160 	if (pi->ipi_mflags & M_VLANTAG)
161 		cmd |= ICE_TX_DESC_CMD_IL2TAG1;
162 
163 	mask = txq->desc_count - 1;
164 	for (j = 0; j < nsegs; j++) {
165 		bus_size_t seglen;
166 
167 		txd = &txq->tx_base[i];
168 		seglen = segs[j].ds_len;
169 
170 		txd->buf_addr = htole64(segs[j].ds_addr);
171 		txd->cmd_type_offset_bsz =
172 		    htole64(ICE_TX_DESC_DTYPE_DATA
173 		    | ((u64)cmd  << ICE_TXD_QW1_CMD_S)
174 		    | ((u64)off << ICE_TXD_QW1_OFFSET_S)
175 		    | ((u64)seglen  << ICE_TXD_QW1_TX_BUF_SZ_S)
176 		    | ((u64)htole16(pi->ipi_vtag) << ICE_TXD_QW1_L2TAG1_S));
177 
178 		txq->stats.tx_bytes += seglen;
179 		pidx_last = i;
180 		i = (i+1) & mask;
181 	}
182 
183 	/* Set the last descriptor for report */
184 	txd->cmd_type_offset_bsz |=
185 	    htole64((u64)txd_cmd << ICE_TXD_QW1_CMD_S);
186 
187 	/* Add to report status array if requesting descriptor writeback. */
188 	if (tx_intr) {
189 		txq->tx_rsq[txq->tx_rs_pidx] = pidx_last;
190 		txq->tx_rs_pidx = (txq->tx_rs_pidx+1) & mask;
191 		MPASS(txq->tx_rs_pidx != txq->tx_rs_cidx);
192 	}
193 
194 	pi->ipi_new_pidx = i;
195 
196 	++txq->stats.tx_packets;
197 	return (0);
198 }
199 
200 /**
201  * ice_ift_txd_encap - prepare Tx descriptors for a packet
202  * @arg: the iflib softc structure pointer
203  * @pi: packet info
204  *
205  * Prepares and encapsulates the given packet into Tx descriptors, in
206  * preparation for sending to the transmit engine. Sets the necessary context
207  * descriptors for TSO and other offloads, and prepares the last descriptor
208  * for the writeback status.
209  *
210  * Return 0 on success, non-zero error code on failure.
211  */
212 static int
213 ice_ift_txd_encap(void *arg, if_pkt_info_t pi)
214 {
215 	struct ice_softc *sc = (struct ice_softc *)arg;
216 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[pi->ipi_qsidx];
217 
218 	return _ice_ift_txd_encap(txq, pi);
219 }
220 
221 /**
222  * ice_ift_txd_flush - Flush Tx descriptors to hardware
223  * @arg: device specific softc pointer
224  * @txqid: the Tx queue to flush
225  * @pidx: descriptor index to advance tail to
226  *
227  * Advance the Transmit Descriptor Tail (TDT). This indicates to hardware that
228  * frames are available for transmit.
229  */
230 static void
231 ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
232 {
233 	struct ice_softc *sc = (struct ice_softc *)arg;
234 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
235 	struct ice_hw *hw = &sc->hw;
236 
237 	wr32(hw, txq->tail, pidx);
238 }
239 
240 /**
241  * _ice_ift_txd_credits_update - cleanup Tx descriptors
242  * @sc: device private softc
243  * @txq: the Tx queue to update
244  * @clear: if false, only report, do not actually clean
245  *
246  * If clear is false, iflib is asking if we *could* clean up any Tx
247  * descriptors.
248  *
249  * If clear is true, iflib is requesting to cleanup and reclaim used Tx
250  * descriptors.
251  *
252  * Called by other txd_credits_update functions passed to iflib.
253  */
254 static int
255 _ice_ift_txd_credits_update(struct ice_softc *sc __unused, struct ice_tx_queue *txq, bool clear)
256 {
257 	qidx_t processed = 0;
258 	qidx_t cur, prev, ntxd, rs_cidx;
259 	int32_t delta;
260 	bool is_done;
261 
262 	rs_cidx = txq->tx_rs_cidx;
263 	if (rs_cidx == txq->tx_rs_pidx)
264 		return (0);
265 	cur = txq->tx_rsq[rs_cidx];
266 	MPASS(cur != QIDX_INVALID);
267 	is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
268 
269 	if (!is_done)
270 		return (0);
271 	else if (clear == false)
272 		return (1);
273 
274 	prev = txq->tx_cidx_processed;
275 	ntxd = txq->desc_count;
276 	do {
277 		MPASS(prev != cur);
278 		delta = (int32_t)cur - (int32_t)prev;
279 		if (delta < 0)
280 			delta += ntxd;
281 		MPASS(delta > 0);
282 		processed += delta;
283 		prev = cur;
284 		rs_cidx = (rs_cidx + 1) & (ntxd-1);
285 		if (rs_cidx == txq->tx_rs_pidx)
286 			break;
287 		cur = txq->tx_rsq[rs_cidx];
288 		MPASS(cur != QIDX_INVALID);
289 		is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
290 	} while (is_done);
291 
292 	txq->tx_rs_cidx = rs_cidx;
293 	txq->tx_cidx_processed = prev;
294 
295 	return (processed);
296 }
297 
298 /**
299  * ice_ift_txd_credits_update - cleanup PF VSI Tx descriptors
300  * @arg: device private softc
301  * @txqid: the Tx queue to update
302  * @clear: if false, only report, do not actually clean
303  *
304  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
305  * belong to the PF VSI.
306  *
307  * @see _ice_ift_txd_credits_update()
308  */
309 static int
310 ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear)
311 {
312 	struct ice_softc *sc = (struct ice_softc *)arg;
313 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
314 
315 	return _ice_ift_txd_credits_update(sc, txq, clear);
316 }
317 
318 /**
319  * _ice_ift_rxd_available - Return number of available Rx packets
320  * @rxq: RX queue driver structure
321  * @pidx: descriptor start point
322  * @budget: maximum Rx budget
323  *
324  * Determines how many Rx packets are available on the queue, up to a maximum
325  * of the given budget.
326  */
327 static int
328 _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget)
329 {
330 	union ice_32b_rx_flex_desc *rxd;
331 	uint16_t status0;
332 	int cnt, i, nrxd;
333 
334 	nrxd = rxq->desc_count;
335 
336 	for (cnt = 0, i = pidx; cnt < nrxd - 1 && cnt < budget;) {
337 		rxd = &rxq->rx_base[i];
338 		status0 = le16toh(rxd->wb.status_error0);
339 
340 		if ((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) == 0)
341 			break;
342 		if (++i == nrxd)
343 			i = 0;
344 		if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S))
345 			cnt++;
346 	}
347 
348 	return (cnt);
349 }
350 
351 /**
352  * ice_ift_rxd_available - Return number of available Rx packets
353  * @arg: device private softc
354  * @rxqid: the Rx queue id
355  * @pidx: descriptor start point
356  * @budget: maximum Rx budget
357  *
358  * Wrapper for _ice_ift_rxd_available() that provides a function pointer
359  * that iflib requires for RX processing.
360  */
361 static int
362 ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
363 {
364 	struct ice_softc *sc = (struct ice_softc *)arg;
365 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
366 
367 	return _ice_ift_rxd_available(rxq, pidx, budget);
368 }
369 
370 /**
371  * ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
372  * @arg: device specific softc
373  * @ri: receive packet info
374  *
375  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
376  * used by iflib for RX packet processing.
377  */
378 static int
379 ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
380 {
381 	struct ice_softc *sc = (struct ice_softc *)arg;
382 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[ri->iri_qsidx];
383 
384 	return _ice_ift_rxd_pkt_get(rxq, ri);
385 }
386 
387 /**
388  * _ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
389  * @rxq: RX queue driver structure
390  * @ri: receive packet info
391  *
392  * This function is called by iflib, and executes in ithread context. It is
393  * called by iflib to obtain data which has been DMA'ed into host memory.
394  * Returns zero on success, and EBADMSG on failure.
395  */
396 static int
397 _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri)
398 {
399 	union ice_32b_rx_flex_desc *cur;
400 	u16 status0, plen, ptype;
401 	bool eop;
402 	size_t cidx;
403 	int i;
404 
405 	cidx = ri->iri_cidx;
406 	i = 0;
407 	do {
408 		/* 5 descriptor receive limit */
409 		MPASS(i < ICE_MAX_RX_SEGS);
410 
411 		cur = &rxq->rx_base[cidx];
412 		status0 = le16toh(cur->wb.status_error0);
413 		plen = le16toh(cur->wb.pkt_len) &
414 			ICE_RX_FLX_DESC_PKT_LEN_M;
415 
416 		/* we should never be called without a valid descriptor */
417 		MPASS((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) != 0);
418 
419 		ri->iri_len += plen;
420 
421 		cur->wb.status_error0 = 0;
422 		eop = (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S));
423 
424 		ri->iri_frags[i].irf_flid = 0;
425 		ri->iri_frags[i].irf_idx = cidx;
426 		ri->iri_frags[i].irf_len = plen;
427 		if (++cidx == rxq->desc_count)
428 			cidx = 0;
429 		i++;
430 	} while (!eop);
431 
432 	/* End of Packet reached; cur is eop/last descriptor */
433 
434 	/* Make sure packets with bad L2 values are discarded.
435 	 * This bit is only valid in the last descriptor.
436 	 */
437 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S)) {
438 		rxq->stats.desc_errs++;
439 		return (EBADMSG);
440 	}
441 
442 	/* Get VLAN tag information if one is in descriptor */
443 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) {
444 		ri->iri_vtag = le16toh(cur->wb.l2tag1);
445 		ri->iri_flags |= M_VLANTAG;
446 	}
447 
448 	/* Capture soft statistics for this Rx queue */
449 	rxq->stats.rx_packets++;
450 	rxq->stats.rx_bytes += ri->iri_len;
451 
452 	/* Get packet type and set checksum flags */
453 	ptype = le16toh(cur->wb.ptype_flex_flags0) &
454 		ICE_RX_FLEX_DESC_PTYPE_M;
455 	if ((if_getcapenable(ri->iri_ifp) & IFCAP_RXCSUM) != 0)
456 		ice_rx_checksum(rxq, &ri->iri_csum_flags,
457 				&ri->iri_csum_data, status0, ptype);
458 
459 	/* Set remaining iflib RX descriptor info fields */
460 	ri->iri_flowid = le32toh(RX_FLEX_NIC(&cur->wb, rss_hash));
461 	ri->iri_rsstype = ice_ptype_to_hash(ptype);
462 	ri->iri_nfrags = i;
463 	return (0);
464 }
465 
466 /**
467  * ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
468  * @arg: device specific softc structure
469  * @iru: the Rx descriptor update structure
470  *
471  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
472  * used by iflib for RX packet processing.
473  */
474 static void
475 ice_ift_rxd_refill(void *arg, if_rxd_update_t iru)
476 {
477 	struct ice_softc *sc = (struct ice_softc *)arg;
478 	struct ice_rx_queue *rxq;
479 	uint64_t *paddrs;
480 	uint32_t pidx;
481 	uint16_t qsidx, count;
482 
483 	paddrs = iru->iru_paddrs;
484 	pidx = iru->iru_pidx;
485 	qsidx = iru->iru_qsidx;
486 	count = iru->iru_count;
487 
488 	rxq = &(sc->pf_vsi.rx_queues[qsidx]);
489 
490 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
491 }
492 
493 /**
494  * _ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
495  * @rxq: RX queue driver structure
496  * @pidx: first index to refill
497  * @paddrs: physical addresses to use
498  * @count: number of descriptors to refill
499  *
500  * Update the Rx descriptor indices for a given queue, assigning new physical
501  * addresses to the descriptors, preparing them for re-use by the hardware.
502  */
503 static void
504 _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx,
505 		    uint64_t *paddrs, uint16_t count)
506 {
507 	uint32_t next_pidx;
508 	int i;
509 
510 	for (i = 0, next_pidx = pidx; i < count; i++) {
511 		rxq->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
512 		if (++next_pidx == (uint32_t)rxq->desc_count)
513 			next_pidx = 0;
514 	}
515 }
516 
517 /**
518  * ice_ift_rxd_flush - Flush Rx descriptors to hardware
519  * @arg: device specific softc pointer
520  * @rxqid: the Rx queue to flush
521  * @flidx: unused parameter
522  * @pidx: descriptor index to advance tail to
523  *
524  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
525  * used by iflib for RX packet processing.
526  */
527 static void
528 ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx __unused,
529 		  qidx_t pidx)
530 {
531 	struct ice_softc *sc = (struct ice_softc *)arg;
532 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
533 
534 	_ice_ift_rxd_flush(sc, rxq, (uint32_t)pidx);
535 }
536 
537 /**
538  * _ice_ift_rxd_flush - Flush Rx descriptors to hardware
539  * @sc: device specific softc pointer
540  * @rxq: RX queue driver structure
541  * @pidx: descriptor index to advance tail to
542  *
543  * Advance the Receive Descriptor Tail (RDT). This indicates to hardware that
544  * software is done with the descriptor and it can be recycled.
545  */
546 static void
547 _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq, uint32_t pidx)
548 {
549 	wr32(&sc->hw, rxq->tail, pidx);
550 }
551 
552 /**
553  * ice_ift_queue_select - Select queue index to transmit packet on
554  * @arg: device specific softc
555  * @m: transmit packet data
556  * @pi: transmit packet metadata
557  *
558  * Called by iflib to determine which queue index to transmit the packet
559  * pointed to by @m on. In particular, ensures packets go out on the right
560  * queue index for the right transmit class when multiple traffic classes are
561  * enabled in the driver.
562  */
563 static qidx_t
564 ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi)
565 {
566 	struct ice_softc *sc = (struct ice_softc *)arg;
567 	struct ice_dcbx_cfg *local_dcbx_cfg;
568 	struct ice_vsi *vsi = &sc->pf_vsi;
569 	u16 tc_base_queue, tc_qcount;
570 	u8 up, tc;
571 
572 #ifdef ALTQ
573 	/* Included to match default iflib behavior */
574 	/* Only go out on default queue if ALTQ is enabled */
575 	struct ifnet *ifp = (struct ifnet *)iflib_get_ifp(sc->ctx);
576 	if (if_altq_is_enabled(ifp))
577 		return (0);
578 #endif
579 
580 	if (!ice_test_state(&sc->state, ICE_STATE_MULTIPLE_TCS)) {
581 		if (M_HASHTYPE_GET(m)) {
582 			/* Default iflib queue selection method */
583 			return (m->m_pkthdr.flowid % sc->pf_vsi.num_tx_queues);
584 		} else
585 			return (0);
586 	}
587 
588 	/* Use default TC unless overridden later */
589 	tc = 0; /* XXX: Get default TC for traffic if >1 TC? */
590 
591 	local_dcbx_cfg = &sc->hw.port_info->qos_cfg.local_dcbx_cfg;
592 
593 #if defined(INET) || defined(INET6)
594 	if ((local_dcbx_cfg->pfc_mode == ICE_QOS_MODE_DSCP) &&
595 	    (pi->ipi_flags & (IPI_TX_IPV4 | IPI_TX_IPV6))) {
596 		u8 dscp_val = pi->ipi_ip_tos >> 2;
597 		tc = local_dcbx_cfg->dscp_map[dscp_val];
598 	} else
599 #endif /* defined(INET) || defined(INET6) */
600 	if (m->m_flags & M_VLANTAG) { /* ICE_QOS_MODE_VLAN */
601 		up = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
602 		tc = local_dcbx_cfg->etscfg.prio_table[up];
603 	}
604 
605 	tc_base_queue = vsi->tc_info[tc].qoffset;
606 	tc_qcount = vsi->tc_info[tc].qcount_tx;
607 
608 	if (M_HASHTYPE_GET(m))
609 		return ((m->m_pkthdr.flowid % tc_qcount) + tc_base_queue);
610 	else
611 		return (tc_base_queue);
612 }
613 
614 /**
615  * ice_ift_txd_credits_update_subif - cleanup subinterface VSI Tx descriptors
616  * @arg: subinterface private structure (struct ice_mirr_if)
617  * @txqid: the Tx queue to update
618  * @clear: if false, only report, do not actually clean
619  *
620  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
621  * do not belong to the PF VSI.
622  *
623  * See _ice_ift_txd_credits_update().
624  */
625 static int
626 ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear)
627 {
628 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
629 	struct ice_softc *sc = mif->back;
630 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
631 
632 	return _ice_ift_txd_credits_update(sc, txq, clear);
633 }
634 
635 /**
636  * ice_ift_txd_encap_subif - prepare Tx descriptors for a packet
637  * @arg: subinterface private structure (struct ice_mirr_if)
638  * @pi: packet info
639  *
640  * Wrapper for _ice_ift_txd_encap_subif() meant for TX queues that
641  * do not belong to the PF VSI.
642  *
643  * See _ice_ift_txd_encap_subif().
644  */
645 static int
646 ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi)
647 {
648 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
649 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[pi->ipi_qsidx];
650 
651 	return _ice_ift_txd_encap(txq, pi);
652 }
653 
654 /**
655  * ice_ift_txd_flush_subif - Flush Tx descriptors to hardware
656  * @arg: subinterface private structure (struct ice_mirr_if)
657  * @txqid: the Tx queue to flush
658  * @pidx: descriptor index to advance tail to
659  *
660  * Advance the Transmit Descriptor Tail (TDT). Functionally identical to
661  * the ice_ift_txd_encap() meant for the main PF VSI, but provides a function
662  * pointer to iflib for use with non-main-PF VSI TX queues.
663  */
664 static void
665 ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx)
666 {
667 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
668 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
669 	struct ice_hw *hw = &mif->back->hw;
670 
671 	wr32(hw, txq->tail, pidx);
672 }
673 
674 /**
675  * ice_ift_rxd_available_subif - Return number of available Rx packets
676  * @arg: subinterface private structure (struct ice_mirr_if)
677  * @rxqid: the Rx queue id
678  * @pidx: descriptor start point
679  * @budget: maximum Rx budget
680  *
681  * Determines how many Rx packets are available on the queue, up to a maximum
682  * of the given budget.
683  *
684  * See _ice_ift_rxd_available().
685  */
686 static int
687 ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
688 {
689 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
690 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
691 
692 	return _ice_ift_rxd_available(rxq, pidx, budget);
693 }
694 
695 /**
696  * ice_ift_rxd_pkt_get_subif - Called by iflib to send data to upper layer
697  * @arg: subinterface private structure (struct ice_mirr_if)
698  * @ri: receive packet info
699  *
700  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
701  * used by iflib for RX packet processing, for iflib subinterfaces.
702  */
703 static int
704 ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri)
705 {
706 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
707 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[ri->iri_qsidx];
708 
709 	return _ice_ift_rxd_pkt_get(rxq, ri);
710 }
711 
712 /**
713  * ice_ift_rxd_refill_subif - Prepare Rx descriptors for re-use by hardware
714  * @arg: subinterface private structure (struct ice_mirr_if)
715  * @iru: the Rx descriptor update structure
716  *
717  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
718  * used by iflib for RX packet processing, for iflib subinterfaces.
719  */
720 static void
721 ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru)
722 {
723 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
724 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[iru->iru_qsidx];
725 
726 	uint64_t *paddrs;
727 	uint32_t pidx;
728 	uint16_t count;
729 
730 	paddrs = iru->iru_paddrs;
731 	pidx = iru->iru_pidx;
732 	count = iru->iru_count;
733 
734 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
735 }
736 
737 /**
738  * ice_ift_rxd_flush_subif - Flush Rx descriptors to hardware
739  * @arg: subinterface private structure (struct ice_mirr_if)
740  * @rxqid: the Rx queue to flush
741  * @flidx: unused parameter
742  * @pidx: descriptor index to advance tail to
743  *
744  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
745  * used by iflib for RX packet processing.
746  */
747 static void
748 ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx __unused,
749 			qidx_t pidx)
750 {
751 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
752 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
753 
754 	_ice_ift_rxd_flush(mif->back, rxq, pidx);
755 }
756