[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 <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0d586a4..c795461 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1890,6 +1890,16 @@
 	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 @@
 
 	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 @@
 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);