diff options
Diffstat (limited to 'drivers/net/cnic.c')
| -rw-r--r-- | drivers/net/cnic.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 7ff170cbc7d..302be4aa69d 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
| @@ -2760,6 +2760,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) | |||
| 2760 | u32 status_idx = (u16) *cp->kcq1.status_idx_ptr; | 2760 | u32 status_idx = (u16) *cp->kcq1.status_idx_ptr; |
| 2761 | int kcqe_cnt; | 2761 | int kcqe_cnt; |
| 2762 | 2762 | ||
| 2763 | /* status block index must be read before reading other fields */ | ||
| 2764 | rmb(); | ||
| 2763 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2765 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
| 2764 | 2766 | ||
| 2765 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { | 2767 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { |
| @@ -2770,6 +2772,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) | |||
| 2770 | barrier(); | 2772 | barrier(); |
| 2771 | if (status_idx != *cp->kcq1.status_idx_ptr) { | 2773 | if (status_idx != *cp->kcq1.status_idx_ptr) { |
| 2772 | status_idx = (u16) *cp->kcq1.status_idx_ptr; | 2774 | status_idx = (u16) *cp->kcq1.status_idx_ptr; |
| 2775 | /* status block index must be read first */ | ||
| 2776 | rmb(); | ||
| 2773 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2777 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
| 2774 | } else | 2778 | } else |
| 2775 | break; | 2779 | break; |
| @@ -2888,6 +2892,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) | |||
| 2888 | u32 last_status = *info->status_idx_ptr; | 2892 | u32 last_status = *info->status_idx_ptr; |
| 2889 | int kcqe_cnt; | 2893 | int kcqe_cnt; |
| 2890 | 2894 | ||
| 2895 | /* status block index must be read before reading the KCQ */ | ||
| 2896 | rmb(); | ||
| 2891 | while ((kcqe_cnt = cnic_get_kcqes(dev, info))) { | 2897 | while ((kcqe_cnt = cnic_get_kcqes(dev, info))) { |
| 2892 | 2898 | ||
| 2893 | service_kcqes(dev, kcqe_cnt); | 2899 | service_kcqes(dev, kcqe_cnt); |
| @@ -2898,6 +2904,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) | |||
| 2898 | break; | 2904 | break; |
| 2899 | 2905 | ||
| 2900 | last_status = *info->status_idx_ptr; | 2906 | last_status = *info->status_idx_ptr; |
| 2907 | /* status block index must be read before reading the KCQ */ | ||
| 2908 | rmb(); | ||
| 2901 | } | 2909 | } |
| 2902 | return last_status; | 2910 | return last_status; |
| 2903 | } | 2911 | } |
| @@ -2906,26 +2914,35 @@ static void cnic_service_bnx2x_bh(unsigned long data) | |||
| 2906 | { | 2914 | { |
| 2907 | struct cnic_dev *dev = (struct cnic_dev *) data; | 2915 | struct cnic_dev *dev = (struct cnic_dev *) data; |
| 2908 | struct cnic_local *cp = dev->cnic_priv; | 2916 | struct cnic_local *cp = dev->cnic_priv; |
| 2909 | u32 status_idx; | 2917 | u32 status_idx, new_status_idx; |
| 2910 | 2918 | ||
| 2911 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) | 2919 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) |
| 2912 | return; | 2920 | return; |
| 2913 | 2921 | ||
| 2914 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); | 2922 | while (1) { |
| 2923 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); | ||
| 2915 | 2924 | ||
| 2916 | CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); | 2925 | CNIC_WR16(dev, cp->kcq1.io_addr, |
| 2926 | cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); | ||
| 2917 | 2927 | ||
| 2918 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) { | 2928 | if (!BNX2X_CHIP_IS_E2(cp->chip_id)) { |
| 2919 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); | 2929 | cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, |
| 2930 | status_idx, IGU_INT_ENABLE, 1); | ||
| 2931 | break; | ||
| 2932 | } | ||
| 2933 | |||
| 2934 | new_status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); | ||
| 2935 | |||
| 2936 | if (new_status_idx != status_idx) | ||
| 2937 | continue; | ||
| 2920 | 2938 | ||
| 2921 | CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx + | 2939 | CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx + |
| 2922 | MAX_KCQ_IDX); | 2940 | MAX_KCQ_IDX); |
| 2923 | 2941 | ||
| 2924 | cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, | 2942 | cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, |
| 2925 | status_idx, IGU_INT_ENABLE, 1); | 2943 | status_idx, IGU_INT_ENABLE, 1); |
| 2926 | } else { | 2944 | |
| 2927 | cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, | 2945 | break; |
| 2928 | status_idx, IGU_INT_ENABLE, 1); | ||
| 2929 | } | 2946 | } |
| 2930 | } | 2947 | } |
| 2931 | 2948 | ||
