aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cnic.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-04 00:27:42 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-04 00:27:42 -0500
commit0a0e9ae1bd788bc19adc4d4ae08c98b233697402 (patch)
tree13825eeb5bbeae27d66e95f12168eff4b60701ab /drivers/net/cnic.c
parent01a16b21d6adf992aa863186c3c4e561a57c1714 (diff)
parentb65a0e0c84cf489bfa00d6aa6c48abc5a237100f (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.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 25f08880ae0f..271a1f00c224 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