xref: /freebsd/sys/dev/ice/ice_iflib_txrx.c (revision 9e54973f)
171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2015f8cc5SEric Joyner /*  Copyright (c) 2024, Intel Corporation
371d10453SEric Joyner  *  All rights reserved.
471d10453SEric Joyner  *
571d10453SEric Joyner  *  Redistribution and use in source and binary forms, with or without
671d10453SEric Joyner  *  modification, are permitted provided that the following conditions are met:
771d10453SEric Joyner  *
871d10453SEric Joyner  *   1. Redistributions of source code must retain the above copyright notice,
971d10453SEric Joyner  *      this list of conditions and the following disclaimer.
1071d10453SEric Joyner  *
1171d10453SEric Joyner  *   2. Redistributions in binary form must reproduce the above copyright
1271d10453SEric Joyner  *      notice, this list of conditions and the following disclaimer in the
1371d10453SEric Joyner  *      documentation and/or other materials provided with the distribution.
1471d10453SEric Joyner  *
1571d10453SEric Joyner  *   3. Neither the name of the Intel Corporation nor the names of its
1671d10453SEric Joyner  *      contributors may be used to endorse or promote products derived from
1771d10453SEric Joyner  *      this software without specific prior written permission.
1871d10453SEric Joyner  *
1971d10453SEric Joyner  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2071d10453SEric Joyner  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2171d10453SEric Joyner  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2271d10453SEric Joyner  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2371d10453SEric Joyner  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2471d10453SEric Joyner  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2571d10453SEric Joyner  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2671d10453SEric Joyner  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2771d10453SEric Joyner  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2871d10453SEric Joyner  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2971d10453SEric Joyner  *  POSSIBILITY OF SUCH DAMAGE.
3071d10453SEric Joyner  */
3171d10453SEric Joyner 
3271d10453SEric Joyner /**
3371d10453SEric Joyner  * @file ice_iflib_txrx.c
3471d10453SEric Joyner  * @brief iflib Tx/Rx hotpath
3571d10453SEric Joyner  *
3671d10453SEric Joyner  * Main location for the iflib Tx/Rx hotpath implementation.
3771d10453SEric Joyner  *
3871d10453SEric Joyner  * Contains the implementation for the iflib function callbacks and the
3971d10453SEric Joyner  * if_txrx ops structure.
4071d10453SEric Joyner  */
4171d10453SEric Joyner 
4271d10453SEric Joyner #include "ice_iflib.h"
4371d10453SEric Joyner 
4471d10453SEric Joyner /* Tx/Rx hotpath utility functions */
4571d10453SEric Joyner #include "ice_common_txrx.h"
4671d10453SEric Joyner 
4771d10453SEric Joyner /*
489e54973fSEric Joyner  * Driver private implementations
499e54973fSEric Joyner  */
509e54973fSEric Joyner static int _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi);
519e54973fSEric Joyner static int _ice_ift_txd_credits_update(struct ice_softc *sc, struct ice_tx_queue *txq, bool clear);
529e54973fSEric Joyner static int _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget);
539e54973fSEric Joyner static int _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri);
549e54973fSEric Joyner static void _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx,
559e54973fSEric Joyner 				uint64_t *paddrs, uint16_t count);
569e54973fSEric Joyner static void _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq,
579e54973fSEric Joyner 			       uint32_t pidx);
589e54973fSEric Joyner 
599e54973fSEric Joyner /*
6071d10453SEric Joyner  * iflib txrx method declarations
6171d10453SEric Joyner  */
6271d10453SEric Joyner static int ice_ift_txd_encap(void *arg, if_pkt_info_t pi);
6371d10453SEric Joyner static int ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri);
6471d10453SEric Joyner static void ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
6571d10453SEric Joyner static int ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear);
6671d10453SEric Joyner static int ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget);
6771d10453SEric Joyner static void ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx);
6871d10453SEric Joyner static void ice_ift_rxd_refill(void *arg, if_rxd_update_t iru);
698923de59SPiotr Kubaj static qidx_t ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi);
709e54973fSEric Joyner static int ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear);
719e54973fSEric Joyner static int ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi);
729e54973fSEric Joyner static void ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx);
739e54973fSEric Joyner static int ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget);
749e54973fSEric Joyner static int ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri);
759e54973fSEric Joyner static void ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru);
769e54973fSEric Joyner static void ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx, qidx_t pidx);
7771d10453SEric Joyner 
7871d10453SEric Joyner /* Macro to help extract the NIC mode flexible Rx descriptor fields from the
7971d10453SEric Joyner  * advanced 32byte Rx descriptors.
8071d10453SEric Joyner  */
8171d10453SEric Joyner #define RX_FLEX_NIC(desc, field) \
8271d10453SEric Joyner 	(((struct ice_32b_rx_flex_desc_nic *)desc)->field)
8371d10453SEric Joyner 
8471d10453SEric Joyner /**
8571d10453SEric Joyner  * @var ice_txrx
8671d10453SEric Joyner  * @brief Tx/Rx operations for the iflib stack
8771d10453SEric Joyner  *
8871d10453SEric Joyner  * Structure defining the Tx and Rx related operations that iflib can request
8971d10453SEric Joyner  * the driver to perform. These are the main entry points for the hot path of
9071d10453SEric Joyner  * the transmit and receive paths in the iflib driver.
9171d10453SEric Joyner  */
9271d10453SEric Joyner struct if_txrx ice_txrx = {
9371d10453SEric Joyner 	.ift_txd_encap = ice_ift_txd_encap,
9471d10453SEric Joyner 	.ift_txd_flush = ice_ift_txd_flush,
9571d10453SEric Joyner 	.ift_txd_credits_update = ice_ift_txd_credits_update,
9671d10453SEric Joyner 	.ift_rxd_available = ice_ift_rxd_available,
9771d10453SEric Joyner 	.ift_rxd_pkt_get = ice_ift_rxd_pkt_get,
9871d10453SEric Joyner 	.ift_rxd_refill = ice_ift_rxd_refill,
9971d10453SEric Joyner 	.ift_rxd_flush = ice_ift_rxd_flush,
1008923de59SPiotr Kubaj 	.ift_txq_select_v2 = ice_ift_queue_select,
10171d10453SEric Joyner };
10271d10453SEric Joyner 
10371d10453SEric Joyner /**
1049e54973fSEric Joyner  * @var ice_subif_txrx
1059e54973fSEric Joyner  * @brief Tx/Rx operations for the iflib stack, for subinterfaces
1069e54973fSEric Joyner  *
1079e54973fSEric Joyner  * Structure defining the Tx and Rx related operations that iflib can request
1089e54973fSEric Joyner  * the subinterface driver to perform. These are the main entry points for the
1099e54973fSEric Joyner  * hot path of the transmit and receive paths in the iflib driver.
1109e54973fSEric Joyner  */
1119e54973fSEric Joyner struct if_txrx ice_subif_txrx = {
1129e54973fSEric Joyner 	.ift_txd_credits_update = ice_ift_txd_credits_update_subif,
1139e54973fSEric Joyner 	.ift_txd_encap = ice_ift_txd_encap_subif,
1149e54973fSEric Joyner 	.ift_txd_flush = ice_ift_txd_flush_subif,
1159e54973fSEric Joyner 	.ift_rxd_available = ice_ift_rxd_available_subif,
1169e54973fSEric Joyner 	.ift_rxd_pkt_get = ice_ift_rxd_pkt_get_subif,
1179e54973fSEric Joyner 	.ift_rxd_refill = ice_ift_rxd_refill_subif,
1189e54973fSEric Joyner 	.ift_rxd_flush = ice_ift_rxd_flush_subif,
1199e54973fSEric Joyner 	.ift_txq_select_v2 = NULL,
1209e54973fSEric Joyner };
1219e54973fSEric Joyner 
1229e54973fSEric Joyner /**
1239e54973fSEric Joyner  * _ice_ift_txd_encap - prepare Tx descriptors for a packet
1249e54973fSEric Joyner  * @txq: driver's TX queue context
12571d10453SEric Joyner  * @pi: packet info
12671d10453SEric Joyner  *
12771d10453SEric Joyner  * Prepares and encapsulates the given packet into into Tx descriptors, in
12871d10453SEric Joyner  * preparation for sending to the transmit engine. Sets the necessary context
12971d10453SEric Joyner  * descriptors for TSO and other offloads, and prepares the last descriptor
13071d10453SEric Joyner  * for the writeback status.
13171d10453SEric Joyner  *
13271d10453SEric Joyner  * Return 0 on success, non-zero error code on failure.
13371d10453SEric Joyner  */
13471d10453SEric Joyner static int
_ice_ift_txd_encap(struct ice_tx_queue * txq,if_pkt_info_t pi)1359e54973fSEric Joyner _ice_ift_txd_encap(struct ice_tx_queue *txq, if_pkt_info_t pi)
13671d10453SEric Joyner {
13771d10453SEric Joyner 	int nsegs = pi->ipi_nsegs;
13871d10453SEric Joyner 	bus_dma_segment_t *segs = pi->ipi_segs;
13971d10453SEric Joyner 	struct ice_tx_desc *txd = NULL;
14071d10453SEric Joyner 	int i, j, mask, pidx_last;
14171d10453SEric Joyner 	u32 cmd, off;
14271d10453SEric Joyner 
14371d10453SEric Joyner 	cmd = off = 0;
14471d10453SEric Joyner 	i = pi->ipi_pidx;
14571d10453SEric Joyner 
14671d10453SEric Joyner 	/* Set up the TSO/CSUM offload */
14771d10453SEric Joyner 	if (pi->ipi_csum_flags & ICE_CSUM_OFFLOAD) {
14871d10453SEric Joyner 		/* Set up the TSO context descriptor if required */
14971d10453SEric Joyner 		if (pi->ipi_csum_flags & CSUM_TSO) {
15071d10453SEric Joyner 			if (ice_tso_detect_sparse(pi))
15171d10453SEric Joyner 				return (EFBIG);
15271d10453SEric Joyner 			i = ice_tso_setup(txq, pi);
15371d10453SEric Joyner 		}
15471d10453SEric Joyner 		ice_tx_setup_offload(txq, pi, &cmd, &off);
15571d10453SEric Joyner 	}
15671d10453SEric Joyner 	if (pi->ipi_mflags & M_VLANTAG)
15771d10453SEric Joyner 		cmd |= ICE_TX_DESC_CMD_IL2TAG1;
15871d10453SEric Joyner 
15971d10453SEric Joyner 	mask = txq->desc_count - 1;
16071d10453SEric Joyner 	for (j = 0; j < nsegs; j++) {
16171d10453SEric Joyner 		bus_size_t seglen;
16271d10453SEric Joyner 
16371d10453SEric Joyner 		txd = &txq->tx_base[i];
16471d10453SEric Joyner 		seglen = segs[j].ds_len;
16571d10453SEric Joyner 
16671d10453SEric Joyner 		txd->buf_addr = htole64(segs[j].ds_addr);
16771d10453SEric Joyner 		txd->cmd_type_offset_bsz =
16871d10453SEric Joyner 		    htole64(ICE_TX_DESC_DTYPE_DATA
16971d10453SEric Joyner 		    | ((u64)cmd  << ICE_TXD_QW1_CMD_S)
17071d10453SEric Joyner 		    | ((u64)off << ICE_TXD_QW1_OFFSET_S)
17171d10453SEric Joyner 		    | ((u64)seglen  << ICE_TXD_QW1_TX_BUF_SZ_S)
17271d10453SEric Joyner 		    | ((u64)htole16(pi->ipi_vtag) << ICE_TXD_QW1_L2TAG1_S));
17371d10453SEric Joyner 
17471d10453SEric Joyner 		txq->stats.tx_bytes += seglen;
17571d10453SEric Joyner 		pidx_last = i;
17671d10453SEric Joyner 		i = (i+1) & mask;
17771d10453SEric Joyner 	}
17871d10453SEric Joyner 
17971d10453SEric Joyner 	/* Set the last descriptor for report */
18071d10453SEric Joyner #define ICE_TXD_CMD (ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS)
18171d10453SEric Joyner 	txd->cmd_type_offset_bsz |=
18271d10453SEric Joyner 	    htole64(((u64)ICE_TXD_CMD << ICE_TXD_QW1_CMD_S));
18371d10453SEric Joyner 
18471d10453SEric Joyner 	/* Add to report status array */
18571d10453SEric Joyner 	txq->tx_rsq[txq->tx_rs_pidx] = pidx_last;
18671d10453SEric Joyner 	txq->tx_rs_pidx = (txq->tx_rs_pidx+1) & mask;
18771d10453SEric Joyner 	MPASS(txq->tx_rs_pidx != txq->tx_rs_cidx);
18871d10453SEric Joyner 
18971d10453SEric Joyner 	pi->ipi_new_pidx = i;
19071d10453SEric Joyner 
19171d10453SEric Joyner 	++txq->stats.tx_packets;
19271d10453SEric Joyner 	return (0);
19371d10453SEric Joyner }
19471d10453SEric Joyner 
19571d10453SEric Joyner /**
1969e54973fSEric Joyner  * ice_ift_txd_encap - prepare Tx descriptors for a packet
1979e54973fSEric Joyner  * @arg: the iflib softc structure pointer
1989e54973fSEric Joyner  * @pi: packet info
1999e54973fSEric Joyner  *
2009e54973fSEric Joyner  * Prepares and encapsulates the given packet into Tx descriptors, in
2019e54973fSEric Joyner  * preparation for sending to the transmit engine. Sets the necessary context
2029e54973fSEric Joyner  * descriptors for TSO and other offloads, and prepares the last descriptor
2039e54973fSEric Joyner  * for the writeback status.
2049e54973fSEric Joyner  *
2059e54973fSEric Joyner  * Return 0 on success, non-zero error code on failure.
2069e54973fSEric Joyner  */
2079e54973fSEric Joyner static int
ice_ift_txd_encap(void * arg,if_pkt_info_t pi)2089e54973fSEric Joyner ice_ift_txd_encap(void *arg, if_pkt_info_t pi)
2099e54973fSEric Joyner {
2109e54973fSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
2119e54973fSEric Joyner 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[pi->ipi_qsidx];
2129e54973fSEric Joyner 
2139e54973fSEric Joyner 	return _ice_ift_txd_encap(txq, pi);
2149e54973fSEric Joyner }
2159e54973fSEric Joyner 
2169e54973fSEric Joyner /**
21771d10453SEric Joyner  * ice_ift_txd_flush - Flush Tx descriptors to hardware
21871d10453SEric Joyner  * @arg: device specific softc pointer
21971d10453SEric Joyner  * @txqid: the Tx queue to flush
22071d10453SEric Joyner  * @pidx: descriptor index to advance tail to
22171d10453SEric Joyner  *
22271d10453SEric Joyner  * Advance the Transmit Descriptor Tail (TDT). This indicates to hardware that
22371d10453SEric Joyner  * frames are available for transmit.
22471d10453SEric Joyner  */
22571d10453SEric Joyner static void
ice_ift_txd_flush(void * arg,uint16_t txqid,qidx_t pidx)22671d10453SEric Joyner ice_ift_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
22771d10453SEric Joyner {
22871d10453SEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
22971d10453SEric Joyner 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
23071d10453SEric Joyner 	struct ice_hw *hw = &sc->hw;
23171d10453SEric Joyner 
23271d10453SEric Joyner 	wr32(hw, txq->tail, pidx);
23371d10453SEric Joyner }
23471d10453SEric Joyner 
23571d10453SEric Joyner /**
2369e54973fSEric Joyner  * _ice_ift_txd_credits_update - cleanup Tx descriptors
2379e54973fSEric Joyner  * @sc: device private softc
2389e54973fSEric Joyner  * @txq: the Tx queue to update
23971d10453SEric Joyner  * @clear: if false, only report, do not actually clean
24071d10453SEric Joyner  *
24171d10453SEric Joyner  * If clear is false, iflib is asking if we *could* clean up any Tx
24271d10453SEric Joyner  * descriptors.
24371d10453SEric Joyner  *
24471d10453SEric Joyner  * If clear is true, iflib is requesting to cleanup and reclaim used Tx
24571d10453SEric Joyner  * descriptors.
2469e54973fSEric Joyner  *
2479e54973fSEric Joyner  * Called by other txd_credits_update functions passed to iflib.
24871d10453SEric Joyner  */
24971d10453SEric Joyner static int
_ice_ift_txd_credits_update(struct ice_softc * sc __unused,struct ice_tx_queue * txq,bool clear)2509e54973fSEric Joyner _ice_ift_txd_credits_update(struct ice_softc *sc __unused, struct ice_tx_queue *txq, bool clear)
25171d10453SEric Joyner {
25271d10453SEric Joyner 	qidx_t processed = 0;
25371d10453SEric Joyner 	qidx_t cur, prev, ntxd, rs_cidx;
25471d10453SEric Joyner 	int32_t delta;
25571d10453SEric Joyner 	bool is_done;
25671d10453SEric Joyner 
25771d10453SEric Joyner 	rs_cidx = txq->tx_rs_cidx;
25871d10453SEric Joyner 	if (rs_cidx == txq->tx_rs_pidx)
25971d10453SEric Joyner 		return (0);
26071d10453SEric Joyner 	cur = txq->tx_rsq[rs_cidx];
26171d10453SEric Joyner 	MPASS(cur != QIDX_INVALID);
26271d10453SEric Joyner 	is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
26371d10453SEric Joyner 
26471d10453SEric Joyner 	if (!is_done)
26571d10453SEric Joyner 		return (0);
26671d10453SEric Joyner 	else if (clear == false)
26771d10453SEric Joyner 		return (1);
26871d10453SEric Joyner 
26971d10453SEric Joyner 	prev = txq->tx_cidx_processed;
27071d10453SEric Joyner 	ntxd = txq->desc_count;
27171d10453SEric Joyner 	do {
27271d10453SEric Joyner 		MPASS(prev != cur);
27371d10453SEric Joyner 		delta = (int32_t)cur - (int32_t)prev;
27471d10453SEric Joyner 		if (delta < 0)
27571d10453SEric Joyner 			delta += ntxd;
27671d10453SEric Joyner 		MPASS(delta > 0);
27771d10453SEric Joyner 		processed += delta;
27871d10453SEric Joyner 		prev = cur;
27971d10453SEric Joyner 		rs_cidx = (rs_cidx + 1) & (ntxd-1);
28071d10453SEric Joyner 		if (rs_cidx == txq->tx_rs_pidx)
28171d10453SEric Joyner 			break;
28271d10453SEric Joyner 		cur = txq->tx_rsq[rs_cidx];
28371d10453SEric Joyner 		MPASS(cur != QIDX_INVALID);
28471d10453SEric Joyner 		is_done = ice_is_tx_desc_done(&txq->tx_base[cur]);
28571d10453SEric Joyner 	} while (is_done);
28671d10453SEric Joyner 
28771d10453SEric Joyner 	txq->tx_rs_cidx = rs_cidx;
28871d10453SEric Joyner 	txq->tx_cidx_processed = prev;
28971d10453SEric Joyner 
29071d10453SEric Joyner 	return (processed);
29171d10453SEric Joyner }
29271d10453SEric Joyner 
29371d10453SEric Joyner /**
2949e54973fSEric Joyner  * ice_ift_txd_credits_update - cleanup PF VSI Tx descriptors
29571d10453SEric Joyner  * @arg: device private softc
2969e54973fSEric Joyner  * @txqid: the Tx queue to update
2979e54973fSEric Joyner  * @clear: if false, only report, do not actually clean
2989e54973fSEric Joyner  *
2999e54973fSEric Joyner  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
3009e54973fSEric Joyner  * belong to the PF VSI.
3019e54973fSEric Joyner  *
3029e54973fSEric Joyner  * @see _ice_ift_txd_credits_update()
3039e54973fSEric Joyner  */
3049e54973fSEric Joyner static int
ice_ift_txd_credits_update(void * arg,uint16_t txqid,bool clear)3059e54973fSEric Joyner ice_ift_txd_credits_update(void *arg, uint16_t txqid, bool clear)
3069e54973fSEric Joyner {
3079e54973fSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
3089e54973fSEric Joyner 	struct ice_tx_queue *txq = &sc->pf_vsi.tx_queues[txqid];
3099e54973fSEric Joyner 
3109e54973fSEric Joyner 	return _ice_ift_txd_credits_update(sc, txq, clear);
3119e54973fSEric Joyner }
3129e54973fSEric Joyner 
3139e54973fSEric Joyner /**
3149e54973fSEric Joyner  * _ice_ift_rxd_available - Return number of available Rx packets
3159e54973fSEric Joyner  * @rxq: RX queue driver structure
31671d10453SEric Joyner  * @pidx: descriptor start point
31771d10453SEric Joyner  * @budget: maximum Rx budget
31871d10453SEric Joyner  *
31971d10453SEric Joyner  * Determines how many Rx packets are available on the queue, up to a maximum
32071d10453SEric Joyner  * of the given budget.
32171d10453SEric Joyner  */
32271d10453SEric Joyner static int
_ice_ift_rxd_available(struct ice_rx_queue * rxq,qidx_t pidx,qidx_t budget)3239e54973fSEric Joyner _ice_ift_rxd_available(struct ice_rx_queue *rxq, qidx_t pidx, qidx_t budget)
32471d10453SEric Joyner {
32571d10453SEric Joyner 	union ice_32b_rx_flex_desc *rxd;
32671d10453SEric Joyner 	uint16_t status0;
32771d10453SEric Joyner 	int cnt, i, nrxd;
32871d10453SEric Joyner 
32971d10453SEric Joyner 	nrxd = rxq->desc_count;
33071d10453SEric Joyner 
33171d10453SEric Joyner 	for (cnt = 0, i = pidx; cnt < nrxd - 1 && cnt < budget;) {
33271d10453SEric Joyner 		rxd = &rxq->rx_base[i];
33371d10453SEric Joyner 		status0 = le16toh(rxd->wb.status_error0);
33471d10453SEric Joyner 
33571d10453SEric Joyner 		if ((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) == 0)
33671d10453SEric Joyner 			break;
33771d10453SEric Joyner 		if (++i == nrxd)
33871d10453SEric Joyner 			i = 0;
33971d10453SEric Joyner 		if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S))
34071d10453SEric Joyner 			cnt++;
34171d10453SEric Joyner 	}
34271d10453SEric Joyner 
34371d10453SEric Joyner 	return (cnt);
34471d10453SEric Joyner }
34571d10453SEric Joyner 
34671d10453SEric Joyner /**
3479e54973fSEric Joyner  * ice_ift_rxd_available - Return number of available Rx packets
3489e54973fSEric Joyner  * @arg: device private softc
3499e54973fSEric Joyner  * @rxqid: the Rx queue id
3509e54973fSEric Joyner  * @pidx: descriptor start point
3519e54973fSEric Joyner  * @budget: maximum Rx budget
3529e54973fSEric Joyner  *
3539e54973fSEric Joyner  * Wrapper for _ice_ift_rxd_available() that provides a function pointer
3549e54973fSEric Joyner  * that iflib requires for RX processing.
3559e54973fSEric Joyner  */
3569e54973fSEric Joyner static int
ice_ift_rxd_available(void * arg,uint16_t rxqid,qidx_t pidx,qidx_t budget)3579e54973fSEric Joyner ice_ift_rxd_available(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
3589e54973fSEric Joyner {
3599e54973fSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
3609e54973fSEric Joyner 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
3619e54973fSEric Joyner 
3629e54973fSEric Joyner 	return _ice_ift_rxd_available(rxq, pidx, budget);
3639e54973fSEric Joyner }
3649e54973fSEric Joyner 
3659e54973fSEric Joyner /**
36671d10453SEric Joyner  * ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
36771d10453SEric Joyner  * @arg: device specific softc
36871d10453SEric Joyner  * @ri: receive packet info
36971d10453SEric Joyner  *
3709e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
3719e54973fSEric Joyner  * used by iflib for RX packet processing.
3729e54973fSEric Joyner  */
3739e54973fSEric Joyner static int
ice_ift_rxd_pkt_get(void * arg,if_rxd_info_t ri)3749e54973fSEric Joyner ice_ift_rxd_pkt_get(void *arg, if_rxd_info_t ri)
3759e54973fSEric Joyner {
3769e54973fSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
3779e54973fSEric Joyner 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[ri->iri_qsidx];
3789e54973fSEric Joyner 
3799e54973fSEric Joyner 	return _ice_ift_rxd_pkt_get(rxq, ri);
3809e54973fSEric Joyner }
3819e54973fSEric Joyner 
3829e54973fSEric Joyner /**
3839e54973fSEric Joyner  * _ice_ift_rxd_pkt_get - Called by iflib to send data to upper layer
3849e54973fSEric Joyner  * @rxq: RX queue driver structure
3859e54973fSEric Joyner  * @ri: receive packet info
3869e54973fSEric Joyner  *
38771d10453SEric Joyner  * This function is called by iflib, and executes in ithread context. It is
38871d10453SEric Joyner  * called by iflib to obtain data which has been DMA'ed into host memory.
38956429daeSEric Joyner  * Returns zero on success, and EBADMSG on failure.
39071d10453SEric Joyner  */
39171d10453SEric Joyner static int
_ice_ift_rxd_pkt_get(struct ice_rx_queue * rxq,if_rxd_info_t ri)3929e54973fSEric Joyner _ice_ift_rxd_pkt_get(struct ice_rx_queue *rxq, if_rxd_info_t ri)
39371d10453SEric Joyner {
39471d10453SEric Joyner 	union ice_32b_rx_flex_desc *cur;
395f7926a6dSVincenzo Maffione 	u16 status0, plen, ptype;
39671d10453SEric Joyner 	bool eop;
39771d10453SEric Joyner 	size_t cidx;
39871d10453SEric Joyner 	int i;
39971d10453SEric Joyner 
40071d10453SEric Joyner 	cidx = ri->iri_cidx;
40171d10453SEric Joyner 	i = 0;
40271d10453SEric Joyner 	do {
40371d10453SEric Joyner 		/* 5 descriptor receive limit */
40471d10453SEric Joyner 		MPASS(i < ICE_MAX_RX_SEGS);
40571d10453SEric Joyner 
40671d10453SEric Joyner 		cur = &rxq->rx_base[cidx];
40771d10453SEric Joyner 		status0 = le16toh(cur->wb.status_error0);
40871d10453SEric Joyner 		plen = le16toh(cur->wb.pkt_len) &
40971d10453SEric Joyner 			ICE_RX_FLX_DESC_PKT_LEN_M;
41071d10453SEric Joyner 
41171d10453SEric Joyner 		/* we should never be called without a valid descriptor */
41271d10453SEric Joyner 		MPASS((status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) != 0);
41371d10453SEric Joyner 
41471d10453SEric Joyner 		ri->iri_len += plen;
41571d10453SEric Joyner 
41671d10453SEric Joyner 		cur->wb.status_error0 = 0;
41771d10453SEric Joyner 		eop = (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S));
41871d10453SEric Joyner 
41971d10453SEric Joyner 		ri->iri_frags[i].irf_flid = 0;
42071d10453SEric Joyner 		ri->iri_frags[i].irf_idx = cidx;
42171d10453SEric Joyner 		ri->iri_frags[i].irf_len = plen;
42271d10453SEric Joyner 		if (++cidx == rxq->desc_count)
42371d10453SEric Joyner 			cidx = 0;
42471d10453SEric Joyner 		i++;
42571d10453SEric Joyner 	} while (!eop);
42671d10453SEric Joyner 
42756429daeSEric Joyner 	/* End of Packet reached; cur is eop/last descriptor */
42871d10453SEric Joyner 
42956429daeSEric Joyner 	/* Make sure packets with bad L2 values are discarded.
43056429daeSEric Joyner 	 * This bit is only valid in the last descriptor.
43156429daeSEric Joyner 	 */
43256429daeSEric Joyner 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S)) {
43356429daeSEric Joyner 		rxq->stats.desc_errs++;
43456429daeSEric Joyner 		return (EBADMSG);
43556429daeSEric Joyner 	}
43656429daeSEric Joyner 
43756429daeSEric Joyner 	/* Get VLAN tag information if one is in descriptor */
438f7926a6dSVincenzo Maffione 	if (status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S)) {
439f7926a6dSVincenzo Maffione 		ri->iri_vtag = le16toh(cur->wb.l2tag1);
44071d10453SEric Joyner 		ri->iri_flags |= M_VLANTAG;
441f7926a6dSVincenzo Maffione 	}
44256429daeSEric Joyner 
44356429daeSEric Joyner 	/* Capture soft statistics for this Rx queue */
44456429daeSEric Joyner 	rxq->stats.rx_packets++;
44556429daeSEric Joyner 	rxq->stats.rx_bytes += ri->iri_len;
44656429daeSEric Joyner 
44756429daeSEric Joyner 	/* Get packet type and set checksum flags */
44856429daeSEric Joyner 	ptype = le16toh(cur->wb.ptype_flex_flags0) &
44956429daeSEric Joyner 		ICE_RX_FLEX_DESC_PTYPE_M;
4509e54973fSEric Joyner 	if ((if_getcapenable(ri->iri_ifp) & IFCAP_RXCSUM) != 0)
45156429daeSEric Joyner 		ice_rx_checksum(rxq, &ri->iri_csum_flags,
45256429daeSEric Joyner 				&ri->iri_csum_data, status0, ptype);
45356429daeSEric Joyner 
45456429daeSEric Joyner 	/* Set remaining iflib RX descriptor info fields */
45556429daeSEric Joyner 	ri->iri_flowid = le32toh(RX_FLEX_NIC(&cur->wb, rss_hash));
45656429daeSEric Joyner 	ri->iri_rsstype = ice_ptype_to_hash(ptype);
457f7926a6dSVincenzo Maffione 	ri->iri_nfrags = i;
45871d10453SEric Joyner 	return (0);
45971d10453SEric Joyner }
46071d10453SEric Joyner 
46171d10453SEric Joyner /**
46271d10453SEric Joyner  * ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
46371d10453SEric Joyner  * @arg: device specific softc structure
46471d10453SEric Joyner  * @iru: the Rx descriptor update structure
46571d10453SEric Joyner  *
4669e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
4679e54973fSEric Joyner  * used by iflib for RX packet processing.
46871d10453SEric Joyner  */
46971d10453SEric Joyner static void
ice_ift_rxd_refill(void * arg,if_rxd_update_t iru)47071d10453SEric Joyner ice_ift_rxd_refill(void *arg, if_rxd_update_t iru)
47171d10453SEric Joyner {
47271d10453SEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
47371d10453SEric Joyner 	struct ice_rx_queue *rxq;
47471d10453SEric Joyner 	uint64_t *paddrs;
47571d10453SEric Joyner 	uint32_t pidx;
47671d10453SEric Joyner 	uint16_t qsidx, count;
47771d10453SEric Joyner 
47871d10453SEric Joyner 	paddrs = iru->iru_paddrs;
47971d10453SEric Joyner 	pidx = iru->iru_pidx;
48071d10453SEric Joyner 	qsidx = iru->iru_qsidx;
48171d10453SEric Joyner 	count = iru->iru_count;
48271d10453SEric Joyner 
48371d10453SEric Joyner 	rxq = &(sc->pf_vsi.rx_queues[qsidx]);
48471d10453SEric Joyner 
4859e54973fSEric Joyner 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
4869e54973fSEric Joyner }
4879e54973fSEric Joyner 
4889e54973fSEric Joyner /**
4899e54973fSEric Joyner  * _ice_ift_rxd_refill - Prepare Rx descriptors for re-use by hardware
4909e54973fSEric Joyner  * @rxq: RX queue driver structure
4919e54973fSEric Joyner  * @pidx: first index to refill
4929e54973fSEric Joyner  * @paddrs: physical addresses to use
4939e54973fSEric Joyner  * @count: number of descriptors to refill
4949e54973fSEric Joyner  *
4959e54973fSEric Joyner  * Update the Rx descriptor indices for a given queue, assigning new physical
4969e54973fSEric Joyner  * addresses to the descriptors, preparing them for re-use by the hardware.
4979e54973fSEric Joyner  */
4989e54973fSEric Joyner static void
_ice_ift_rxd_refill(struct ice_rx_queue * rxq,uint32_t pidx,uint64_t * paddrs,uint16_t count)4999e54973fSEric Joyner _ice_ift_rxd_refill(struct ice_rx_queue *rxq, uint32_t pidx,
5009e54973fSEric Joyner 		    uint64_t *paddrs, uint16_t count)
5019e54973fSEric Joyner {
5029e54973fSEric Joyner 	uint32_t next_pidx;
5039e54973fSEric Joyner 	int i;
5049e54973fSEric Joyner 
50571d10453SEric Joyner 	for (i = 0, next_pidx = pidx; i < count; i++) {
50671d10453SEric Joyner 		rxq->rx_base[next_pidx].read.pkt_addr = htole64(paddrs[i]);
50771d10453SEric Joyner 		if (++next_pidx == (uint32_t)rxq->desc_count)
50871d10453SEric Joyner 			next_pidx = 0;
50971d10453SEric Joyner 	}
51071d10453SEric Joyner }
51171d10453SEric Joyner 
51271d10453SEric Joyner /**
51371d10453SEric Joyner  * ice_ift_rxd_flush - Flush Rx descriptors to hardware
51471d10453SEric Joyner  * @arg: device specific softc pointer
51571d10453SEric Joyner  * @rxqid: the Rx queue to flush
51671d10453SEric Joyner  * @flidx: unused parameter
51771d10453SEric Joyner  * @pidx: descriptor index to advance tail to
51871d10453SEric Joyner  *
5199e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
5209e54973fSEric Joyner  * used by iflib for RX packet processing.
52171d10453SEric Joyner  */
52271d10453SEric Joyner static void
ice_ift_rxd_flush(void * arg,uint16_t rxqid,uint8_t flidx __unused,qidx_t pidx)52371d10453SEric Joyner ice_ift_rxd_flush(void *arg, uint16_t rxqid, uint8_t flidx __unused,
52471d10453SEric Joyner 		  qidx_t pidx)
52571d10453SEric Joyner {
52671d10453SEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
52771d10453SEric Joyner 	struct ice_rx_queue *rxq = &sc->pf_vsi.rx_queues[rxqid];
52871d10453SEric Joyner 
5299e54973fSEric Joyner 	_ice_ift_rxd_flush(sc, rxq, (uint32_t)pidx);
53071d10453SEric Joyner }
53156429daeSEric Joyner 
5329e54973fSEric Joyner /**
5339e54973fSEric Joyner  * _ice_ift_rxd_flush - Flush Rx descriptors to hardware
5349e54973fSEric Joyner  * @sc: device specific softc pointer
5359e54973fSEric Joyner  * @rxq: RX queue driver structure
5369e54973fSEric Joyner  * @pidx: descriptor index to advance tail to
5379e54973fSEric Joyner  *
5389e54973fSEric Joyner  * Advance the Receive Descriptor Tail (RDT). This indicates to hardware that
5399e54973fSEric Joyner  * software is done with the descriptor and it can be recycled.
5409e54973fSEric Joyner  */
5419e54973fSEric Joyner static void
_ice_ift_rxd_flush(struct ice_softc * sc,struct ice_rx_queue * rxq,uint32_t pidx)5429e54973fSEric Joyner _ice_ift_rxd_flush(struct ice_softc *sc, struct ice_rx_queue *rxq, uint32_t pidx)
5439e54973fSEric Joyner {
5449e54973fSEric Joyner 	wr32(&sc->hw, rxq->tail, pidx);
5459e54973fSEric Joyner }
5469e54973fSEric Joyner 
5479e54973fSEric Joyner /**
5489e54973fSEric Joyner  * ice_ift_queue_select - Select queue index to transmit packet on
5499e54973fSEric Joyner  * @arg: device specific softc
5509e54973fSEric Joyner  * @m: transmit packet data
5519e54973fSEric Joyner  * @pi: transmit packet metadata
5529e54973fSEric Joyner  *
5539e54973fSEric Joyner  * Called by iflib to determine which queue index to transmit the packet
5549e54973fSEric Joyner  * pointed to by @m on. In particular, ensures packets go out on the right
5559e54973fSEric Joyner  * queue index for the right transmit class when multiple traffic classes are
5569e54973fSEric Joyner  * enabled in the driver.
5579e54973fSEric Joyner  */
55856429daeSEric Joyner static qidx_t
ice_ift_queue_select(void * arg,struct mbuf * m,if_pkt_info_t pi)5598923de59SPiotr Kubaj ice_ift_queue_select(void *arg, struct mbuf *m, if_pkt_info_t pi)
56056429daeSEric Joyner {
56156429daeSEric Joyner 	struct ice_softc *sc = (struct ice_softc *)arg;
5628923de59SPiotr Kubaj 	struct ice_dcbx_cfg *local_dcbx_cfg;
56356429daeSEric Joyner 	struct ice_vsi *vsi = &sc->pf_vsi;
56456429daeSEric Joyner 	u16 tc_base_queue, tc_qcount;
56556429daeSEric Joyner 	u8 up, tc;
56656429daeSEric Joyner 
56761d83041SEric Joyner #ifdef ALTQ
56861d83041SEric Joyner 	/* Included to match default iflib behavior */
56956429daeSEric Joyner 	/* Only go out on default queue if ALTQ is enabled */
57061d83041SEric Joyner 	struct ifnet *ifp = (struct ifnet *)iflib_get_ifp(sc->ctx);
5718d5feedeSJustin Hibbits 	if (if_altq_is_enabled(ifp))
57256429daeSEric Joyner 		return (0);
57361d83041SEric Joyner #endif
57456429daeSEric Joyner 
57556429daeSEric Joyner 	if (!ice_test_state(&sc->state, ICE_STATE_MULTIPLE_TCS)) {
57656429daeSEric Joyner 		if (M_HASHTYPE_GET(m)) {
57756429daeSEric Joyner 			/* Default iflib queue selection method */
57856429daeSEric Joyner 			return (m->m_pkthdr.flowid % sc->pf_vsi.num_tx_queues);
57956429daeSEric Joyner 		} else
58056429daeSEric Joyner 			return (0);
58156429daeSEric Joyner 	}
58256429daeSEric Joyner 
5838923de59SPiotr Kubaj 	/* Use default TC unless overridden later */
58456429daeSEric Joyner 	tc = 0; /* XXX: Get default TC for traffic if >1 TC? */
58556429daeSEric Joyner 
5868923de59SPiotr Kubaj 	local_dcbx_cfg = &sc->hw.port_info->qos_cfg.local_dcbx_cfg;
5878923de59SPiotr Kubaj 
5888923de59SPiotr Kubaj #if defined(INET) || defined(INET6)
5898923de59SPiotr Kubaj 	if ((local_dcbx_cfg->pfc_mode == ICE_QOS_MODE_DSCP) &&
5908923de59SPiotr Kubaj 	    (pi->ipi_flags & (IPI_TX_IPV4 | IPI_TX_IPV6))) {
5918923de59SPiotr Kubaj 		u8 dscp_val = pi->ipi_ip_tos >> 2;
5928923de59SPiotr Kubaj 		tc = local_dcbx_cfg->dscp_map[dscp_val];
5938923de59SPiotr Kubaj 	} else
5948923de59SPiotr Kubaj #endif /* defined(INET) || defined(INET6) */
5958923de59SPiotr Kubaj 	if (m->m_flags & M_VLANTAG) { /* ICE_QOS_MODE_VLAN */
59656429daeSEric Joyner 		up = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
5978923de59SPiotr Kubaj 		tc = local_dcbx_cfg->etscfg.prio_table[up];
59856429daeSEric Joyner 	}
59956429daeSEric Joyner 
60056429daeSEric Joyner 	tc_base_queue = vsi->tc_info[tc].qoffset;
60156429daeSEric Joyner 	tc_qcount = vsi->tc_info[tc].qcount_tx;
60256429daeSEric Joyner 
60356429daeSEric Joyner 	if (M_HASHTYPE_GET(m))
60456429daeSEric Joyner 		return ((m->m_pkthdr.flowid % tc_qcount) + tc_base_queue);
60556429daeSEric Joyner 	else
60656429daeSEric Joyner 		return (tc_base_queue);
60756429daeSEric Joyner }
6089e54973fSEric Joyner 
6099e54973fSEric Joyner /**
6109e54973fSEric Joyner  * ice_ift_txd_credits_update_subif - cleanup subinterface VSI Tx descriptors
6119e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
6129e54973fSEric Joyner  * @txqid: the Tx queue to update
6139e54973fSEric Joyner  * @clear: if false, only report, do not actually clean
6149e54973fSEric Joyner  *
6159e54973fSEric Joyner  * Wrapper for _ice_ift_txd_credits_update() meant for TX queues that
6169e54973fSEric Joyner  * do not belong to the PF VSI.
6179e54973fSEric Joyner  *
6189e54973fSEric Joyner  * See _ice_ift_txd_credits_update().
6199e54973fSEric Joyner  */
6209e54973fSEric Joyner static int
ice_ift_txd_credits_update_subif(void * arg,uint16_t txqid,bool clear)6219e54973fSEric Joyner ice_ift_txd_credits_update_subif(void *arg, uint16_t txqid, bool clear)
6229e54973fSEric Joyner {
6239e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
6249e54973fSEric Joyner 	struct ice_softc *sc = mif->back;
6259e54973fSEric Joyner 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
6269e54973fSEric Joyner 
6279e54973fSEric Joyner 	return _ice_ift_txd_credits_update(sc, txq, clear);
6289e54973fSEric Joyner }
6299e54973fSEric Joyner 
6309e54973fSEric Joyner /**
6319e54973fSEric Joyner  * ice_ift_txd_encap_subif - prepare Tx descriptors for a packet
6329e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
6339e54973fSEric Joyner  * @pi: packet info
6349e54973fSEric Joyner  *
6359e54973fSEric Joyner  * Wrapper for _ice_ift_txd_encap_subif() meant for TX queues that
6369e54973fSEric Joyner  * do not belong to the PF VSI.
6379e54973fSEric Joyner  *
6389e54973fSEric Joyner  * See _ice_ift_txd_encap_subif().
6399e54973fSEric Joyner  */
6409e54973fSEric Joyner static int
ice_ift_txd_encap_subif(void * arg,if_pkt_info_t pi)6419e54973fSEric Joyner ice_ift_txd_encap_subif(void *arg, if_pkt_info_t pi)
6429e54973fSEric Joyner {
6439e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
6449e54973fSEric Joyner 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[pi->ipi_qsidx];
6459e54973fSEric Joyner 
6469e54973fSEric Joyner 	return _ice_ift_txd_encap(txq, pi);
6479e54973fSEric Joyner }
6489e54973fSEric Joyner 
6499e54973fSEric Joyner /**
6509e54973fSEric Joyner  * ice_ift_txd_flush_subif - Flush Tx descriptors to hardware
6519e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
6529e54973fSEric Joyner  * @txqid: the Tx queue to flush
6539e54973fSEric Joyner  * @pidx: descriptor index to advance tail to
6549e54973fSEric Joyner  *
6559e54973fSEric Joyner  * Advance the Transmit Descriptor Tail (TDT). Functionally identical to
6569e54973fSEric Joyner  * the ice_ift_txd_encap() meant for the main PF VSI, but provides a function
6579e54973fSEric Joyner  * pointer to iflib for use with non-main-PF VSI TX queues.
6589e54973fSEric Joyner  */
6599e54973fSEric Joyner static void
ice_ift_txd_flush_subif(void * arg,uint16_t txqid,qidx_t pidx)6609e54973fSEric Joyner ice_ift_txd_flush_subif(void *arg, uint16_t txqid, qidx_t pidx)
6619e54973fSEric Joyner {
6629e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
6639e54973fSEric Joyner 	struct ice_tx_queue *txq = &mif->vsi->tx_queues[txqid];
6649e54973fSEric Joyner 	struct ice_hw *hw = &mif->back->hw;
6659e54973fSEric Joyner 
6669e54973fSEric Joyner 	wr32(hw, txq->tail, pidx);
6679e54973fSEric Joyner }
6689e54973fSEric Joyner 
6699e54973fSEric Joyner /**
6709e54973fSEric Joyner  * ice_ift_rxd_available_subif - Return number of available Rx packets
6719e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
6729e54973fSEric Joyner  * @rxqid: the Rx queue id
6739e54973fSEric Joyner  * @pidx: descriptor start point
6749e54973fSEric Joyner  * @budget: maximum Rx budget
6759e54973fSEric Joyner  *
6769e54973fSEric Joyner  * Determines how many Rx packets are available on the queue, up to a maximum
6779e54973fSEric Joyner  * of the given budget.
6789e54973fSEric Joyner  *
6799e54973fSEric Joyner  * See _ice_ift_rxd_available().
6809e54973fSEric Joyner  */
6819e54973fSEric Joyner static int
ice_ift_rxd_available_subif(void * arg,uint16_t rxqid,qidx_t pidx,qidx_t budget)6829e54973fSEric Joyner ice_ift_rxd_available_subif(void *arg, uint16_t rxqid, qidx_t pidx, qidx_t budget)
6839e54973fSEric Joyner {
6849e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
6859e54973fSEric Joyner 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
6869e54973fSEric Joyner 
6879e54973fSEric Joyner 	return _ice_ift_rxd_available(rxq, pidx, budget);
6889e54973fSEric Joyner }
6899e54973fSEric Joyner 
6909e54973fSEric Joyner /**
6919e54973fSEric Joyner  * ice_ift_rxd_pkt_get_subif - Called by iflib to send data to upper layer
6929e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
6939e54973fSEric Joyner  * @ri: receive packet info
6949e54973fSEric Joyner  *
6959e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_pkt_get() that provides a function pointer
6969e54973fSEric Joyner  * used by iflib for RX packet processing, for iflib subinterfaces.
6979e54973fSEric Joyner  */
6989e54973fSEric Joyner static int
ice_ift_rxd_pkt_get_subif(void * arg,if_rxd_info_t ri)6999e54973fSEric Joyner ice_ift_rxd_pkt_get_subif(void *arg, if_rxd_info_t ri)
7009e54973fSEric Joyner {
7019e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
7029e54973fSEric Joyner 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[ri->iri_qsidx];
7039e54973fSEric Joyner 
7049e54973fSEric Joyner 	return _ice_ift_rxd_pkt_get(rxq, ri);
7059e54973fSEric Joyner }
7069e54973fSEric Joyner 
7079e54973fSEric Joyner /**
7089e54973fSEric Joyner  * ice_ift_rxd_refill_subif - Prepare Rx descriptors for re-use by hardware
7099e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
7109e54973fSEric Joyner  * @iru: the Rx descriptor update structure
7119e54973fSEric Joyner  *
7129e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_refill() that provides a function pointer
7139e54973fSEric Joyner  * used by iflib for RX packet processing, for iflib subinterfaces.
7149e54973fSEric Joyner  */
7159e54973fSEric Joyner static void
ice_ift_rxd_refill_subif(void * arg,if_rxd_update_t iru)7169e54973fSEric Joyner ice_ift_rxd_refill_subif(void *arg, if_rxd_update_t iru)
7179e54973fSEric Joyner {
7189e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
7199e54973fSEric Joyner 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[iru->iru_qsidx];
7209e54973fSEric Joyner 
7219e54973fSEric Joyner 	uint64_t *paddrs;
7229e54973fSEric Joyner 	uint32_t pidx;
7239e54973fSEric Joyner 	uint16_t count;
7249e54973fSEric Joyner 
7259e54973fSEric Joyner 	paddrs = iru->iru_paddrs;
7269e54973fSEric Joyner 	pidx = iru->iru_pidx;
7279e54973fSEric Joyner 	count = iru->iru_count;
7289e54973fSEric Joyner 
7299e54973fSEric Joyner 	_ice_ift_rxd_refill(rxq, pidx, paddrs, count);
7309e54973fSEric Joyner }
7319e54973fSEric Joyner 
7329e54973fSEric Joyner /**
7339e54973fSEric Joyner  * ice_ift_rxd_flush_subif - Flush Rx descriptors to hardware
7349e54973fSEric Joyner  * @arg: subinterface private structure (struct ice_mirr_if)
7359e54973fSEric Joyner  * @rxqid: the Rx queue to flush
7369e54973fSEric Joyner  * @flidx: unused parameter
7379e54973fSEric Joyner  * @pidx: descriptor index to advance tail to
7389e54973fSEric Joyner  *
7399e54973fSEric Joyner  * Wrapper function for _ice_ift_rxd_flush() that provides a function pointer
7409e54973fSEric Joyner  * used by iflib for RX packet processing.
7419e54973fSEric Joyner  */
7429e54973fSEric Joyner static void
ice_ift_rxd_flush_subif(void * arg,uint16_t rxqid,uint8_t flidx __unused,qidx_t pidx)7439e54973fSEric Joyner ice_ift_rxd_flush_subif(void *arg, uint16_t rxqid, uint8_t flidx __unused,
7449e54973fSEric Joyner 			qidx_t pidx)
7459e54973fSEric Joyner {
7469e54973fSEric Joyner 	struct ice_mirr_if *mif = (struct ice_mirr_if *)arg;
7479e54973fSEric Joyner 	struct ice_rx_queue *rxq = &mif->vsi->rx_queues[rxqid];
7489e54973fSEric Joyner 
7499e54973fSEric Joyner 	_ice_ift_rxd_flush(mif->back, rxq, pidx);
7509e54973fSEric Joyner }
751