aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorGiridhar Malavali <giridhar.malavali@qlogic.com>2011-02-23 18:27:10 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-25 12:51:44 -0500
commit7190575f7a48c82fd99363748544023739dc4bb8 (patch)
treeaf1cd65418a060c98a2997e082b1cf5171e0aac3 /drivers/scsi/qla2xxx
parentcf2d771255251bfd4570b01bea491a631b4033c9 (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')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h9
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c155
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c6
6 files changed, 125 insertions, 61 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ccfc8e78be21..6c51c0a35b9e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2402,13 +2402,13 @@ struct qla_hw_data {
2402 volatile struct { 2402 volatile struct {
2403 uint32_t mbox_int :1; 2403 uint32_t mbox_int :1;
2404 uint32_t mbox_busy :1; 2404 uint32_t mbox_busy :1;
2405
2406 uint32_t disable_risc_code_load :1; 2405 uint32_t disable_risc_code_load :1;
2407 uint32_t enable_64bit_addressing :1; 2406 uint32_t enable_64bit_addressing :1;
2408 uint32_t enable_lip_reset :1; 2407 uint32_t enable_lip_reset :1;
2409 uint32_t enable_target_reset :1; 2408 uint32_t enable_target_reset :1;
2410 uint32_t enable_lip_full_login :1; 2409 uint32_t enable_lip_full_login :1;
2411 uint32_t enable_led_scheme :1; 2410 uint32_t enable_led_scheme :1;
2411
2412 uint32_t msi_enabled :1; 2412 uint32_t msi_enabled :1;
2413 uint32_t msix_enabled :1; 2413 uint32_t msix_enabled :1;
2414 uint32_t disable_serdes :1; 2414 uint32_t disable_serdes :1;
@@ -2417,6 +2417,7 @@ struct qla_hw_data {
2417 uint32_t pci_channel_io_perm_failure :1; 2417 uint32_t pci_channel_io_perm_failure :1;
2418 uint32_t fce_enabled :1; 2418 uint32_t fce_enabled :1;
2419 uint32_t fac_supported :1; 2419 uint32_t fac_supported :1;
2420
2420 uint32_t chip_reset_done :1; 2421 uint32_t chip_reset_done :1;
2421 uint32_t port0 :1; 2422 uint32_t port0 :1;
2422 uint32_t running_gold_fw :1; 2423 uint32_t running_gold_fw :1;
@@ -2424,9 +2425,11 @@ struct qla_hw_data {
2424 uint32_t cpu_affinity_enabled :1; 2425 uint32_t cpu_affinity_enabled :1;
2425 uint32_t disable_msix_handshake :1; 2426 uint32_t disable_msix_handshake :1;
2426 uint32_t fcp_prio_enabled :1; 2427 uint32_t fcp_prio_enabled :1;
2427 uint32_t fw_hung :1; 2428 uint32_t isp82xx_fw_hung:1;
2428 uint32_t quiesce_owner:1; 2429
2430 uint32_t quiesce_owner:1;
2429 uint32_t thermal_supported:1; 2431 uint32_t thermal_supported:1;
2432 uint32_t isp82xx_reset_hdlr_active:1;
2430 /* 26 bits */ 2433 /* 26 bits */
2431 } flags; 2434 } flags;
2432 2435
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 89e900adb679..d48326ee3f61 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -565,6 +565,7 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
565extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *); 565extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
566extern void qla82xx_start_iocbs(srb_t *); 566extern void qla82xx_start_iocbs(srb_t *);
567extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *); 567extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
568extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
568 569
569/* BSG related functions */ 570/* BSG related functions */
570extern int qla24xx_bsg_request(struct fc_bsg_job *); 571extern int qla24xx_bsg_request(struct fc_bsg_job *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f948e1a73aec..6370cdc193d5 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1967,7 +1967,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
1967 } else { 1967 } else {
1968 /* Mailbox cmd failed. Timeout on min_wait. */ 1968 /* Mailbox cmd failed. Timeout on min_wait. */
1969 if (time_after_eq(jiffies, mtime) || 1969 if (time_after_eq(jiffies, mtime) ||
1970 (IS_QLA82XX(ha) && ha->flags.fw_hung)) 1970 ha->flags.isp82xx_fw_hung)
1971 break; 1971 break;
1972 } 1972 }
1973 1973
@@ -3980,13 +3980,8 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
3980 3980
3981 if (!ha->flags.eeh_busy) { 3981 if (!ha->flags.eeh_busy) {
3982 /* Make sure for ISP 82XX IO DMA is complete */ 3982 /* Make sure for ISP 82XX IO DMA is complete */
3983 if (IS_QLA82XX(ha)) { 3983 if (IS_QLA82XX(ha))
3984 if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, 3984 qla82xx_chip_reset_cleanup(vha);
3985 WAIT_HOST) == QLA_SUCCESS) {
3986 DEBUG2(qla_printk(KERN_INFO, ha,
3987 "Done wait for pending commands\n"));
3988 }
3989 }
3990 3985
3991 /* Requeue all commands in outstanding command list. */ 3986 /* Requeue all commands in outstanding command list. */
3992 qla2x00_abort_all_cmds(vha, DID_RESET << 16); 3987 qla2x00_abort_all_cmds(vha, DID_RESET << 16);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index e473e9fb363c..a7f7346c783a 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -83,7 +83,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
83 return QLA_FUNCTION_TIMEOUT; 83 return QLA_FUNCTION_TIMEOUT;
84 } 84 }
85 85
86 if (IS_QLA82XX(ha) && ha->flags.fw_hung) { 86 if (ha->flags.isp82xx_fw_hung) {
87 /* Setting Link-Down error */ 87 /* Setting Link-Down error */
88 mcp->mb[0] = MBS_LINK_DOWN_ERROR; 88 mcp->mb[0] = MBS_LINK_DOWN_ERROR;
89 rval = QLA_FUNCTION_FAILED; 89 rval = QLA_FUNCTION_FAILED;
@@ -223,7 +223,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
223 ha->flags.mbox_int = 0; 223 ha->flags.mbox_int = 0;
224 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 224 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
225 225
226 if (IS_QLA82XX(ha) && ha->flags.fw_hung) { 226 if (ha->flags.isp82xx_fw_hung) {
227 ha->flags.mbox_busy = 0; 227 ha->flags.mbox_busy = 0;
228 /* Setting Link-Down error */ 228 /* Setting Link-Down error */
229 mcp->mb[0] = MBS_LINK_DOWN_ERROR; 229 mcp->mb[0] = MBS_LINK_DOWN_ERROR;
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
3460static void 3460int
3461qla82xx_check_fw_alive(scsi_qla_host_t *vha) 3461qla82xx_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
3599void qla82xx_watchdog(scsi_qla_host_t *vha) 3581void 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
3794void
3795qla82xx_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}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a37ac8b73e55..032d494da0db 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3793,7 +3793,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
3793 ha->flags.eeh_busy = 1; 3793 ha->flags.eeh_busy = 1;
3794 /* For ISP82XX complete any pending mailbox cmd */ 3794 /* For ISP82XX complete any pending mailbox cmd */
3795 if (IS_QLA82XX(ha)) { 3795 if (IS_QLA82XX(ha)) {
3796 ha->flags.fw_hung = 1; 3796 ha->flags.isp82xx_fw_hung = 1;
3797 if (ha->flags.mbox_busy) { 3797 if (ha->flags.mbox_busy) {
3798 ha->flags.mbox_int = 1; 3798 ha->flags.mbox_int = 1;
3799 DEBUG2(qla_printk(KERN_ERR, ha, 3799 DEBUG2(qla_printk(KERN_ERR, ha,
@@ -3933,7 +3933,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
3933 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 3933 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3934 QLA82XX_DEV_READY); 3934 QLA82XX_DEV_READY);
3935 qla82xx_idc_unlock(ha); 3935 qla82xx_idc_unlock(ha);
3936 ha->flags.fw_hung = 0; 3936 ha->flags.isp82xx_fw_hung = 0;
3937 rval = qla82xx_restart_isp(base_vha); 3937 rval = qla82xx_restart_isp(base_vha);
3938 qla82xx_idc_lock(ha); 3938 qla82xx_idc_lock(ha);
3939 /* Clear driver state register */ 3939 /* Clear driver state register */
@@ -3946,7 +3946,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
3946 "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn)); 3946 "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
3947 if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == 3947 if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
3948 QLA82XX_DEV_READY)) { 3948 QLA82XX_DEV_READY)) {
3949 ha->flags.fw_hung = 0; 3949 ha->flags.isp82xx_fw_hung = 0;
3950 rval = qla82xx_restart_isp(base_vha); 3950 rval = qla82xx_restart_isp(base_vha);
3951 qla82xx_idc_lock(ha); 3951 qla82xx_idc_lock(ha);
3952 qla82xx_set_drv_active(base_vha); 3952 qla82xx_set_drv_active(base_vha);