forked from Minki/linux
Merge branch 'bnxt_en-fixes'
Michael Chan says: ==================== bnxt_en: Add workaround to detect bad opaque in rx completion. 2-part workaround for this hardware bug. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1b7cc307a8
@ -813,6 +813,46 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_napi *bnapi,
|
||||
u32 *raw_cons, void *cmp)
|
||||
{
|
||||
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
|
||||
struct rx_cmp *rxcmp = cmp;
|
||||
u32 tmp_raw_cons = *raw_cons;
|
||||
u8 cmp_type, agg_bufs = 0;
|
||||
|
||||
cmp_type = RX_CMP_TYPE(rxcmp);
|
||||
|
||||
if (cmp_type == CMP_TYPE_RX_L2_CMP) {
|
||||
agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) &
|
||||
RX_CMP_AGG_BUFS) >>
|
||||
RX_CMP_AGG_BUFS_SHIFT;
|
||||
} else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
|
||||
struct rx_tpa_end_cmp *tpa_end = cmp;
|
||||
|
||||
agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) &
|
||||
RX_TPA_END_CMP_AGG_BUFS) >>
|
||||
RX_TPA_END_CMP_AGG_BUFS_SHIFT;
|
||||
}
|
||||
|
||||
if (agg_bufs) {
|
||||
if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, &tmp_raw_cons))
|
||||
return -EBUSY;
|
||||
}
|
||||
*raw_cons = tmp_raw_cons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
|
||||
{
|
||||
if (!rxr->bnapi->in_reset) {
|
||||
rxr->bnapi->in_reset = true;
|
||||
set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
|
||||
schedule_work(&bp->sp_task);
|
||||
}
|
||||
rxr->rx_next_cons = 0xffff;
|
||||
}
|
||||
|
||||
static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
|
||||
struct rx_tpa_start_cmp *tpa_start,
|
||||
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,
|
||||
prod_rx_buf = &rxr->rx_buf_ring[prod];
|
||||
tpa_info = &rxr->rx_tpa[agg_id];
|
||||
|
||||
if (unlikely(cons != rxr->rx_next_cons)) {
|
||||
bnxt_sched_reset(bp, rxr);
|
||||
return;
|
||||
}
|
||||
|
||||
prod_rx_buf->data = tpa_info->data;
|
||||
|
||||
mapping = tpa_info->mapping;
|
||||
@ -867,6 +912,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
|
||||
|
||||
rxr->rx_prod = NEXT_RX(prod);
|
||||
cons = NEXT_RX(cons);
|
||||
rxr->rx_next_cons = NEXT_RX(cons);
|
||||
cons_rx_buf = &rxr->rx_buf_ring[cons];
|
||||
|
||||
bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data);
|
||||
@ -980,6 +1026,14 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
|
||||
dma_addr_t mapping;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (unlikely(bnapi->in_reset)) {
|
||||
int rc = bnxt_discard_rx(bp, bnapi, raw_cons, tpa_end);
|
||||
|
||||
if (rc < 0)
|
||||
return ERR_PTR(-EBUSY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tpa_info = &rxr->rx_tpa[agg_id];
|
||||
data = tpa_info->data;
|
||||
prefetch(data);
|
||||
@ -1146,6 +1200,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
|
||||
cons = rxcmp->rx_cmp_opaque;
|
||||
rx_buf = &rxr->rx_buf_ring[cons];
|
||||
data = rx_buf->data;
|
||||
if (unlikely(cons != rxr->rx_next_cons)) {
|
||||
int rc1 = bnxt_discard_rx(bp, bnapi, raw_cons, rxcmp);
|
||||
|
||||
bnxt_sched_reset(bp, rxr);
|
||||
return rc1;
|
||||
}
|
||||
prefetch(data);
|
||||
|
||||
agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >>
|
||||
@ -1245,6 +1305,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
|
||||
|
||||
next_rx:
|
||||
rxr->rx_prod = NEXT_RX(prod);
|
||||
rxr->rx_next_cons = NEXT_RX(cons);
|
||||
|
||||
next_rx_no_prod:
|
||||
*raw_cons = tmp_raw_cons;
|
||||
@ -2486,6 +2547,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
|
||||
rxr->rx_prod = 0;
|
||||
rxr->rx_agg_prod = 0;
|
||||
rxr->rx_sw_agg_prod = 0;
|
||||
rxr->rx_next_cons = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4462,6 +4524,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->cp_nr_rings; i++) {
|
||||
bp->bnapi[i]->in_reset = false;
|
||||
bnxt_enable_poll(bp->bnapi[i]);
|
||||
napi_enable(&bp->bnapi[i]->napi);
|
||||
}
|
||||
|
@ -584,6 +584,7 @@ struct bnxt_rx_ring_info {
|
||||
u16 rx_prod;
|
||||
u16 rx_agg_prod;
|
||||
u16 rx_sw_agg_prod;
|
||||
u16 rx_next_cons;
|
||||
void __iomem *rx_doorbell;
|
||||
void __iomem *rx_agg_doorbell;
|
||||
|
||||
@ -636,6 +637,7 @@ struct bnxt_napi {
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
atomic_t poll_state;
|
||||
#endif
|
||||
bool in_reset;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
|
Loading…
Reference in New Issue
Block a user