Commit 376a5b86 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Add workaround to detect bad opaque in rx completion (part 1)

There is a rare hardware bug that can cause a bad opaque value in the RX
or TPA completion.  When this happens, the hardware may have used the
same buffer twice for 2 rx packets.  In addition, the driver will also
crash later using the bad opaque as the index into the ring.

The rx opaque value is predictable and is always monotonically increasing.
The workaround is to keep track of the expected next opaque value and
compare it with the one returned by hardware during RX and TPA start
completions.  If they miscompare, we will not process any more RX and
TPA completions and exit NAPI.  We will then schedule a workqueue to
reset the function.

This patch adds the logic to keep track of the next rx consumer index.
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5f46feab
...@@ -867,6 +867,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, ...@@ -867,6 +867,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
rxr->rx_prod = NEXT_RX(prod); rxr->rx_prod = NEXT_RX(prod);
cons = NEXT_RX(cons); cons = NEXT_RX(cons);
rxr->rx_next_cons = NEXT_RX(cons);
cons_rx_buf = &rxr->rx_buf_ring[cons]; cons_rx_buf = &rxr->rx_buf_ring[cons];
bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data); bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data);
...@@ -1245,6 +1246,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, ...@@ -1245,6 +1246,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
next_rx: next_rx:
rxr->rx_prod = NEXT_RX(prod); rxr->rx_prod = NEXT_RX(prod);
rxr->rx_next_cons = NEXT_RX(cons);
next_rx_no_prod: next_rx_no_prod:
*raw_cons = tmp_raw_cons; *raw_cons = tmp_raw_cons;
...@@ -2486,6 +2488,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp) ...@@ -2486,6 +2488,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
rxr->rx_prod = 0; rxr->rx_prod = 0;
rxr->rx_agg_prod = 0; rxr->rx_agg_prod = 0;
rxr->rx_sw_agg_prod = 0; rxr->rx_sw_agg_prod = 0;
rxr->rx_next_cons = 0;
} }
} }
} }
......
...@@ -584,6 +584,7 @@ struct bnxt_rx_ring_info { ...@@ -584,6 +584,7 @@ struct bnxt_rx_ring_info {
u16 rx_prod; u16 rx_prod;
u16 rx_agg_prod; u16 rx_agg_prod;
u16 rx_sw_agg_prod; u16 rx_sw_agg_prod;
u16 rx_next_cons;
void __iomem *rx_doorbell; void __iomem *rx_doorbell;
void __iomem *rx_agg_doorbell; void __iomem *rx_agg_doorbell;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment