Skip to content

Commit fa7e281

Browse files
Michael Chandavem330
Michael Chan
authored andcommitted
bnxt_en: Add workaround to detect bad opaque in rx completion (part 2)
Add detection and recovery code when the hardware returned opaque value does not match the expected consumer index. Once the issue is detected, we skip the processing of all RX and LRO/GRO packets. These completion entries are discarded without sending the SKB to the stack and without producing new buffers. The function will be reset from a workqueue. Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 376a5b8 commit fa7e281

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,46 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
813813
return skb;
814814
}
815815

816+
static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_napi *bnapi,
817+
u32 *raw_cons, void *cmp)
818+
{
819+
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
820+
struct rx_cmp *rxcmp = cmp;
821+
u32 tmp_raw_cons = *raw_cons;
822+
u8 cmp_type, agg_bufs = 0;
823+
824+
cmp_type = RX_CMP_TYPE(rxcmp);
825+
826+
if (cmp_type == CMP_TYPE_RX_L2_CMP) {
827+
agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) &
828+
RX_CMP_AGG_BUFS) >>
829+
RX_CMP_AGG_BUFS_SHIFT;
830+
} else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
831+
struct rx_tpa_end_cmp *tpa_end = cmp;
832+
833+
agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
834+
RX_TPA_END_CMP_AGG_BUFS) >>
835+
RX_TPA_END_CMP_AGG_BUFS_SHIFT;
836+
}
837+
838+
if (agg_bufs) {
839+
if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, &tmp_raw_cons))
840+
return -EBUSY;
841+
}
842+
*raw_cons = tmp_raw_cons;
843+
return 0;
844+
}
845+
846+
static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
847+
{
848+
if (!rxr->bnapi->in_reset) {
849+
rxr->bnapi->in_reset = true;
850+
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
851+
schedule_work(&bp->sp_task);
852+
}
853+
rxr->rx_next_cons = 0xffff;
854+
}
855+
816856
static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
817857
struct rx_tpa_start_cmp *tpa_start,
818858
struct rx_tpa_start_cmp_ext *tpa_start1)
@@ -830,6 +870,11 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
830870
prod_rx_buf = &rxr->rx_buf_ring[prod];
831871
tpa_info = &rxr->rx_tpa[agg_id];
832872

873+
if (unlikely(cons != rxr->rx_next_cons)) {
874+
bnxt_sched_reset(bp, rxr);
875+
return;
876+
}
877+
833878
prod_rx_buf->data = tpa_info->data;
834879

835880
mapping = tpa_info->mapping;
@@ -981,6 +1026,14 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
9811026
dma_addr_t mapping;
9821027
struct sk_buff *skb;
9831028

1029+
if (unlikely(bnapi->in_reset)) {
1030+
int rc = bnxt_discard_rx(bp, bnapi, raw_cons, tpa_end);
1031+
1032+
if (rc < 0)
1033+
return ERR_PTR(-EBUSY);
1034+
return NULL;
1035+
}
1036+
9841037
tpa_info = &rxr->rx_tpa[agg_id];
9851038
data = tpa_info->data;
9861039
prefetch(data);
@@ -1147,6 +1200,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
11471200
cons = rxcmp->rx_cmp_opaque;
11481201
rx_buf = &rxr->rx_buf_ring[cons];
11491202
data = rx_buf->data;
1203+
if (unlikely(cons != rxr->rx_next_cons)) {
1204+
int rc1 = bnxt_discard_rx(bp, bnapi, raw_cons, rxcmp);
1205+
1206+
bnxt_sched_reset(bp, rxr);
1207+
return rc1;
1208+
}
11501209
prefetch(data);
11511210

11521211
agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >>
@@ -4465,6 +4524,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
44654524
int i;
44664525

44674526
for (i = 0; i < bp->cp_nr_rings; i++) {
4527+
bp->bnapi[i]->in_reset = false;
44684528
bnxt_enable_poll(bp->bnapi[i]);
44694529
napi_enable(&bp->bnapi[i]->napi);
44704530
}

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ struct bnxt_napi {
637637
#ifdef CONFIG_NET_RX_BUSY_POLL
638638
atomic_t poll_state;
639639
#endif
640+
bool in_reset;
640641
};
641642

642643
#ifdef CONFIG_NET_RX_BUSY_POLL

0 commit comments

Comments
 (0)