[SCSI] qla4xxx: Disable generating pause frames for ISP83XX
authorTej Parkash <tej.parkash@qlogic.com>
Thu, 20 Sep 2012 11:35:12 +0000 (07:35 -0400)
committerJames Bottomley <JBottomley@Parallels.com>
Mon, 24 Sep 2012 08:49:00 +0000 (12:49 +0400)
In case of FW hung ISP83XX generates continuous pause frames
which causes switch to disable port.
Added fix to disable generating pause frames in case of
FW hung

Signed-off-by: Tej Parkash <tej.parkash@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_83xx.c
drivers/scsi/qla4xxx/ql4_83xx.h
drivers/scsi/qla4xxx/ql4_glbl.h
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c

index 8b367efb7239e9813095ba3a43f25479e0c5a71a..6e9af20be12f8a720b06279a1800c579f2fc713b 100644 (file)
@@ -1465,3 +1465,147 @@ exit_isp_reset:
 
        return rval;
 }
+
+static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha)
+{
+       u32 val = 0, val1 = 0;
+       int i, status = QLA_SUCCESS;
+
+       status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val);
+       DEBUG2(ql4_printk(KERN_INFO, ha, "SRE-Shim Ctrl:0x%x\n", val));
+
+       /* Port 0 Rx Buffer Pause Threshold Registers. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+               "Port 0 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));
+       for (i = 0; i < 8; i++) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                               QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4), &val);
+               DEBUG2(pr_info("0x%x ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       /* Port 1 Rx Buffer Pause Threshold Registers. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+               "Port 1 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));
+       for (i = 0; i < 8; i++) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                               QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4), &val);
+               DEBUG2(pr_info("0x%x  ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       /* Port 0 RxB Traffic Class Max Cell Registers. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+               "Port 0 RxB Traffic Class Max Cell Registers[3..0]:"));
+       for (i = 0; i < 4; i++) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                              QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4), &val);
+               DEBUG2(pr_info("0x%x  ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       /* Port 1 RxB Traffic Class Max Cell Registers. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+               "Port 1 RxB Traffic Class Max Cell Registers[3..0]:"));
+       for (i = 0; i < 4; i++) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                              QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4), &val);
+               DEBUG2(pr_info("0x%x  ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       /* Port 0 RxB Rx Traffic Class Stats. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "Port 0 RxB Rx Traffic Class Stats [TC7..TC0]"));
+       for (i = 7; i >= 0; i--) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                                                  QLA83XX_PORT0_RXB_TC_STATS,
+                                                  &val);
+               val &= ~(0x7 << 29);    /* Reset bits 29 to 31 */
+               qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS,
+                                         (val | (i << 29)));
+               status = qla4_83xx_rd_reg_indirect(ha,
+                                                  QLA83XX_PORT0_RXB_TC_STATS,
+                                                  &val);
+               DEBUG2(pr_info("0x%x  ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       /* Port 1 RxB Rx Traffic Class Stats. */
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "Port 1 RxB Rx Traffic Class Stats [TC7..TC0]"));
+       for (i = 7; i >= 0; i--) {
+               status = qla4_83xx_rd_reg_indirect(ha,
+                                                  QLA83XX_PORT1_RXB_TC_STATS,
+                                                  &val);
+               val &= ~(0x7 << 29);    /* Reset bits 29 to 31 */
+               qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS,
+                                         (val | (i << 29)));
+               status = qla4_83xx_rd_reg_indirect(ha,
+                                                  QLA83XX_PORT1_RXB_TC_STATS,
+                                                  &val);
+               DEBUG2(pr_info("0x%x  ", val));
+       }
+
+       DEBUG2(pr_info("\n"));
+
+       status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS,
+                                          &val);
+       status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS,
+                                          &val1);
+
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",
+                         val, val1));
+}
+
+static void __qla4_83xx_disable_pause(struct scsi_qla_host *ha)
+{
+       int i;
+
+       /* set SRE-Shim Control Register */
+       qla4_83xx_wr_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL,
+                                 QLA83XX_SET_PAUSE_VAL);
+
+       for (i = 0; i < 8; i++) {
+               /* Port 0 Rx Buffer Pause Threshold Registers. */
+               qla4_83xx_wr_reg_indirect(ha,
+                                     QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4),
+                                     QLA83XX_SET_PAUSE_VAL);
+               /* Port 1 Rx Buffer Pause Threshold Registers. */
+               qla4_83xx_wr_reg_indirect(ha,
+                                     QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4),
+                                     QLA83XX_SET_PAUSE_VAL);
+       }
+
+       for (i = 0; i < 4; i++) {
+               /* Port 0 RxB Traffic Class Max Cell Registers. */
+               qla4_83xx_wr_reg_indirect(ha,
+                                    QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4),
+                                    QLA83XX_SET_TC_MAX_CELL_VAL);
+               /* Port 1 RxB Traffic Class Max Cell Registers. */
+               qla4_83xx_wr_reg_indirect(ha,
+                                    QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4),
+                                    QLA83XX_SET_TC_MAX_CELL_VAL);
+       }
+
+       qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS,
+                                 QLA83XX_SET_PAUSE_VAL);
+       qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS,
+                                 QLA83XX_SET_PAUSE_VAL);
+
+       ql4_printk(KERN_INFO, ha, "Disabled pause frames successfully.\n");
+}
+
+void qla4_83xx_disable_pause(struct scsi_qla_host *ha)
+{
+       ha->isp_ops->idc_lock(ha);
+       qla4_83xx_dump_pause_control_regs(ha);
+       __qla4_83xx_disable_pause(ha);
+       ha->isp_ops->idc_unlock(ha);
+}
index 18d86abbf27643f262ea0bcd2e06a03bb0d6d955..6a00f903f2a6f584edc19ae3a65bca6fac56258d 100644 (file)
 #define QLA83XX_CRB_IDC_VER_MINOR      0x3798
 #define QLA83XX_IDC_DRV_CTRL           0x3790
 #define QLA83XX_IDC_DRV_AUDIT          0x3794
