aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorLalit Chandivade <lalit.chandivade@qlogic.com>2010-05-04 18:01:32 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-16 18:22:07 -0400
commit86fbee86e94c7e80c9bb01db0cf68b7977462109 (patch)
tree5986a38b823136858ac93466f0af35d22037bf40 /drivers/scsi
parent1516ef44835417f55645cdd9ccf203551ca6e8c0 (diff)
[SCSI] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive
The problem occurring is a hw-race where there's an outstanding read-flash operation occurring while the chip is being reset (done via an sg_reset script). After the chip is paused, the read-flash operation never completes and the DPC thread, while trying to complete the reset, is never able to recover, as the HW appears to be hung... The fix is to wait for outstanding flash operation prior to doing a sg_reset -h. And to wait for reset to complete before any flash operations. Note, during the wait, if any of the operation (reset/flash) does not complete, failure is returned to the upper layer. The upper layer either need to fail or retry. Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c46
2 files changed, 51 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 62a22cfae20e..3b708606b932 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -281,6 +281,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
281 return count; 281 return count;
282 } 282 }
283 283
284 if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
285 qla_printk(KERN_WARNING, ha,
286 "HBA not online, failing NVRAM update.\n");
287 return -EAGAIN;
288 }
289
284 DEBUG2(qla_printk(KERN_INFO, ha, 290 DEBUG2(qla_printk(KERN_INFO, ha,
285 "Reading flash region -- 0x%x/0x%x.\n", 291 "Reading flash region -- 0x%x/0x%x.\n",
286 ha->optrom_region_start, ha->optrom_region_size)); 292 ha->optrom_region_start, ha->optrom_region_size));
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 5104aefdc7e6..0de92d376677 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -676,6 +676,50 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
676 return (return_status); 676 return (return_status);
677} 677}
678 678
679/*
680 * qla2x00_wait_for_reset_ready
681 * Wait till the HBA is online after going through
682 * <= MAX_RETRIES_OF_ISP_ABORT or
683 * finally HBA is disabled ie marked offline or flash
684 * operations are in progress.
685 *
686 * Input:
687 * ha - pointer to host adapter structure
688 *
689 * Note:
690 * Does context switching-Release SPIN_LOCK
691 * (if any) before calling this routine.
692 *
693 * Return:
694 * Success (Adapter is online/no flash ops) : 0
695 * Failed (Adapter is offline/disabled/flash ops in progress) : 1
696 */
697int
698qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
699{
700 int return_status;
701 unsigned long wait_online;
702 struct qla_hw_data *ha = vha->hw;
703 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
704
705 wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
706 while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
707 test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
708 test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
709 ha->optrom_state != QLA_SWAITING ||
710 ha->dpc_active) && time_before(jiffies, wait_online))
711 msleep(1000);
712
713 if (base_vha->flags.online && ha->optrom_state == QLA_SWAITING)
714 return_status = QLA_SUCCESS;
715 else
716 return_status = QLA_FUNCTION_FAILED;
717
718 DEBUG2(printk("%s return_status=%d\n", __func__, return_status));
719
720 return return_status;
721}
722
679int 723int
680qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) 724qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
681{ 725{
@@ -1081,7 +1125,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
1081 qla_printk(KERN_INFO, ha, 1125 qla_printk(KERN_INFO, ha,
1082 "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun); 1126 "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
1083 1127
1084 if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) 1128 if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
1085 goto eh_host_reset_lock; 1129 goto eh_host_reset_lock;
1086 1130
1087 /* 1131 /*