From 2dfab9aad47e5209eb356e11cf937605f645189d Mon Sep 17 00:00:00 2001 From: Lance Richardson Date: Wed, 16 Jun 2021 13:55:21 -0400 Subject: [PATCH] net/bnxt: fix Tx descriptor status implementation [ upstream commit ce5c57ac01af038b930d5164df2cb16193e238ec ] With Tx completion batching, a single transmit completion can correspond to one or more transmit descriptors, adjust implementation to account for this. RTE_ETH_TX_DESC_DONE should be returned for descriptors that are available for use instead of RTE_ETH_TX_DESC_UNAVAIL. Fixes: 5735eb241947 ("net/bnxt: support Tx batching") Fixes: 478ed3bb7b9d ("net/bnxt: support Tx descriptor status") Signed-off-by: Lance Richardson Reviewed-by: Ajit Khaparde --- drivers/net/bnxt/bnxt_ethdev.c | 54 +++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index f34e90e8df..2bd3c9eaa5 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -3213,41 +3213,49 @@ static int bnxt_tx_descriptor_status_op(void *tx_queue, uint16_t offset) { struct bnxt_tx_queue *txq = (struct bnxt_tx_queue *)tx_queue; - struct bnxt_tx_ring_info *txr; - struct bnxt_cp_ring_info *cpr; - struct bnxt_sw_tx_bd *tx_buf; - struct tx_pkt_cmpl *txcmp; - uint32_t cons, cp_cons; + struct bnxt_cp_ring_info *cpr = txq->cp_ring; + uint32_t ring_mask, raw_cons, nb_tx_pkts = 0; + struct bnxt_ring *cp_ring_struct; + struct cmpl_base *cp_desc_ring; int rc; - if (!txq) - return -EINVAL; - rc = is_bnxt_in_error(txq->bp); if (rc) return rc; - cpr = txq->cp_ring; - txr = txq->tx_ring; - if (offset >= txq->nb_tx_desc) return -EINVAL; - cons = RING_CMP(cpr->cp_ring_struct, offset); - txcmp = (struct tx_pkt_cmpl *)&cpr->cp_desc_ring[cons]; - cp_cons = cpr->cp_raw_cons; + /* Return "desc done" if descriptor is available for use. */ + if (bnxt_tx_bds_in_hw(txq) <= offset) + return RTE_ETH_TX_DESC_DONE; - if (cons > cp_cons) { - if (CMPL_VALID(txcmp, cpr->valid)) - return RTE_ETH_TX_DESC_UNAVAIL; - } else { - if (CMPL_VALID(txcmp, !cpr->valid)) - return RTE_ETH_TX_DESC_UNAVAIL; + raw_cons = cpr->cp_raw_cons; + cp_desc_ring = cpr->cp_desc_ring; + cp_ring_struct = cpr->cp_ring_struct; + ring_mask = cpr->cp_ring_struct->ring_mask; + + /* Check to see if hw has posted a completion for the descriptor. */ + while (1) { + struct tx_cmpl *txcmp; + uint32_t cons; + + cons = RING_CMPL(ring_mask, raw_cons); + txcmp = (struct tx_cmpl *)&cp_desc_ring[cons]; + + if (!CMP_VALID(txcmp, raw_cons, cp_ring_struct)) + break; + + if (CMP_TYPE(txcmp) == TX_CMPL_TYPE_TX_L2) + nb_tx_pkts += rte_le_to_cpu_32(txcmp->opaque); + + if (nb_tx_pkts > offset) + return RTE_ETH_TX_DESC_DONE; + + raw_cons = NEXT_RAW_CMP(raw_cons); } - tx_buf = &txr->tx_buf_ring[cons]; - if (tx_buf->mbuf == NULL) - return RTE_ETH_TX_DESC_DONE; + /* Descriptor is pending transmit, not yet completed by hardware. */ return RTE_ETH_TX_DESC_FULL; }