When handling RX completion queue PMD is not using required read/write
barriers before reading completion queue element (CQE) indices,
updating/writing hardware consumer and producer.
This patch adds appropriate read/write memory barriers in places which
are required by driver and adapter to read or update indices.

Fixes: 540a211084a7 ("bnx2x: driver core")
Cc: sta...@dpdk.org

Signed-off-by: Rasesh Mody <rm...@marvell.com>
---
 drivers/net/bnx2x/bnx2x.c      |  5 +++++
 drivers/net/bnx2x/bnx2x_rxtx.c | 22 ++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c
index ed31335ac..9c5e7995d 100644
--- a/drivers/net/bnx2x/bnx2x.c
+++ b/drivers/net/bnx2x/bnx2x.c
@@ -1255,6 +1255,11 @@ static uint8_t bnx2x_rxeof(struct bnx2x_softc *sc, 
struct bnx2x_fastpath *fp)
                return 0;
        }
 
+       /* Add memory barrier as status block fields can change. This memory
+        * barrier will flush out all the read/write operations to status block
+        * generated before the barrier. It will ensure stale data is not read
+        */
+       mb();
        /* CQ "next element" is of the size of the regular element */
        hw_cq_cons = le16toh(*fp->rx_cq_cons_sb);
        if (unlikely((hw_cq_cons & USABLE_RCQ_ENTRIES_PER_PAGE) ==
diff --git a/drivers/net/bnx2x/bnx2x_rxtx.c b/drivers/net/bnx2x/bnx2x_rxtx.c
index ae97dfee3..b52f023ea 100644
--- a/drivers/net/bnx2x/bnx2x_rxtx.c
+++ b/drivers/net/bnx2x/bnx2x_rxtx.c
@@ -324,11 +324,22 @@ bnx2x_upd_rx_prod_fast(struct bnx2x_softc *sc, struct 
bnx2x_fastpath *fp,
        struct ustorm_eth_rx_producers rx_prods = { 0 };
        uint32_t *val = NULL;
 
+       /* Update producers */
        rx_prods.bd_prod  = rx_bd_prod;
        rx_prods.cqe_prod = rx_cq_prod;
 
+       /*
+        * Make sure that the BD and SGE data is updated before updating the
+        * producers since FW might read the BD/SGE right after the producer
+        * is updated.
+        * The following barrier is also mandatory since FW will assumes BDs
+        * must have buffers.
+        */
+       wmb();
        val = (uint32_t *)&rx_prods;
        REG_WR(sc, fp->ustorm_rx_prods_offset, val[0]);
+
+       wmb();                  /* keep prod updates ordered */
 }
 
 static uint16_t
@@ -346,6 +357,11 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, 
uint16_t nb_pkts)
        uint16_t len, pad;
        struct rte_mbuf *rx_mb = NULL;
 
+       /* Add memory barrier as status block fields can change. This memory
+        * barrier will flush out all the read/write operations to status block
+        * generated before the barrier. It will ensure stale data is not read
+        */
+       mb();
        hw_cq_cons = le16toh(*fp->rx_cq_cons_sb);
        if ((hw_cq_cons & USABLE_RCQ_ENTRIES_PER_PAGE) ==
                        USABLE_RCQ_ENTRIES_PER_PAGE) {
@@ -357,6 +373,12 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, 
uint16_t nb_pkts)
        sw_cq_cons = rxq->rx_cq_head;
        sw_cq_prod = rxq->rx_cq_tail;
 
+       /*
+        * Memory barrier necessary as speculative reads of the Rx
+        * buffer can be ahead of the index in the status block
+        */
+       rmb();
+
        if (sw_cq_cons == hw_cq_cons)
                return 0;
 
-- 
2.18.0

Reply via email to