xref: /freebsd/sys/dev/ice/ice_iflib_txrx.c (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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;
142 
143 	cmd = off = 0;
144 	i = pi->ipi_pidx;
145 
146 	/* Set up the TSO/CSUM offload */
147 	if (pi->ipi_csum_flags & ICE_CSUM_OFFLOAD) {
148 		/* Set up the TSO context descriptor if required */
149 		if (pi->ipi_csum_flags & CSUM_TSO) {
150 			if (ice_tso_detect_sparse(pi))
151 				return (EFBIG);
152 			i = ice_tso_setup(txq, pi);
153 		}
154 		ice_tx_setup_offload(txq, pi, &cmd, &off);
155 	}
156 	if (pi->ipi_mflags & M_VLANTAG)
157 		cmd |= ICE_TX_DESC_CMD_IL2TAG1;
158 
159 	mask = txq->desc_count - 1;
160 	for (j = 0; j < nsegs; j++) {
161 		bus_size_t seglen;
162 
163 		txd = &txq->tx_base[i];
164 		seglen = segs[j].ds_len;
165 
166 		txd->buf_addr = htole64(segs[j].ds_addr);
167 		txd->cmd_type_offset_bsz =
168 		    htole64(ICE_TX_DESC_DTYPE_DATA
169 		    | ((u64)cmd  << ICE_TXD_QW1_CMD_S)
170 		    | ((u64)off << ICE_TXD_QW1_OFFSET_S)
171 		    | ((u64)seglen  << ICE_TXD_QW1_TX_BUF_SZ_S)
172 		    | ((u64)htole16(pi->ipi_vtag) << ICE_TXD_QW1_L2TAG1_S));
173 
174 		txq->stats.tx_bytes += seglen;
175 		pidx_last = i;
176 		i = (i+1) & mask;
177 	}
178 
179 	/* Set the last descriptor for report */
180 #define ICE_TXD_CMD (ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS)
181 	txd->cmd_type_offset_bsz |=
182 	    htole64(((u64)ICE_TXD_CMD << ICE_TXD_QW1_CMD_S));
183 
184 	/* Add to report status array */
185 	txq->tx_rsq[txq->tx_rs_pidx] = pidx_last;
186 	txq->tx_rs_pidx = (txq->tx_rs_pidx+1) & mask;
187 	MPASS(txq->tx_rs_pidx != txq->tx_rs_cidx);
188 
189 	pi->ipi_new_pidx = i;
190 
191 	++txq->stats.tx_packets;
192 	return (0);
193 }
194 
195 /**
196  * ice_ift_txd_encap - prepare Tx descriptors for a packet
197  * @arg: the iflib softc structure pointer
198  * @pi: packet info
199  *
200  * Prepares and encapsulates the given packet into Tx descriptors, in
201  * preparation for sending to the transmit engine. Sets the necessary context
202  * descriptors for TSO and other offloads, and prepares the last descriptor
203  * for the writeback status.
204  *
205  * Return 0 on success, non-zero error code on failure.
206  */
207 static int
208 ice_ift_txd_encap(void *arg, if_pkt_info_t pi)
209 {
210 	struct ice_softc *sc = (struct ice_softc *)arg;
211 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[pi->ipi_qsidx];
212 
213 	return _ice_ift_txd_encap(txq, pi);
214 }
215 
216 /**
217  * ice_ift_txd_flush - Flush Tx descriptors to hardware
218  * @arg: device specific softc pointer
219  * @txqid: the Tx queue to flush
220  * @pidx: descriptor index to advance tail to
221  *
222  * Advance the Transmit Descriptor Tail (TDT). This indicates to hardware that
223  * frames are available for transmit.
224  */
225 static void
226 ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
227 {
228 	struct ice_softc *sc = (struct ice_softc *)arg;
229 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
230 	struct ice_hw *hw = &sc->hw;
231 
232 	wr32(hw, txq->tail, pidx);
233 }
234 
235 /**
236  * _ice_ift_txd_credits_update - cleanup Tx descriptors
237  * @sc: device private softc
238  * @txq: the Tx queue to update
239  * @clear: if false, only report, do not actually clean
240  *
241  * If clear is false, iflib is asking if we *could* clean up any Tx
242  * descriptors.
243  *
244  * If clear is true, iflib is requesting to cleanup and reclaim used Tx
245  * descriptors.
246  *
247  * Called by other txd_credits_update functions passed to iflib.
248  */
249 static int
250 _ice_ift_txd_credits_update(struct ice_softc *sc __unused, struct ice_tx_queue *txq, bool clear)
251 {
252 	qidx_t processed = 0;
253 	qidx_t cur, prev, ntxd, rs_cidx;
254 	int32_t delta;
255 	bool is_done;
256 
257 	rs_cidx = txq->tx_rs_cidx;
258 	if (rs_cidx == txq->tx_rs_pidx)
259 		return (0);
260 	cur = txq->tx_rsq[rs_cidx];
261 	MPASS(cur != QIDX_INVALID);
262 	is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
263 
264 	if (!is_done)
265 		return (0);
266 	else if (clear == false)
267 		return (1);
268 
269 	prev = txq->tx_cidx_processed;
270 	ntxd = txq->desc_count;
271 	do {
272 		MPASS(prev != cur);
273 		delta = (int32_t)cur - (int32_t)prev;
274 		if (delta < 0)
275 			delta += ntxd;
276 		MPASS(delta > 0);
277 		processed += delta;
278 		prev = cur;
279 		rs_cidx = (rs_cidx + 1) & (ntxd-1);
280 		if (rs_cidx == txq->tx_rs_pidx)
281 			break;
282 		cur = txq->tx_rsq[rs_cidx];
283 		MPASS(cur != QIDX_INVALID);
284 		is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
285 	} while (is_done);
286 
287 	txq->tx_rs_cidx = rs_cidx;
288 	txq->tx_cidx_processed = prev;
289 
290 	return (processed);
291 }
292 
293 /**
294  * ice_ift_txd_credits_update - cleanup PF VSI Tx descriptors
295  * @arg: device private softc
296  * @txqid: the Tx queue to update
297  * @clear: if false, only report, do not actually clean
298  *
299  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
300  * belong to the PF VSI.
301  *
302  * @see _ice_ift_txd_credits_update()
303  */
304 static int
305 ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear)
306 {
307 	struct ice_softc *sc = (struct ice_softc *)arg;
308 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
309 
310 	return _ice_ift_txd_credits_update(sc, txq, clear);
311 }
312 
313 /**
314  * _ice_ift_rxd_available - Return number of available Rx packets
315  * @rxq: RX queue driver structure
316  * @pidx: descriptor start point
317  * @budget: maximum Rx budget
318  *
319  * Determines how many Rx packets are available on the queue, up to a maximum
320  * of the given budget.
321  */
322 static int
323 _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget)
324 {
325 	union ice_32b_rx_flex_desc *rxd;
326 	uint16_t status0;
327 	int cnt, i, nrxd;
328 
329 	nrxd = rxq->desc_count;
330 
331 	for (cnt = 0, i = pidx; cnt < nrxd - 1 && cnt < budget;) {
332 		rxd = &rxq->rx_base[i];
333 		status0 = le16toh(rxd->wb.status_error0);
334 
335 		if ((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) == 0)
336 			break;
337 		if (++i == nrxd)
338 			i = 0;
339 		if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S))
340 			cnt++;
341 	}
342 
343 	return (cnt);
344 }
345 
346 /**
347  * ice_ift_rxd_available - Return number of available Rx packets
348  * @arg: device private softc
349  * @rxqid: the Rx queue id
350  * @pidx: descriptor start point
351  * @budget: maximum Rx budget
352  *
353  * Wrapper for _ice_ift_rxd_available() that provides a function pointer
354  * that iflib requires for RX processing.
355  */
356 static int
357 ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
358 {
359 	struct ice_softc *sc = (struct ice_softc *)arg;
360 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
361 
362 	return _ice_ift_rxd_available(rxq, pidx, budget);
363 }
364 
365 /**
366  * ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
367  * @arg: device specific softc
368  * @ri: receive packet info
369  *
370  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
371  * used by iflib for RX packet processing.
372  */
373 static int
374 ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
375 {
376 	struct ice_softc *sc = (struct ice_softc *)arg;
377 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[ri->iri_qsidx];
378 
379 	return _ice_ift_rxd_pkt_get(rxq, ri);
380 }
381 
382 /**
383  * _ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
384  * @rxq: RX queue driver structure
385  * @ri: receive packet info
386  *
387  * This function is called by iflib, and executes in ithread context. It is
388  * called by iflib to obtain data which has been DMA'ed into host memory.
389  * Returns zero on success, and EBADMSG on failure.
390  */
391 static int
392 _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri)
393 {
394 	union ice_32b_rx_flex_desc *cur;
395 	u16 status0, plen, ptype;
396 	bool eop;
397 	size_t cidx;
398 	int i;
399 
400 	cidx = ri->iri_cidx;
401 	i = 0;
402 	do {
403 		/* 5 descriptor receive limit */
404 		MPASS(i < ICE_MAX_RX_SEGS);
405 
406 		cur = &rxq->rx_base[cidx];
407 		status0 = le16toh(cur->wb.status_error0);
408 		plen = le16toh(cur->wb.pkt_len) &
409 			ICE_RX_FLX_DESC_PKT_LEN_M;
410 
411 		/* we should never be called without a valid descriptor */
412 		MPASS((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) != 0);
413 
414 		ri->iri_len += plen;
415 
416 		cur->wb.status_error0 = 0;
417 		eop = (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S));
418 
419 		ri->iri_frags[i].irf_flid = 0;
420 		ri->iri_frags[i].irf_idx = cidx;
421 		ri->iri_frags[i].irf_len = plen;
422 		if (++cidx == rxq->desc_count)
423 			cidx = 0;
424 		i++;
425 	} while (!eop);
426 
427 	/* End of Packet reached; cur is eop/last descriptor */
428 
429 	/* Make sure packets with bad L2 values are discarded.
430 	 * This bit is only valid in the last descriptor.
431 	 */
432 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S)) {
433 		rxq->stats.desc_errs++;
434 		return (EBADMSG);
435 	}
436 
437 	/* Get VLAN tag information if one is in descriptor */
438 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) {
439 		ri->iri_vtag = le16toh(cur->wb.l2tag1);
440 		ri->iri_flags |= M_VLANTAG;
441 	}
442 
443 	/* Capture soft statistics for this Rx queue */
444 	rxq->stats.rx_packets++;
445 	rxq->stats.rx_bytes += ri->iri_len;
446 
447 	/* Get packet type and set checksum flags */
448 	ptype = le16toh(cur->wb.ptype_flex_flags0) &
449 		ICE_RX_FLEX_DESC_PTYPE_M;
450 	if ((if_getcapenable(ri->iri_ifp) & IFCAP_RXCSUM) != 0)
451 		ice_rx_checksum(rxq, &ri->iri_csum_flags,
452 				&ri->iri_csum_data, status0, ptype);
453 
454 	/* Set remaining iflib RX descriptor info fields */
455 	ri->iri_flowid = le32toh(RX_FLEX_NIC(&cur->wb, rss_hash));
456 	ri->iri_rsstype = ice_ptype_to_hash(ptype);
457 	ri->iri_nfrags = i;
458 	return (0);
459 }
460 
461 /**
462  * ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
463  * @arg: device specific softc structure
464  * @iru: the Rx descriptor update structure
465  *
466  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
467  * used by iflib for RX packet processing.
468  */
469 static void
470 ice_ift_rxd_refill(void *arg, if_rxd_update_t iru)
471 {
472 	struct ice_softc *sc = (struct ice_softc *)arg;
473 	struct ice_rx_queue *rxq;
474 	uint64_t *paddrs;
475 	uint32_t pidx;
476 	uint16_t qsidx, count;
477 
478 	paddrs = iru->iru_paddrs;
479 	pidx = iru->iru_pidx;
480 	qsidx = iru->iru_qsidx;
481 	count = iru->iru_count;
482 
483 	rxq = &(sc->pf_vsi.rx_queues[qsidx]);
484 
485 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
486 }
487 
488 /**
489  * _ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
490  * @rxq: RX queue driver structure
491  * @pidx: first index to refill
492  * @paddrs: physical addresses to use
493  * @count: number of descriptors to refill
494  *
495  * Update the Rx descriptor indices for a given queue, assigning new physical
496  * addresses to the descriptors, preparing them for re-use by the hardware.
497  */
498 static void
499 _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx,
500 		    uint64_t *paddrs, uint16_t count)
501 {
502 	uint32_t next_pidx;
503 	int i;
504 
505 	for (i = 0, next_pidx = pidx; i < count; i++) {
506 		rxq->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
507 		if (++next_pidx == (uint32_t)rxq->desc_count)
508 			next_pidx = 0;
509 	}
510 }
511 
512 /**
513  * ice_ift_rxd_flush - Flush Rx descriptors to hardware
514  * @arg: device specific softc pointer
515  * @rxqid: the Rx queue to flush
516  * @flidx: unused parameter
517  * @pidx: descriptor index to advance tail to
518  *
519  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
520  * used by iflib for RX packet processing.
521  */
522 static void
523 ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx __unused,
524 		  qidx_t pidx)
525 {
526 	struct ice_softc *sc = (struct ice_softc *)arg;
527 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
528 
529 	_ice_ift_rxd_flush(sc, rxq, (uint32_t)pidx);
530 }
531 
532 /**
533  * _ice_ift_rxd_flush - Flush Rx descriptors to hardware
534  * @sc: device specific softc pointer
535  * @rxq: RX queue driver structure
536  * @pidx: descriptor index to advance tail to
537  *
538  * Advance the Receive Descriptor Tail (RDT). This indicates to hardware that
539  * software is done with the descriptor and it can be recycled.
540  */
541 static void
542 _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq, uint32_t pidx)
543 {
544 	wr32(&sc->hw, rxq->tail, pidx);
545 }
546 
547 /**
548  * ice_ift_queue_select - Select queue index to transmit packet on
549  * @arg: device specific softc
550  * @m: transmit packet data
551  * @pi: transmit packet metadata
552  *
553  * Called by iflib to determine which queue index to transmit the packet
554  * pointed to by @m on. In particular, ensures packets go out on the right
555  * queue index for the right transmit class when multiple traffic classes are
556  * enabled in the driver.
557  */
558 static qidx_t
559 ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi)
560 {
561 	struct ice_softc *sc = (struct ice_softc *)arg;
562 	struct ice_dcbx_cfg *local_dcbx_cfg;
563 	struct ice_vsi *vsi = &sc->pf_vsi;
564 	u16 tc_base_queue, tc_qcount;
565 	u8 up, tc;
566 
567 #ifdef ALTQ
568 	/* Included to match default iflib behavior */
569 	/* Only go out on default queue if ALTQ is enabled */
570 	struct ifnet *ifp = (struct ifnet *)iflib_get_ifp(sc->ctx);
571 	if (if_altq_is_enabled(ifp))
572 		return (0);
573 #endif
574 
575 	if (!ice_test_state(&sc->state, ICE_STATE_MULTIPLE_TCS)) {
576 		if (M_HASHTYPE_GET(m)) {
577 			/* Default iflib queue selection method */
578 			return (m->m_pkthdr.flowid % sc->pf_vsi.num_tx_queues);
579 		} else
580 			return (0);
581 	}
582 
583 	/* Use default TC unless overridden later */
584 	tc = 0; /* XXX: Get default TC for traffic if >1 TC? */
585 
586 	local_dcbx_cfg = &sc->hw.port_info->qos_cfg.local_dcbx_cfg;
587 
588 #if defined(INET) || defined(INET6)
589 	if ((local_dcbx_cfg->pfc_mode == ICE_QOS_MODE_DSCP) &&
590 	    (pi->ipi_flags & (IPI_TX_IPV4 | IPI_TX_IPV6))) {
591 		u8 dscp_val = pi->ipi_ip_tos >> 2;
592 		tc = local_dcbx_cfg->dscp_map[dscp_val];
593 	} else
594 #endif /* defined(INET) || defined(INET6) */
595 	if (m->m_flags & M_VLANTAG) { /* ICE_QOS_MODE_VLAN */
596 		up = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
597 		tc = local_dcbx_cfg->etscfg.prio_table[up];
598 	}
599 
600 	tc_base_queue = vsi->tc_info[tc].qoffset;
601 	tc_qcount = vsi->tc_info[tc].qcount_tx;
602 
603 	if (M_HASHTYPE_GET(m))
604 		return ((m->m_pkthdr.flowid % tc_qcount) + tc_base_queue);
605 	else
606 		return (tc_base_queue);
607 }
608 
609 /**
610  * ice_ift_txd_credits_update_subif - cleanup subinterface VSI Tx descriptors
611  * @arg: subinterface private structure (struct ice_mirr_if)
612  * @txqid: the Tx queue to update
613  * @clear: if false, only report, do not actually clean
614  *
615  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
616  * do not belong to the PF VSI.
617  *
618  * See _ice_ift_txd_credits_update().
619  */
620 static int
621 ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear)
622 {
623 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
624 	struct ice_softc *sc = mif->back;
625 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
626 
627 	return _ice_ift_txd_credits_update(sc, txq, clear);
628 }
629 
630 /**
631  * ice_ift_txd_encap_subif - prepare Tx descriptors for a packet
632  * @arg: subinterface private structure (struct ice_mirr_if)
633  * @pi: packet info
634  *
635  * Wrapper for _ice_ift_txd_encap_subif() meant for TX queues that
636  * do not belong to the PF VSI.
637  *
638  * See _ice_ift_txd_encap_subif().
639  */
640 static int
641 ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi)
642 {
643 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
644 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[pi->ipi_qsidx];
645 
646 	return _ice_ift_txd_encap(txq, pi);
647 }
648 
649 /**
650  * ice_ift_txd_flush_subif - Flush Tx descriptors to hardware
651  * @arg: subinterface private structure (struct ice_mirr_if)
652  * @txqid: the Tx queue to flush
653  * @pidx: descriptor index to advance tail to
654  *
655  * Advance the Transmit Descriptor Tail (TDT). Functionally identical to
656  * the ice_ift_txd_encap() meant for the main PF VSI, but provides a function
657  * pointer to iflib for use with non-main-PF VSI TX queues.
658  */
659 static void
660 ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx)
661 {
662 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
663 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
664 	struct ice_hw *hw = &mif->back->hw;
665 
666 	wr32(hw, txq->tail, pidx);
667 }
668 
669 /**
670  * ice_ift_rxd_available_subif - Return number of available Rx packets
671  * @arg: subinterface private structure (struct ice_mirr_if)
672  * @rxqid: the Rx queue id
673  * @pidx: descriptor start point
674  * @budget: maximum Rx budget
675  *
676  * Determines how many Rx packets are available on the queue, up to a maximum
677  * of the given budget.
678  *
679  * See _ice_ift_rxd_available().
680  */
681 static int
682 ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
683 {
684 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
685 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
686 
687 	return _ice_ift_rxd_available(rxq, pidx, budget);
688 }
689 
690 /**
691  * ice_ift_rxd_pkt_get_subif - Called by iflib to send data to upper layer
692  * @arg: subinterface private structure (struct ice_mirr_if)
693  * @ri: receive packet info
694  *
695  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
696  * used by iflib for RX packet processing, for iflib subinterfaces.
697  */
698 static int
699 ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri)
700 {
701 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
702 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[ri->iri_qsidx];
703 
704 	return _ice_ift_rxd_pkt_get(rxq, ri);
705 }
706 
707 /**
708  * ice_ift_rxd_refill_subif - Prepare Rx descriptors for re-use by hardware
709  * @arg: subinterface private structure (struct ice_mirr_if)
710  * @iru: the Rx descriptor update structure
711  *
712  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
713  * used by iflib for RX packet processing, for iflib subinterfaces.
714  */
715 static void
716 ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru)
717 {
718 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
719 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[iru->iru_qsidx];
720 
721 	uint64_t *paddrs;
722 	uint32_t pidx;
723 	uint16_t count;
724 
725 	paddrs = iru->iru_paddrs;
726 	pidx = iru->iru_pidx;
727 	count = iru->iru_count;
728 
729 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
730 }
731 
732 /**
733  * ice_ift_rxd_flush_subif - Flush Rx descriptors to hardware
734  * @arg: subinterface private structure (struct ice_mirr_if)
735  * @rxqid: the Rx queue to flush
736  * @flidx: unused parameter
737  * @pidx: descriptor index to advance tail to
738  *
739  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
740  * used by iflib for RX packet processing.
741  */
742 static void
743 ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx __unused,
744 			qidx_t pidx)
745 {
746 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
747 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
748 
749 	_ice_ift_rxd_flush(mif->back, rxq, pidx);
750 }
751