+#define QLA83XX_SRE_SHIM_CONTROL       0x0D200284
+#define QLA83XX_PORT0_RXB_PAUSE_THRS   0x0B2003A4
+#define QLA83XX_PORT1_RXB_PAUSE_THRS   0x0B2013A4
+#define QLA83XX_PORT0_RXB_TC_MAX_CELL  0x0B200388
+#define QLA83XX_PORT1_RXB_TC_MAX_CELL  0x0B201388
+#define QLA83XX_PORT0_RXB_TC_STATS     0x0B20039C
+#define QLA83XX_PORT1_RXB_TC_STATS     0x0B20139C
+#define QLA83XX_PORT2_IFB_PAUSE_THRS   0x0B200704
+#define QLA83XX_PORT3_IFB_PAUSE_THRS   0x0B201704
+
+/* set value to pause threshold value */
+#define QLA83XX_SET_PAUSE_VAL          0x0
+#define QLA83XX_SET_TC_MAX_CELL_VAL    0x03FF03FF
 
 /* qla_83xx_reg_tbl registers */
 #define QLA83XX_PEG_HALT_STATUS1       0x34A8
index 3eb5fd957c4ab2cbe75a67fada94c10dd1a71e9f..57a5a3cf5770d5e402d88db55feead1b417a3175 100644 (file)
@@ -258,6 +258,7 @@ int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha);
 int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param);
 int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha);
 int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha);
+void qla4_83xx_disable_pause(struct scsi_qla_host *ha);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdontresethba;
index 0d3d641f891bf8fb44c0c3906dc40eb87951cb23..3d41034191f02588b6c94cc4ec7c4d6d53fb0650 100644 (file)
@@ -204,6 +204,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
                        qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
                                        CRB_NIU_XG_PAUSE_CTL_P0 |
                                        CRB_NIU_XG_PAUSE_CTL_P1);
+               } else if (is_qla8032(ha)) {
+                       ql4_printk(KERN_INFO, ha, " %s: disabling pause transmit on port 0 & 1.\n",
+                                  __func__);
+                       qla4_83xx_disable_pause(ha);
                }
                goto mbox_exit;
        }
index 35546807c9f73d1517712b7b5538e0c1909780fa..ad2da9cd7000be04e4ed18fd98137ef527e3b408 100644 (file)
@@ -2946,6 +2946,14 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)
 
        set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
 
+       if (is_qla8032(ha) &&
+           !test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {
+               ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",
+                          __func__);
+               /* disable pause frame for ISP83xx */
+               qla4_83xx_disable_pause(ha);
+       }
+
        iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);
 
        if (test_bit(DPC_RESET_HA, &ha->dpc_flags))
@@ -3391,6 +3399,13 @@ static void qla4xxx_do_dpc(struct work_struct *work)
 
        if (is_qla80XX(ha)) {
                if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
+                       if (is_qla8032(ha)) {
+                               ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",
+                                          __func__);
+                               /* disable pause frame for ISP83xx */
+                               qla4_83xx_disable_pause(ha);
+                       }
+
                        ha->isp_ops->idc_lock(ha);
                        qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,
                                            QLA8XXX_DEV_FAILED);
This page took 0.029669 seconds and 5 git commands to generate.