aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-05-11 23:46:09 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-11 23:46:09 -0400
commit1b7cc307a88377b0c948f9cbc36d026b272fe6e3 (patch)
tree10bed408042dacc3bc4a73f84126477c67f55138
parent5f46feab87bb105d6a217d966b327fdc56696802 (diff)
parentfa7e28127a5ad9fd55ac9c7707d8c8b835113a7c (diff)
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>
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c63
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h2
2 files changed, 65 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 9d4e8e113fe1..c39a7f5c6a01 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -813,6 +813,46 @@ static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data,
813 return skb; 813 return skb;
814} 814}
815 815
816static 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
846static 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
816static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, 856static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
817 struct rx_tpa_start_cmp *tpa_start, 857 struct rx_tpa_start_cmp *tpa_start,
818 struct rx_tpa_start_cmp_ext *tpa_start1) 858 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,
830 prod_rx_buf = &rxr->rx_buf_ring[prod]; 870 prod_rx_buf = &rxr->rx_buf_ring[prod];
831 tpa_info = &rxr->rx_tpa[agg_id]; 871 tpa_info = &rxr->rx_tpa[agg_id];
832 872
873 if (unlikely(cons != rxr->rx_next_cons)) {
874 bnxt_sched_reset(bp, rxr);
875 return;
876 }
877
833 prod_rx_buf->data = tpa_info->data; 878 prod_rx_buf->data = tpa_info->data;
834 879
835 mapping = tpa_info->mapping; 880 mapping = tpa_info->mapping;
@@ -867,6 +912,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
867 912
868 rxr->rx_prod = NEXT_RX(prod); 913 rxr->rx_prod = NEXT_RX(prod);
869 cons = NEXT_RX(cons); 914 cons = NEXT_RX(cons);
915 rxr->rx_next_cons = NEXT_RX(cons);
870 cons_rx_buf = &rxr->rx_buf_ring[cons]; 916 cons_rx_buf = &rxr->rx_buf_ring[cons];
871 917
872 bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data); 918 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,
980 dma_addr_t mapping; 1026 dma_addr_t mapping;
981 struct sk_buff *skb; 1027 struct sk_buff *skb;
982 1028
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
983 tpa_info = &rxr->rx_tpa[agg_id]; 1037 tpa_info = &rxr->rx_tpa[agg_id];
984 data = tpa_info->data; 1038 data = tpa_info->data;
985 prefetch(data); 1039 prefetch(data);
@@ -1146,6 +1200,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
1146 cons = rxcmp->rx_cmp_opaque; 1200 cons = rxcmp->rx_cmp_opaque;
1147 rx_buf = &rxr->rx_buf_ring[cons]; 1201 rx_buf = &rxr->rx_buf_ring[cons];
1148 data = rx_buf->data; 1202 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 }
1149 prefetch(data); 1209 prefetch(data);
1150 1210
1151 agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >> 1211 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,
1245 1305
1246next_rx: 1306next_rx:
1247 rxr->rx_prod = NEXT_RX(prod); 1307 rxr->rx_prod = NEXT_RX(prod);
1308 rxr->rx_next_cons = NEXT_RX(cons);
1248 1309
1249next_rx_no_prod: 1310next_rx_no_prod:
1250 *raw_cons = tmp_raw_cons; 1311 *raw_cons = tmp_raw_cons;
@@ -2486,6 +2547,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
2486 rxr->rx_prod = 0; 2547 rxr->rx_prod = 0;
2487 rxr->rx_agg_prod = 0; 2548 rxr->rx_agg_prod = 0;
2488 rxr->rx_sw_agg_prod = 0; 2549 rxr->rx_sw_agg_prod = 0;
2550 rxr->rx_next_cons = 0;
2489 } 2551 }
2490 } 2552 }
2491} 2553}
@@ -4462,6 +4524,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
4462 int i; 4524 int i;
4463 4525
4464 for (i = 0; i < bp->cp_nr_rings; i++) { 4526 for (i = 0; i < bp->cp_nr_rings; i++) {
4527 bp->bnapi[i]->in_reset = false;
4465 bnxt_enable_poll(bp->bnapi[i]); 4528 bnxt_enable_poll(bp->bnapi[i]);
4466 napi_enable(&bp->bnapi[i]->napi); 4529 napi_enable(&bp->bnapi[i]->napi);
4467 } 4530 }
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 8b823ff558ff..de9d53eee3dd 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -584,6 +584,7 @@ struct bnxt_rx_ring_info {
584 u16 rx_prod; 584 u16 rx_prod;
585 u16 rx_agg_prod; 585 u16 rx_agg_prod;
586 u16 rx_sw_agg_prod; 586 u16 rx_sw_agg_prod;
587 u16 rx_next_cons;
587 void __iomem *rx_doorbell; 588 void __iomem *rx_doorbell;
588 void __iomem *rx_agg_doorbell; 589 void __iomem *rx_agg_doorbell;
589 590
@@ -636,6 +637,7 @@ struct bnxt_napi {
636#ifdef CONFIG_NET_RX_BUSY_POLL 637#ifdef CONFIG_NET_RX_BUSY_POLL
637 atomic_t poll_state; 638 atomic_t poll_state;
638#endif 639#endif
640 bool in_reset;
639}; 641};
640 642
641#ifdef CONFIG_NET_RX_BUSY_POLL 643#ifdef CONFIG_NET_RX_BUSY_POLL