dect
/
linux-2.6
Archived
13
0
Fork 0

[SCSI] qla4xxx: Disable generating pause frames for ISP83XX

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>
This commit is contained in:
Tej Parkash 2012-09-20 07:35:12 -04:00 committed by James Bottomley
parent 48a859d29f
commit 546fef27c3
5 changed files with 177 additions and 0 deletions

View 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);
}

View File

@ -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

View 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;

View 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;
}

View 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);