diff options
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.c | 144 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.h | 13 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 15 |
5 files changed, 177 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c index 8b367efb7239..6e9af20be12f 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.c +++ b/drivers/scsi/qla4xxx/ql4_83xx.c @@ -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); +} diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h index 18d86abbf276..6a00f903f2a6 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.h +++ b/drivers/scsi/qla4xxx/ql4_83xx.h @@ -41,6 +41,19 @@ #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 diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 3eb5fd957c4a..57a5a3cf5770 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -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; diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 0d3d641f891b..3d41034191f0 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -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; } diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 35546807c9f7..ad2da9cd7000 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -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); |