Loading drivers/scsi/qla2xxx/qla_def.h +6 −3 Original line number Diff line number Diff line Loading @@ -2402,13 +2402,13 @@ struct qla_hw_data { volatile struct { uint32_t mbox_int :1; uint32_t mbox_busy :1; uint32_t disable_risc_code_load :1; uint32_t enable_64bit_addressing :1; uint32_t enable_lip_reset :1; uint32_t enable_target_reset :1; uint32_t enable_lip_full_login :1; uint32_t enable_led_scheme :1; uint32_t msi_enabled :1; uint32_t msix_enabled :1; uint32_t disable_serdes :1; Loading @@ -2417,6 +2417,7 @@ struct qla_hw_data { uint32_t pci_channel_io_perm_failure :1; uint32_t fce_enabled :1; uint32_t fac_supported :1; uint32_t chip_reset_done :1; uint32_t port0 :1; uint32_t running_gold_fw :1; Loading @@ -2424,9 +2425,11 @@ struct qla_hw_data { uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; uint32_t fw_hung :1; uint32_t isp82xx_fw_hung:1; uint32_t quiesce_owner:1; uint32_t thermal_supported:1; uint32_t isp82xx_reset_hdlr_active:1; /* 26 bits */ } flags; Loading drivers/scsi/qla2xxx/qla_gbl.h +1 −0 Original line number Diff line number Diff line Loading @@ -565,6 +565,7 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); extern void qla82xx_start_iocbs(srb_t *); extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct fc_bsg_job *); Loading drivers/scsi/qla2xxx/qla_init.c +3 −8 Original line number Diff line number Diff line Loading @@ -1967,7 +1967,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) } else { /* Mailbox cmd failed. Timeout on min_wait. */ if (time_after_eq(jiffies, mtime) || (IS_QLA82XX(ha) && ha->flags.fw_hung)) ha->flags.isp82xx_fw_hung) break; } Loading Loading @@ -3980,13 +3980,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) if (!ha->flags.eeh_busy) { /* Make sure for ISP 82XX IO DMA is complete */ if (IS_QLA82XX(ha)) { if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == QLA_SUCCESS) { DEBUG2(qla_printk(KERN_INFO, ha, "Done wait for pending commands\n")); } } if (IS_QLA82XX(ha)) qla82xx_chip_reset_cleanup(vha); /* Requeue all commands in outstanding command list. */ qla2x00_abort_all_cmds(vha, DID_RESET << 16); Loading drivers/scsi/qla2xxx/qla_mbx.c +2 −2 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) return QLA_FUNCTION_TIMEOUT; } if (IS_QLA82XX(ha) && ha->flags.fw_hung) { if (ha->flags.isp82xx_fw_hung) { /* Setting Link-Down error */ mcp->mb[0] = MBS_LINK_DOWN_ERROR; rval = QLA_FUNCTION_FAILED; Loading Loading @@ -223,7 +223,7 @@ 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) { if (ha->flags.isp82xx_fw_hung) { ha->flags.mbox_busy = 0; /* Setting Link-Down error */ mcp->mb[0] = MBS_LINK_DOWN_ERROR; Loading drivers/scsi/qla2xxx/qla_nx.c +110 −45 Original line number Diff line number Diff line Loading @@ -3457,46 +3457,28 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) } } static void int qla82xx_check_fw_alive(scsi_qla_host_t *vha) { uint32_t fw_heartbeat_counter, halt_status; struct qla_hw_data *ha = vha->hw; uint32_t fw_heartbeat_counter; int status = 0; fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); fw_heartbeat_counter = qla82xx_rd_32(vha->hw, QLA82XX_PEG_ALIVE_COUNTER); /* all 0xff, assume AER/EEH in progress, ignore */ if (fw_heartbeat_counter == 0xffffffff) return; return status; if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { vha->seconds_since_last_heartbeat++; /* FW not alive after 2 seconds */ if (vha->seconds_since_last_heartbeat == 2) { vha->seconds_since_last_heartbeat = 0; halt_status = qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); if (halt_status & HALT_STATUS_UNRECOVERABLE) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): %s - detect abort needed\n", vha->host_no, __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Due to fw hung, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } status = 1; } } else vha->seconds_since_last_heartbeat = 0; vha->fw_heartbeat_counter = fw_heartbeat_counter; return status; } /* Loading Loading @@ -3598,30 +3580,18 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) void qla82xx_watchdog(scsi_qla_host_t *vha) { uint32_t dev_state; uint32_t dev_state, halt_status; struct qla_hw_data *ha = vha->hw; dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); /* don't poll if reset is going on */ 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))) { if (dev_state == QLA82XX_DEV_NEED_RESET) { if (!ha->flags.isp82xx_reset_hdlr_active) { dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { qla_printk(KERN_WARNING, ha, "%s(): Adapter reset needed!\n", __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Need reset, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { DEBUG(qla_printk(KERN_INFO, ha, Loading @@ -3631,6 +3601,31 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) qla2xxx_wake_dpc(vha); } else { qla82xx_check_fw_alive(vha); if (qla82xx_check_fw_alive(vha)) { halt_status = qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); if (halt_status & HALT_STATUS_UNRECOVERABLE) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): %s - detect abort needed\n", vha->host_no, __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); ha->flags.isp82xx_fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Due to fw hung, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } } } } Loading Loading @@ -3665,6 +3660,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) "Exiting.\n", __func__, vha->host_no); return QLA_SUCCESS; } ha->flags.isp82xx_reset_hdlr_active = 1; qla82xx_idc_lock(ha); dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); Loading @@ -3685,7 +3681,8 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) qla82xx_idc_unlock(ha); if (rval == QLA_SUCCESS) { ha->flags.fw_hung = 0; ha->flags.isp82xx_fw_hung = 0; ha->flags.isp82xx_reset_hdlr_active = 0; qla82xx_restart_isp(vha); } Loading Loading @@ -3793,3 +3790,71 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) return status; } void qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) { int i; unsigned long flags; struct qla_hw_data *ha = vha->hw; /* Check if 82XX firmware is alive or not * We may have arrived here from NEED_RESET * detection only */ if (!ha->flags.isp82xx_fw_hung) { for (i = 0; i < 2; i++) { msleep(1000); if (qla82xx_check_fw_alive(vha)) { ha->flags.isp82xx_fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; complete(&ha->mbx_intr_comp); } break; } } } /* Abort all commands gracefully if fw NOT hung */ if (!ha->flags.isp82xx_fw_hung) { int cnt, que; srb_t *sp; struct req_que *req; spin_lock_irqsave(&ha->hardware_lock, flags); for (que = 0; que < ha->max_req_queues; que++) { req = ha->req_q_map[que]; if (!req) continue; for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { if (!sp->ctx || (sp->flags & SRB_FCP_CMND_DMA_VALID)) { spin_unlock_irqrestore( &ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { qla_printk(KERN_INFO, ha, "scsi(%ld): mbx abort command failed in %s\n", vha->host_no, __func__); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): mbx abort command success in %s\n", vha->host_no, __func__); } spin_lock_irqsave(&ha->hardware_lock, flags); } } } } spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for pending cmds (physical and virtual) to complete */ if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == QLA_SUCCESS) { DEBUG2(qla_printk(KERN_INFO, ha, "Done wait for pending commands\n")); } } } Loading
drivers/scsi/qla2xxx/qla_def.h +6 −3 Original line number Diff line number Diff line Loading @@ -2402,13 +2402,13 @@ struct qla_hw_data { volatile struct { uint32_t mbox_int :1; uint32_t mbox_busy :1; uint32_t disable_risc_code_load :1; uint32_t enable_64bit_addressing :1; uint32_t enable_lip_reset :1; uint32_t enable_target_reset :1; uint32_t enable_lip_full_login :1; uint32_t enable_led_scheme :1; uint32_t msi_enabled :1; uint32_t msix_enabled :1; uint32_t disable_serdes :1; Loading @@ -2417,6 +2417,7 @@ struct qla_hw_data { uint32_t pci_channel_io_perm_failure :1; uint32_t fce_enabled :1; uint32_t fac_supported :1; uint32_t chip_reset_done :1; uint32_t port0 :1; uint32_t running_gold_fw :1; Loading @@ -2424,9 +2425,11 @@ struct qla_hw_data { uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; uint32_t fcp_prio_enabled :1; uint32_t fw_hung :1; uint32_t isp82xx_fw_hung:1; uint32_t quiesce_owner:1; uint32_t thermal_supported:1; uint32_t isp82xx_reset_hdlr_active:1; /* 26 bits */ } flags; Loading
drivers/scsi/qla2xxx/qla_gbl.h +1 −0 Original line number Diff line number Diff line Loading @@ -565,6 +565,7 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *); extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); extern void qla82xx_start_iocbs(srb_t *); extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); /* BSG related functions */ extern int qla24xx_bsg_request(struct fc_bsg_job *); Loading
drivers/scsi/qla2xxx/qla_init.c +3 −8 Original line number Diff line number Diff line Loading @@ -1967,7 +1967,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) } else { /* Mailbox cmd failed. Timeout on min_wait. */ if (time_after_eq(jiffies, mtime) || (IS_QLA82XX(ha) && ha->flags.fw_hung)) ha->flags.isp82xx_fw_hung) break; } Loading Loading @@ -3980,13 +3980,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) if (!ha->flags.eeh_busy) { /* Make sure for ISP 82XX IO DMA is complete */ if (IS_QLA82XX(ha)) { if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == QLA_SUCCESS) { DEBUG2(qla_printk(KERN_INFO, ha, "Done wait for pending commands\n")); } } if (IS_QLA82XX(ha)) qla82xx_chip_reset_cleanup(vha); /* Requeue all commands in outstanding command list. */ qla2x00_abort_all_cmds(vha, DID_RESET << 16); Loading
drivers/scsi/qla2xxx/qla_mbx.c +2 −2 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) return QLA_FUNCTION_TIMEOUT; } if (IS_QLA82XX(ha) && ha->flags.fw_hung) { if (ha->flags.isp82xx_fw_hung) { /* Setting Link-Down error */ mcp->mb[0] = MBS_LINK_DOWN_ERROR; rval = QLA_FUNCTION_FAILED; Loading Loading @@ -223,7 +223,7 @@ 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) { if (ha->flags.isp82xx_fw_hung) { ha->flags.mbox_busy = 0; /* Setting Link-Down error */ mcp->mb[0] = MBS_LINK_DOWN_ERROR; Loading
drivers/scsi/qla2xxx/qla_nx.c +110 −45 Original line number Diff line number Diff line Loading @@ -3457,46 +3457,28 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) } } static void int qla82xx_check_fw_alive(scsi_qla_host_t *vha) { uint32_t fw_heartbeat_counter, halt_status; struct qla_hw_data *ha = vha->hw; uint32_t fw_heartbeat_counter; int status = 0; fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); fw_heartbeat_counter = qla82xx_rd_32(vha->hw, QLA82XX_PEG_ALIVE_COUNTER); /* all 0xff, assume AER/EEH in progress, ignore */ if (fw_heartbeat_counter == 0xffffffff) return; return status; if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { vha->seconds_since_last_heartbeat++; /* FW not alive after 2 seconds */ if (vha->seconds_since_last_heartbeat == 2) { vha->seconds_since_last_heartbeat = 0; halt_status = qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); if (halt_status & HALT_STATUS_UNRECOVERABLE) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): %s - detect abort needed\n", vha->host_no, __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Due to fw hung, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } status = 1; } } else vha->seconds_since_last_heartbeat = 0; vha->fw_heartbeat_counter = fw_heartbeat_counter; return status; } /* Loading Loading @@ -3598,30 +3580,18 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) void qla82xx_watchdog(scsi_qla_host_t *vha) { uint32_t dev_state; uint32_t dev_state, halt_status; struct qla_hw_data *ha = vha->hw; dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); /* don't poll if reset is going on */ 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))) { if (dev_state == QLA82XX_DEV_NEED_RESET) { if (!ha->flags.isp82xx_reset_hdlr_active) { dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { qla_printk(KERN_WARNING, ha, "%s(): Adapter reset needed!\n", __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Need reset, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { DEBUG(qla_printk(KERN_INFO, ha, Loading @@ -3631,6 +3601,31 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) qla2xxx_wake_dpc(vha); } else { qla82xx_check_fw_alive(vha); if (qla82xx_check_fw_alive(vha)) { halt_status = qla82xx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); if (halt_status & HALT_STATUS_UNRECOVERABLE) { set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): %s - detect abort needed\n", vha->host_no, __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); ha->flags.isp82xx_fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, "Due to fw hung, doing premature " "completion of mbx command\n")); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } } } } Loading Loading @@ -3665,6 +3660,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) "Exiting.\n", __func__, vha->host_no); return QLA_SUCCESS; } ha->flags.isp82xx_reset_hdlr_active = 1; qla82xx_idc_lock(ha); dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); Loading @@ -3685,7 +3681,8 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) qla82xx_idc_unlock(ha); if (rval == QLA_SUCCESS) { ha->flags.fw_hung = 0; ha->flags.isp82xx_fw_hung = 0; ha->flags.isp82xx_reset_hdlr_active = 0; qla82xx_restart_isp(vha); } Loading Loading @@ -3793,3 +3790,71 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) return status; } void qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) { int i; unsigned long flags; struct qla_hw_data *ha = vha->hw; /* Check if 82XX firmware is alive or not * We may have arrived here from NEED_RESET * detection only */ if (!ha->flags.isp82xx_fw_hung) { for (i = 0; i < 2; i++) { msleep(1000); if (qla82xx_check_fw_alive(vha)) { ha->flags.isp82xx_fw_hung = 1; if (ha->flags.mbox_busy) { ha->flags.mbox_int = 1; complete(&ha->mbx_intr_comp); } break; } } } /* Abort all commands gracefully if fw NOT hung */ if (!ha->flags.isp82xx_fw_hung) { int cnt, que; srb_t *sp; struct req_que *req; spin_lock_irqsave(&ha->hardware_lock, flags); for (que = 0; que < ha->max_req_queues; que++) { req = ha->req_q_map[que]; if (!req) continue; for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { if (!sp->ctx || (sp->flags & SRB_FCP_CMND_DMA_VALID)) { spin_unlock_irqrestore( &ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { qla_printk(KERN_INFO, ha, "scsi(%ld): mbx abort command failed in %s\n", vha->host_no, __func__); } else { qla_printk(KERN_INFO, ha, "scsi(%ld): mbx abort command success in %s\n", vha->host_no, __func__); } spin_lock_irqsave(&ha->hardware_lock, flags); } } } } spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Wait for pending cmds (physical and virtual) to complete */ if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == QLA_SUCCESS) { DEBUG2(qla_printk(KERN_INFO, ha, "Done wait for pending commands\n")); } } }