aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-03-04 14:26:53 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-03-05 13:03:17 -0500
commit50a29aec9c47d26e869df83ef1d69e3b63c83bf4 (patch)
treef7f035b965da8850078f48a039a10d2ed541d1b2
parent21f1e91d4bb8fa7cd3a59938471fc7c7d27f82da (diff)
[SCSI] qla4xxx: fix host reset dpc race
The host reset callout could be starting to reset the hba at the same time the dpc thread is. This creates lots of problems because they both want to do wierd things with the firmware and interrupts, etc. This patch just has the host reset function fully shutdown the dpc thread before resetting the hba. This patch also moves the setting of the session online bit to fix a potential race with the dpc thread and iscsi recovery thread. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Acked-by: David C Somayajulu <david.somayajulu@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c13
2 files changed, 10 insertions, 5 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 10b3b9a620f3..109c5f5985ec 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1299,9 +1299,9 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
1299 ddb_entry->fw_ddb_device_state = state; 1299 ddb_entry->fw_ddb_device_state = state;
1300 /* Device is back online. */ 1300 /* Device is back online. */
1301 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { 1301 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
1302 atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
1302 atomic_set(&ddb_entry->port_down_timer, 1303 atomic_set(&ddb_entry->port_down_timer,
1303 ha->port_down_retry_count); 1304 ha->port_down_retry_count);
1304 atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
1305 atomic_set(&ddb_entry->relogin_retry_count, 0); 1305 atomic_set(&ddb_entry->relogin_retry_count, 0);
1306 atomic_set(&ddb_entry->relogin_timer, 0); 1306 atomic_set(&ddb_entry->relogin_timer, 0);
1307 clear_bit(DF_RELOGIN, &ddb_entry->flags); 1307 clear_bit(DF_RELOGIN, &ddb_entry->flags);
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index c3c59d763037..10a233e65bc9 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -864,8 +864,9 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
864 * qla4xxx_recover_adapter - recovers adapter after a fatal error 864 * qla4xxx_recover_adapter - recovers adapter after a fatal error
865 * @ha: Pointer to host adapter structure. 865 * @ha: Pointer to host adapter structure.
866 * @renew_ddb_list: Indicates what to do with the adapter's ddb list 866 * @renew_ddb_list: Indicates what to do with the adapter's ddb list
867 * after adapter recovery has completed. 867 *
868 * 0=preserve ddb list, 1=destroy and rebuild ddb list 868 * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild
869 * ddb list.
869 **/ 870 **/
870static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, 871static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
871 uint8_t renew_ddb_list) 872 uint8_t renew_ddb_list)
@@ -874,6 +875,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
874 875
875 /* Stall incoming I/O until we are done */ 876 /* Stall incoming I/O until we are done */
876 clear_bit(AF_ONLINE, &ha->flags); 877 clear_bit(AF_ONLINE, &ha->flags);
878
877 DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, 879 DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no,
878 __func__)); 880 __func__));
879 881
@@ -1600,9 +1602,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
1600 return FAILED; 1602 return FAILED;
1601 } 1603 }
1602 1604
1603 if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) { 1605 /* make sure the dpc thread is stopped while we reset the hba */
1606 clear_bit(AF_ONLINE, &ha->flags);
1607 flush_workqueue(ha->dpc_thread);
1608
1609 if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS)
1604 return_status = SUCCESS; 1610 return_status = SUCCESS;
1605 }
1606 1611
1607 dev_info(&ha->pdev->dev, "HOST RESET %s.\n", 1612 dev_info(&ha->pdev->dev, "HOST RESET %s.\n",
1608 return_status == FAILED ? "FAILED" : "SUCCEDED"); 1613 return_status == FAILED ? "FAILED" : "SUCCEDED");