From b9978769877c6c90c8d6777df13b9ae427af40b7 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 24 Mar 2009 09:08:05 -0700 Subject: [PATCH] [SCSI] qla2xxx: Ensure the timer and DPC routines complete prior to midlayer tear-down. Since the routines can/will use resources such as devices and rports that aren't valid after midlayer tear-down, correct this potential race, by stopping the offending during the early stages of the remove() callback. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 49 +++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0d586a47c101..c7954612ef11 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1890,6 +1890,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->max_queues = 0; probe_failed: + if (base_vha->timer_active) + qla2x00_stop_timer(base_vha); + base_vha->flags.online = 0; + if (ha->dpc_thread) { + struct task_struct *t = ha->dpc_thread; + + ha->dpc_thread = NULL; + kthread_stop(t); + } + qla2x00_free_device(base_vha); scsi_host_put(base_vha->host); @@ -1923,10 +1933,30 @@ qla2x00_remove_one(struct pci_dev *pdev) set_bit(UNLOADING, &base_vha->dpc_flags); + qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); + qla2x00_dfs_remove(base_vha); qla84xx_put_chip(base_vha); + /* Disable timer */ + if (base_vha->timer_active) + qla2x00_stop_timer(base_vha); + + base_vha->flags.online = 0; + + /* Kill the kernel thread for this host */ + if (ha->dpc_thread) { + struct task_struct *t = ha->dpc_thread; + + /* + * qla2xxx_wake_dpc checks for ->dpc_thread + * so we need to zero it out. + */ + ha->dpc_thread = NULL; + kthread_stop(t); + } + qla2x00_free_sysfs_attr(base_vha); fc_remove_host(base_vha->host); @@ -1955,25 +1985,6 @@ static void qla2x00_free_device(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); - - /* Disable timer */ - if (vha->timer_active) - qla2x00_stop_timer(vha); - - vha->flags.online = 0; - - /* Kill the kernel thread for this host */ - if (ha->dpc_thread) { - struct task_struct *t = ha->dpc_thread; - - /* - * qla2xxx_wake_dpc checks for ->dpc_thread - * so we need to zero it out. - */ - ha->dpc_thread = NULL; - kthread_stop(t); - } if (ha->flags.fce_enabled) qla2x00_disable_fce_trace(vha, NULL, NULL);