diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-04 00:27:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-04 00:27:42 -0500 |
commit | 0a0e9ae1bd788bc19adc4d4ae08c98b233697402 (patch) | |
tree | 13825eeb5bbeae27d66e95f12168eff4b60701ab /drivers/net/cnic.c | |
parent | 01a16b21d6adf992aa863186c3c4e561a57c1714 (diff) | |
parent | b65a0e0c84cf489bfa00d6aa6c48abc5a237100f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/bnx2x/bnx2x.h
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 25f08880ae0..271a1f00c22 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -2767,6 +2767,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) | |||
2767 | u32 status_idx = (u16) *cp->kcq1.status_idx_ptr; | 2767 | u32 status_idx = (u16) *cp->kcq1.status_idx_ptr; |
2768 | int kcqe_cnt; | 2768 | int kcqe_cnt; |
2769 | 2769 | ||
2770 | /* status block index must be read before reading other fields */ | ||
2771 | rmb(); | ||
2770 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2772 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
2771 | 2773 | ||
2772 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { | 2774 | while ((kcqe_cnt = cnic_get_kcqes(dev, &cp->kcq1))) { |
@@ -2777,6 +2779,8 @@ static u32 cnic_service_bnx2_queues(struct cnic_dev *dev) | |||
2777 | barrier(); | 2779 | barrier(); |
2778 | if (status_idx != *cp->kcq1.status_idx_ptr) { | 2780 | if (status_idx != *cp->kcq1.status_idx_ptr) { |
2779 | status_idx = (u16) *cp->kcq1.status_idx_ptr; | 2781 | status_idx = (u16) *cp->kcq1.status_idx_ptr; |
2782 | /* status block index must be read first */ | ||
2783 | rmb(); | ||
2780 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; | 2784 | cp->kwq_con_idx = *cp->kwq_con_idx_ptr; |
2781 | } else | 2785 | } else |
2782 | break; | 2786 | break; |
@@ -2895,6 +2899,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) | |||
2895 | u32 last_status = *info->status_idx_ptr; | 2899 | u32 last_status = *info->status_idx_ptr; |
2896 | int kcqe_cnt; | 2900 | int kcqe_cnt; |
2897 | 2901 | ||
2902 | /* status block index must be read before reading the KCQ */ | ||
2903 | rmb(); | ||
2898 | while ((kcqe_cnt = cnic_get_kcqes(dev, info))) { | 2904 | while ((kcqe_cnt = cnic_get_kcqes(dev, info))) { |
2899 | 2905 | ||
2900 | service_kcqes(dev, kcqe_cnt); | 2906 | service_kcqes(dev, kcqe_cnt); |
@@ -2905,6 +2911,8 @@ static u32 cnic_service_bnx2x_kcq(struct cnic_dev *dev, struct kcq_info *info) | |||
2905 | break; | 2911 | break; |
2906 | 2912 | ||
2907 | last_status = *info->status_idx_ptr; | 2913 | last_status = *info->status_idx_ptr; |
2914 | /* status block index must be read before reading the KCQ */ | ||
2915 | rmb(); | ||
2908 | } | 2916 | } |
2909 | return last_status; | 2917 | return last_status; |
2910 | } | 2918 | } |
@@ -2913,26 +2921,35 @@ static void cnic_service_bnx2x_bh(unsigned long data) | |||
2913 | { | 2921 | { |
2914 | struct cnic_dev *dev = (struct cnic_dev *) data; | 2922 | struct cnic_dev *dev = (struct cnic_dev *) data; |
2915 | struct cnic_local *cp = dev->cnic_priv; | 2923 | struct cnic_local *cp = dev->cnic_priv; |
2916 | u32 status_idx; | 2924 | u32 status_idx, new_status_idx; |
2917 | 2925 | ||
2918 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) | 2926 | if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) |
2919 | return; | 2927 | return; |
2920 | 2928 | ||
2921 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); | 2929 | while (1) { |
2930 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq1); | ||
2922 | 2931 | ||
2923 | CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); | 2932 | CNIC_WR16(dev, cp->kcq1.io_addr, |
2933 | cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); | ||
2924 | 2934 | ||
2925 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) { | 2935 | if (!BNX2X_CHIP_IS_E2(cp->chip_id)) { |
2926 | status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); | 2936 | cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, |
2937 | status_idx, IGU_INT_ENABLE, 1); | ||
2938 | break; | ||
2939 | } | ||
2940 | |||
2941 | new_status_idx = cnic_service_bnx2x_kcq(dev, &cp->kcq2); | ||
2942 | |||
2943 | if (new_status_idx != status_idx) | ||
2944 | continue; | ||
2927 | 2945 | ||
2928 | CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx + | 2946 | CNIC_WR16(dev, cp->kcq2.io_addr, cp->kcq2.sw_prod_idx + |
2929 | MAX_KCQ_IDX); | 2947 | MAX_KCQ_IDX); |
2930 | 2948 | ||
2931 | cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, | 2949 | cnic_ack_igu_sb(dev, cp->bnx2x_igu_sb_id, IGU_SEG_ACCESS_DEF, |
2932 | status_idx, IGU_INT_ENABLE, 1); | 2950 | status_idx, IGU_INT_ENABLE, 1); |
2933 | } else { | 2951 | |
2934 | cnic_ack_bnx2x_int(dev, cp->bnx2x_igu_sb_id, USTORM_ID, | 2952 | break; |
2935 | status_idx, IGU_INT_ENABLE, 1); | ||
2936 | } | 2953 | } |
2937 | } | 2954 | } |
2938 | 2955 | ||