diff options
author | Giridhar Malavali <giridhar.malavali@qlogic.com> | 2011-02-23 18:27:10 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-25 12:51:44 -0500 |
commit | 7190575f7a48c82fd99363748544023739dc4bb8 (patch) | |
tree | af1cd65418a060c98a2997e082b1cf5171e0aac3 /drivers/scsi/qla2xxx/qla_nx.c | |
parent | cf2d771255251bfd4570b01bea491a631b4033c9 (diff) |
[SCSI] qla2xxx: Abort pending commands for faster recovery during ISP reset.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: Madhuranath Iyengar <Madhu.Iyengar@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 155 |
1 files changed, 110 insertions, 45 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 4ff80ee1d416..f1ffee4b44ca 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -3457,46 +3457,28 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) | |||
3457 | } | 3457 | } |
3458 | } | 3458 | } |
3459 | 3459 | ||
3460 | static void | 3460 | int |
3461 | qla82xx_check_fw_alive(scsi_qla_host_t *vha) | 3461 | qla82xx_check_fw_alive(scsi_qla_host_t *vha) |
3462 | { | 3462 | { |
3463 | uint32_t fw_heartbeat_counter, halt_status; | 3463 | uint32_t fw_heartbeat_counter; |
3464 | struct qla_hw_data *ha = vha->hw; | 3464 | int status = 0; |
3465 | 3465 | ||
3466 | fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 3466 | fw_heartbeat_counter = qla82xx_rd_32(vha->hw, |
3467 | QLA82XX_PEG_ALIVE_COUNTER); | ||
3467 | /* all 0xff, assume AER/EEH in progress, ignore */ | 3468 | /* all 0xff, assume AER/EEH in progress, ignore */ |
3468 | if (fw_heartbeat_counter == 0xffffffff) | 3469 | if (fw_heartbeat_counter == 0xffffffff) |
3469 | return; | 3470 | return status; |
3470 | if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { | 3471 | if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { |
3471 | vha->seconds_since_last_heartbeat++; | 3472 | vha->seconds_since_last_heartbeat++; |
3472 | /* FW not alive after 2 seconds */ | 3473 | /* FW not alive after 2 seconds */ |
3473 | if (vha->seconds_since_last_heartbeat == 2) { | 3474 | if (vha->seconds_since_last_heartbeat == 2) { |
3474 | vha->seconds_since_last_heartbeat = 0; | 3475 | vha->seconds_since_last_heartbeat = 0; |
3475 | halt_status = qla82xx_rd_32(ha, | 3476 | status = 1; |
3476 | QLA82XX_PEG_HALT_STATUS1); | ||
3477 | if (halt_status & HALT_STATUS_UNRECOVERABLE) { | ||
3478 | set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); | ||
3479 | } else { | ||
3480 | qla_printk(KERN_INFO, ha, | ||
3481 | "scsi(%ld): %s - detect abort needed\n", | ||
3482 | vha->host_no, __func__); | ||
3483 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | ||
3484 | } | ||
3485 | qla2xxx_wake_dpc(vha); | ||
3486 | ha->flags.fw_hung = 1; | ||
3487 | if (ha->flags.mbox_busy) { | ||
3488 | ha->flags.mbox_int = 1; | ||
3489 | DEBUG2(qla_printk(KERN_ERR, ha, | ||
3490 | "Due to fw hung, doing premature " | ||
3491 | "completion of mbx command\n")); | ||
3492 | if (test_bit(MBX_INTR_WAIT, | ||
3493 | &ha->mbx_cmd_flags)) | ||
3494 | complete(&ha->mbx_intr_comp); | ||
3495 | } | ||
3496 | } | 3477 | } |
3497 | } else | 3478 | } else |
3498 | vha->seconds_since_last_heartbeat = 0; | 3479 | vha->seconds_since_last_heartbeat = 0; |
3499 | vha->fw_heartbeat_counter = fw_heartbeat_counter; | 3480 | vha->fw_heartbeat_counter = fw_heartbeat_counter; |
3481 | return status; | ||
3500 | } | 3482 | } |
3501 | 3483 | ||
3502 | /* | 3484 | /* |
@@ -3598,30 +3580,18 @@ exit: | |||
3598 | 3580 | ||
3599 | void qla82xx_watchdog(scsi_qla_host_t *vha) | 3581 | void qla82xx_watchdog(scsi_qla_host_t *vha) |
3600 | { | 3582 | { |
3601 | uint32_t dev_state; | 3583 | uint32_t dev_state, halt_status; |
3602 | struct qla_hw_data *ha = vha->hw; | 3584 | struct qla_hw_data *ha = vha->hw; |
3603 | 3585 | ||
3604 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | ||
3605 | |||
3606 | /* don't poll if reset is going on */ | 3586 | /* don't poll if reset is going on */ |
3607 | if (!(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || | 3587 | if (!ha->flags.isp82xx_reset_hdlr_active) { |
3608 | test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || | 3588 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
3609 | test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))) { | 3589 | if (dev_state == QLA82XX_DEV_NEED_RESET && |
3610 | if (dev_state == QLA82XX_DEV_NEED_RESET) { | 3590 | !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { |
3611 | qla_printk(KERN_WARNING, ha, | 3591 | qla_printk(KERN_WARNING, ha, |
3612 | "%s(): Adapter reset needed!\n", __func__); | 3592 | "%s(): Adapter reset needed!\n", __func__); |
3613 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3593 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3614 | qla2xxx_wake_dpc(vha); | 3594 | qla2xxx_wake_dpc(vha); |
3615 | ha->flags.fw_hung = 1; | ||
3616 | if (ha->flags.mbox_busy) { | ||
3617 | ha->flags.mbox_int = 1; | ||
3618 | DEBUG2(qla_printk(KERN_ERR, ha, | ||
3619 | "Need reset, doing premature " | ||
3620 | "completion of mbx command\n")); | ||
3621 | if (test_bit(MBX_INTR_WAIT, | ||
3622 | &ha->mbx_cmd_flags)) | ||
3623 | complete(&ha->mbx_intr_comp); | ||
3624 | } | ||
3625 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && | 3595 | } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && |
3626 | !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { | 3596 | !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { |
3627 | DEBUG(qla_printk(KERN_INFO, ha, | 3597 | DEBUG(qla_printk(KERN_INFO, ha, |
@@ -3631,6 +3601,31 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3631 | qla2xxx_wake_dpc(vha); | 3601 | qla2xxx_wake_dpc(vha); |
3632 | } else { | 3602 | } else { |
3633 | qla82xx_check_fw_alive(vha); | 3603 | qla82xx_check_fw_alive(vha); |
3604 | if (qla82xx_check_fw_alive(vha)) { | ||
3605 | halt_status = qla82xx_rd_32(ha, | ||
3606 | QLA82XX_PEG_HALT_STATUS1); | ||
3607 | if (halt_status & HALT_STATUS_UNRECOVERABLE) { | ||
3608 | set_bit(ISP_UNRECOVERABLE, | ||
3609 | &vha->dpc_flags); | ||
3610 | } else { | ||
3611 | qla_printk(KERN_INFO, ha, | ||
3612 | "scsi(%ld): %s - detect abort needed\n", | ||
3613 | vha->host_no, __func__); | ||
3614 | set_bit(ISP_ABORT_NEEDED, | ||
3615 | &vha->dpc_flags); | ||
3616 | } | ||
3617 | qla2xxx_wake_dpc(vha); | ||
3618 | ha->flags.isp82xx_fw_hung = 1; | ||
3619 | if (ha->flags.mbox_busy) { | ||
3620 | ha->flags.mbox_int = 1; | ||
3621 | DEBUG2(qla_printk(KERN_ERR, ha, | ||
3622 | "Due to fw hung, doing premature " | ||
3623 | "completion of mbx command\n")); | ||
3624 | if (test_bit(MBX_INTR_WAIT, | ||
3625 | &ha->mbx_cmd_flags)) | ||
3626 | complete(&ha->mbx_intr_comp); | ||
3627 | } | ||
3628 | } | ||
3634 | } | 3629 | } |
3635 | } | 3630 | } |
3636 | } | 3631 | } |
@@ -3665,6 +3660,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) | |||
3665 | "Exiting.\n", __func__, vha->host_no); | 3660 | "Exiting.\n", __func__, vha->host_no); |
3666 | return QLA_SUCCESS; | 3661 | return QLA_SUCCESS; |
3667 | } | 3662 | } |
3663 | ha->flags.isp82xx_reset_hdlr_active = 1; | ||
3668 | 3664 | ||
3669 | qla82xx_idc_lock(ha); | 3665 | qla82xx_idc_lock(ha); |
3670 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 3666 | dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
@@ -3685,7 +3681,8 @@ qla82xx_abort_isp(scsi_qla_host_t *vha) | |||
3685 | qla82xx_idc_unlock(ha); | 3681 | qla82xx_idc_unlock(ha); |
3686 | 3682 | ||
3687 | if (rval == QLA_SUCCESS) { | 3683 | if (rval == QLA_SUCCESS) { |
3688 | ha->flags.fw_hung = 0; | 3684 | ha->flags.isp82xx_fw_hung = 0; |
3685 | ha->flags.isp82xx_reset_hdlr_active = 0; | ||
3689 | qla82xx_restart_isp(vha); | 3686 | qla82xx_restart_isp(vha); |
3690 | } | 3687 | } |
3691 | 3688 | ||
@@ -3793,3 +3790,71 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha) | |||
3793 | 3790 | ||
3794 | return status; | 3791 | return status; |
3795 | } | 3792 | } |
3793 | |||
3794 | void | ||
3795 | qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) | ||
3796 | { | ||
3797 | int i; | ||
3798 | unsigned long flags; | ||
3799 | struct qla_hw_data *ha = vha->hw; | ||
3800 | |||
3801 | /* Check if 82XX firmware is alive or not | ||
3802 | * We may have arrived here from NEED_RESET | ||
3803 | * detection only | ||
3804 | */ | ||
3805 | if (!ha->flags.isp82xx_fw_hung) { | ||
3806 | for (i = 0; i < 2; i++) { | ||
3807 | msleep(1000); | ||
3808 | if (qla82xx_check_fw_alive(vha)) { | ||
3809 | ha->flags.isp82xx_fw_hung = 1; | ||
3810 | if (ha->flags.mbox_busy) { | ||
3811 | ha->flags.mbox_int = 1; | ||
3812 | complete(&ha->mbx_intr_comp); | ||
3813 | } | ||
3814 | break; | ||
3815 | } | ||
3816 | } | ||
3817 | } | ||
3818 | |||
3819 | /* Abort all commands gracefully if fw NOT hung */ | ||
3820 | if (!ha->flags.isp82xx_fw_hung) { | ||
3821 | int cnt, que; | ||
3822 | srb_t *sp; | ||
3823 | struct req_que *req; | ||
3824 | |||
3825 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3826 | for (que = 0; que < ha->max_req_queues; que++) { | ||
3827 | req = ha->req_q_map[que]; | ||
3828 | if (!req) | ||
3829 | continue; | ||
3830 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
3831 | sp = req->outstanding_cmds[cnt]; | ||
3832 | if (sp) { | ||
3833 | if (!sp->ctx || | ||
3834 | (sp->flags & SRB_FCP_CMND_DMA_VALID)) { | ||
3835 | spin_unlock_irqrestore( | ||
3836 | &ha->hardware_lock, flags); | ||
3837 | if (ha->isp_ops->abort_command(sp)) { | ||
3838 | qla_printk(KERN_INFO, ha, | ||
3839 | "scsi(%ld): mbx abort command failed in %s\n", | ||
3840 | vha->host_no, __func__); | ||
3841 | } else { | ||
3842 | qla_printk(KERN_INFO, ha, | ||
3843 | "scsi(%ld): mbx abort command success in %s\n", | ||
3844 | vha->host_no, __func__); | ||
3845 | } | ||
3846 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3847 | } | ||
3848 | } | ||
3849 | } | ||
3850 | } | ||
3851 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3852 | |||
3853 | /* Wait for pending cmds (physical and virtual) to complete */ | ||
3854 | if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0, | ||
3855 | WAIT_HOST) == QLA_SUCCESS) { | ||
3856 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
3857 | "Done wait for pending commands\n")); | ||
3858 | } | ||
3859 | } | ||
3860 | } | ||