net/bnxt: fix Rx handling and buffer allocation logic
[dpdk.git] / drivers / net / bnxt / bnxt_rxr.c
index 5f30e02..bf9f78a 100644 (file)
@@ -68,8 +68,10 @@ static inline int bnxt_alloc_rx_data(struct bnxt_rx_queue *rxq,
        struct rte_mbuf *data;
 
        data = __bnxt_alloc_rx_data(rxq->mb_pool);
-       if (!data)
+       if (!data) {
+               rte_atomic64_inc(&rxq->bp->rx_mbuf_alloc_fail);
                return -ENOMEM;
+       }
 
        rx_buf->mbuf = data;
 
@@ -87,8 +89,10 @@ static inline int bnxt_alloc_ag_data(struct bnxt_rx_queue *rxq,
        struct rte_mbuf *data;
 
        data = __bnxt_alloc_rx_data(rxq->mb_pool);
-       if (!data)
+       if (!data) {
+               rte_atomic64_inc(&rxq->bp->rx_mbuf_alloc_fail);
                return -ENOMEM;
+       }
 
        if (rxbd == NULL)
                RTE_LOG(ERR, PMD, "Jumbo Frame. rxbd is NULL\n");
@@ -319,8 +323,10 @@ static inline struct rte_mbuf *bnxt_tpa_end(
 
        struct rte_mbuf *new_data = __bnxt_alloc_rx_data(rxq->mb_pool);
        RTE_ASSERT(new_data != NULL);
-       if (!new_data)
+       if (!new_data) {
+               rte_atomic64_inc(&rxq->bp->rx_mbuf_alloc_fail);
                return NULL;
+       }
        tpa_info->mbuf = new_data;
 
        return mbuf;
@@ -385,7 +391,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
        rte_prefetch0(mbuf);
 
        if (mbuf == NULL)
-               return -ENOMEM;
+               return -EBUSY;
 
        mbuf->nb_segs = 1;
        mbuf->next = NULL;
@@ -442,13 +448,14 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
        if (bnxt_alloc_rx_data(rxq, rxr, prod)) {
                RTE_LOG(ERR, PMD, "mbuf alloc failed with prod=0x%x\n", prod);
                rc = -ENOMEM;
+               goto rx;
        }
        rxr->rx_prod = prod;
        /*
         * All MBUFs are allocated with the same size under DPDK,
         * no optimization for rx_copy_thresh
         */
-
+rx:
        *rx_pkt = mbuf;
 
 next_rx:
@@ -470,6 +477,7 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
        struct rx_pkt_cmpl *rxcmp;
        uint16_t prod = rxr->rx_prod;
        uint16_t ag_prod = rxr->ag_prod;
+       int rc = 0;
 
        /* Handle RX burst request */
        while (1) {
@@ -485,7 +493,7 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
                /* TODO: Avoid magic numbers... */
                if ((CMP_TYPE(rxcmp) & 0x30) == 0x10) {
                        rc = bnxt_rx_pkt(&rx_pkts[nb_rx_pkts], rxq, &raw_cons);
-                       if (likely(!rc))
+                       if (likely(!rc) || rc == -ENOMEM)
                                nb_rx_pkts++;
                        if (rc == -EBUSY)       /* partial completion */
                                break;
@@ -508,6 +516,30 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
        B_RX_DB(rxr->rx_doorbell, rxr->rx_prod);
        /* Ring the AGG ring DB */
        B_RX_DB(rxr->ag_doorbell, rxr->ag_prod);
+
+       /* Attempt to alloc Rx buf in case of a previous allocation failure. */
+       if (rc == -ENOMEM) {
+               int i;
+
+               for (i = prod; i <= nb_rx_pkts;
+                       i = RING_NEXT(rxr->rx_ring_struct, i)) {
+                       struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[i];
+
+                       /* Buffer already allocated for this index. */
+                       if (rx_buf->mbuf != NULL)
+                               continue;
+
+                       /* This slot is empty. Alloc buffer for Rx */
+                       if (!bnxt_alloc_rx_data(rxq, rxr, i)) {
+                               rxr->rx_prod = i;
+                               B_RX_DB(rxr->rx_doorbell, rxr->rx_prod);
+                       } else {
+                               RTE_LOG(ERR, PMD, "Alloc  mbuf failed\n");
+                               break;
+                       }
+               }
+       }
+
        return nb_rx_pkts;
 }
 
@@ -676,8 +708,10 @@ int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
                for (i = 0; i < BNXT_TPA_MAX; i++) {
                        rxr->tpa_info[i].mbuf =
                                __bnxt_alloc_rx_data(rxq->mb_pool);
-                       if (!rxr->tpa_info[i].mbuf)
+                       if (!rxr->tpa_info[i].mbuf) {
+                               rte_atomic64_inc(&rxq->bp->rx_mbuf_alloc_fail);
                                return -ENOMEM;
+                       }
                }
        }
        RTE_LOG(DEBUG, PMD, "%s TPA alloc Done!\n", __func__);