net/bnxt: fix Rx descriptor status
authorLance Richardson <lance.richardson@broadcom.com>
Tue, 2 Mar 2021 14:29:27 +0000 (09:29 -0500)
committerAjit Khaparde <ajit.khaparde@broadcom.com>
Fri, 12 Mar 2021 06:12:30 +0000 (07:12 +0100)
Fix a number of issues in the bnxt receive descriptor status
function, including:
   - Provide status of receive descriptor instead of completion
     descriptor.
   - Remove invalid comparison of raw ring index with masked ring
     index.
   - Correct misinterpretation of offset parameter as ring index.
   - Correct misuse of completion ring index for mbuf ring (the
     two rings have different sizes).

Fixes: 0fe613bb87b2 ("net/bnxt: support Rx descriptor status")
Cc: stable@dpdk.org
Signed-off-by: Lance Richardson <lance.richardson@broadcom.com>
Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
drivers/net/bnxt/bnxt_ethdev.c

index c55a2d8..fae23a5 100644 (file)
@@ -3076,42 +3076,109 @@ bnxt_rx_queue_count_op(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 static int
 bnxt_rx_descriptor_status_op(void *rx_queue, uint16_t offset)
 {
-       struct bnxt_rx_queue *rxq = (struct bnxt_rx_queue *)rx_queue;
-       struct bnxt_rx_ring_info *rxr;
+       struct bnxt_rx_queue *rxq = rx_queue;
        struct bnxt_cp_ring_info *cpr;
-       struct rte_mbuf *rx_buf;
+       struct bnxt_rx_ring_info *rxr;
+       uint32_t desc, raw_cons;
+       struct bnxt *bp = rxq->bp;
        struct rx_pkt_cmpl *rxcmp;
-       uint32_t cons, cp_cons;
        int rc;
 
-       if (!rxq)
-               return -EINVAL;
-
-       rc = is_bnxt_in_error(rxq->bp);
+       rc = is_bnxt_in_error(bp);
        if (rc)
                return rc;
 
-       cpr = rxq->cp_ring;
-       rxr = rxq->rx_ring;
-
        if (offset >= rxq->nb_rx_desc)
                return -EINVAL;
 
-       cons = RING_CMP(cpr->cp_ring_struct, offset);
-       cp_cons = cpr->cp_raw_cons;
-       rxcmp = (struct rx_pkt_cmpl *)&cpr->cp_desc_ring[cons];
+       rxr = rxq->rx_ring;
+       cpr = rxq->cp_ring;
 
-       if (cons > cp_cons) {
-               if (CMPL_VALID(rxcmp, cpr->valid))
-                       return RTE_ETH_RX_DESC_DONE;
-       } else {
-               if (CMPL_VALID(rxcmp, !cpr->valid))
+       /*
+        * For the vector receive case, the completion at the requested
+        * offset can be indexed directly.
+        */
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
+       if (bp->flags & BNXT_FLAG_RX_VECTOR_PKT_MODE) {
+               struct rx_pkt_cmpl *rxcmp;
+               uint32_t cons;
+
+               /* Check status of completion descriptor. */
+               raw_cons = cpr->cp_raw_cons +
+                          offset * CMP_LEN(CMPL_BASE_TYPE_RX_L2);
+               cons = RING_CMP(cpr->cp_ring_struct, raw_cons);
+               rxcmp = (struct rx_pkt_cmpl *)&cpr->cp_desc_ring[cons];
+
+               if (CMP_VALID(rxcmp, raw_cons, cpr->cp_ring_struct))
                        return RTE_ETH_RX_DESC_DONE;
+
+               /* Check whether rx desc has an mbuf attached. */
+               cons = RING_CMP(rxr->rx_ring_struct, raw_cons / 2);
+               if (cons >= rxq->rxrearm_start &&
+                   cons < rxq->rxrearm_start + rxq->rxrearm_nb) {
+                       return RTE_ETH_RX_DESC_UNAVAIL;
+               }
+
+               return RTE_ETH_RX_DESC_AVAIL;
        }
-       rx_buf = rxr->rx_buf_ring[cons];
-       if (rx_buf == NULL || rx_buf == &rxq->fake_mbuf)
-               return RTE_ETH_RX_DESC_UNAVAIL;
+#endif
+
+       /*
+        * For the non-vector receive case, scan the completion ring to
+        * locate the completion descriptor for the requested offset.
+        */
+       raw_cons = cpr->cp_raw_cons;
+       desc = 0;
+       while (1) {
+               uint32_t agg_cnt, cons, cmpl_type;
+
+               cons = RING_CMP(cpr->cp_ring_struct, raw_cons);
+               rxcmp = (struct rx_pkt_cmpl *)&cpr->cp_desc_ring[cons];
 
+               if (!CMP_VALID(rxcmp, raw_cons, cpr->cp_ring_struct))
+                       break;
+
+               cmpl_type = CMP_TYPE(rxcmp);
+
+               switch (cmpl_type) {
+               case CMPL_BASE_TYPE_RX_L2:
+               case CMPL_BASE_TYPE_RX_L2_V2:
+                       if (desc == offset) {
+                               cons = rxcmp->opaque;
+                               if (rxr->rx_buf_ring[cons])
+                                       return RTE_ETH_RX_DESC_DONE;
+                               else
+                                       return RTE_ETH_RX_DESC_UNAVAIL;
+                       }
+                       agg_cnt = BNXT_RX_L2_AGG_BUFS(rxcmp);
+                       raw_cons = raw_cons + CMP_LEN(cmpl_type) + agg_cnt;
+                       desc++;
+                       break;
+
+               case CMPL_BASE_TYPE_RX_TPA_END:
+                       if (desc == offset)
+                               return RTE_ETH_RX_DESC_DONE;
+
+                       if (BNXT_CHIP_P5(rxq->bp)) {
+                               struct rx_tpa_v2_end_cmpl_hi *p5_tpa_end;
+
+                               p5_tpa_end = (void *)rxcmp;
+                               agg_cnt = BNXT_TPA_END_AGG_BUFS_TH(p5_tpa_end);
+                       } else {
+                               struct rx_tpa_end_cmpl *tpa_end;
+
+                               tpa_end = (void *)rxcmp;
+                               agg_cnt = BNXT_TPA_END_AGG_BUFS(tpa_end);
+                       }
+
+                       raw_cons = raw_cons + CMP_LEN(cmpl_type) + agg_cnt;
+                       desc++;
+                       break;
+
+               default:
+                       raw_cons += CMP_LEN(cmpl_type);
+               }
+       }
 
        return RTE_ETH_RX_DESC_AVAIL;
 }