diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 10f4815aec7..2f39e309393 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -37,7 +37,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) device_reg_t __iomem *reg; uint8_t abort_active; uint8_t io_lock_on; - uint16_t command; + uint16_t command = 0; uint16_t *iptr; uint16_t __iomem *optr; uint32_t cnt; @@ -83,6 +83,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) return QLA_FUNCTION_TIMEOUT; } + if (IS_QLA82XX(ha) && ha->flags.fw_hung) { + /* Setting Link-Down error */ + mcp->mb[0] = MBS_LINK_DOWN_ERROR; + rval = QLA_FUNCTION_FAILED; + goto premature_exit; + } + ha->flags.mbox_busy = 1; /* Save mailbox command for debug */ ha->mcp = mcp; @@ -151,7 +158,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk(KERN_INFO "%s(%ld): Pending Mailbox timeout. " "Exiting.\n", __func__, base_vha->host_no)); - return QLA_FUNCTION_TIMEOUT; + rval = QLA_FUNCTION_TIMEOUT; + goto premature_exit; } WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); } else if (IS_FWI2_CAPABLE(ha)) @@ -176,7 +184,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk(KERN_INFO "%s(%ld): Pending Mailbox timeout. " "Exiting.\n", __func__, base_vha->host_no)); - return QLA_FUNCTION_TIMEOUT; + rval = QLA_FUNCTION_TIMEOUT; + goto premature_exit; } WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING); } else if (IS_FWI2_CAPABLE(ha)) @@ -214,6 +223,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ha->flags.mbox_int = 0; clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + if (IS_QLA82XX(ha) && ha->flags.fw_hung) { + ha->flags.mbox_busy = 0; + /* Setting Link-Down error */ + mcp->mb[0] = MBS_LINK_DOWN_ERROR; + ha->mcp = NULL; + rval = QLA_FUNCTION_FAILED; + goto premature_exit; + } + if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) rval = QLA_FUNCTION_FAILED; @@ -279,35 +297,51 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG2_3_11(printk("%s(%ld): timeout schedule " "isp_abort_needed.\n", __func__, base_vha->host_no)); - qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occurred. Scheduling ISP " - "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy); - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - qla2xxx_wake_dpc(vha); + + if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && + !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && + !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { + + qla_printk(KERN_WARNING, ha, + "Mailbox command timeout occured. " + "Scheduling ISP " "abort. eeh_busy: 0x%x\n", + ha->flags.eeh_busy); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + } } else if (!abort_active) { /* call abort directly since we are in the DPC thread */ DEBUG(printk("%s(%ld): timeout calling abort_isp\n", __func__, base_vha->host_no)); DEBUG2_3_11(printk("%s(%ld): timeout calling " "abort_isp\n", __func__, base_vha->host_no)); - qla_printk(KERN_WARNING, ha, - "Mailbox command timeout occurred. Issuing ISP " - "abort.\n"); - - set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); - clear_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); - if (ha->isp_ops->abort_isp(base_vha)) { - /* Failed. retry later. */ - set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); + + if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && + !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && + !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { + + qla_printk(KERN_WARNING, ha, + "Mailbox command timeout occured. " + "Issuing ISP abort.\n"); + + set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); + clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + if (ha->isp_ops->abort_isp(vha)) { + /* Failed. retry later. */ + set_bit(ISP_ABORT_NEEDED, + &vha->dpc_flags); + } + clear_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); + DEBUG(printk("%s(%ld): finished abort_isp\n", + __func__, vha->host_no)); + DEBUG2_3_11(printk( + "%s(%ld): finished abort_isp\n", + __func__, vha->host_no)); } - clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); - DEBUG(printk("%s(%ld): finished abort_isp\n", __func__, - base_vha->host_no)); - DEBUG2_3_11(printk("%s(%ld): finished abort_isp\n", - __func__, base_vha->host_no)); } } +premature_exit: /* Allow next mbx cmd to come in. */ complete(&ha->mbx_cmd_comp); |