cnic: Reset iSCSI EQ during shutdown.
authorMichael Chan <mchan@broadcom.com>
Wed, 5 Dec 2012 10:10:14 +0000 (10:10 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Dec 2012 21:01:28 +0000 (16:01 -0500)
Without the reset, reloading the cnic driver can cause the iSCSI
Event Queue to be out of sync with the driver and cause intermittent
crash.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Acked-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
drivers/net/ethernet/broadcom/cnic.c

index 620fe939ecfd357ed1e852bd0350c3687886a8b5..60a83ad103700602814842e8d3f47e40386801e8 100644 (file)
        (IRO[159].base + ((funcId) * IRO[159].m1))
 #define CSTORM_FUNC_EN_OFFSET(funcId) \
        (IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hcIndex, sbId) \
+       (IRO[139].base + ((hcIndex) * IRO[139].m1) + ((sbId) * IRO[139].m2))
+#define CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hcIndex, sbId) \
+       (IRO[138].base + (((hcIndex)>>2) * IRO[138].m1) + (((hcIndex)&3) \
+       * IRO[138].m2) + ((sbId) * IRO[138].m3))
 #define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
 #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
        (IRO[316].base + ((pfId) * IRO[316].m1))
index 3b825f422090b3d45576c616d62c857bc42aac1a..5437e2aa97b56a489c2fbcd4e16a0f8f976070a3 100644 (file)
@@ -5344,8 +5344,27 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
 static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       u32 hc_index = HC_INDEX_ISCSI_EQ_CONS;
+       u32 sb_id = cp->status_blk_num;
+       u32 idx_off, syn_off;
 
        cnic_free_irq(dev);
+
+       if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+               idx_off = offsetof(struct hc_status_block_e2, index_values) +
+                         (hc_index * sizeof(u16));
+
+               syn_off = CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hc_index, sb_id);
+       } else {
+               idx_off = offsetof(struct hc_status_block_e1x, index_values) +
+                         (hc_index * sizeof(u16));
+
+               syn_off = CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hc_index, sb_id);
+       }
+       CNIC_WR16(dev, BAR_CSTRORM_INTMEM + syn_off, 0);
+       CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(sb_id) +
+                 idx_off, 0);
+
        *cp->kcq1.hw_prod_idx_ptr = 0;
        CNIC_WR(dev, BAR_CSTRORM_INTMEM +
                CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);