aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2009-03-24 12:08:05 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-04-03 10:22:47 -0400
commitb9978769877c6c90c8d6777df13b9ae427af40b7 (patch)
treefd894c6499004b80893ae68917ec5ba18126d586 /drivers/scsi/qla2xxx/qla_os.c
parente612d46591e2d4fbc35541377d18ab483c211768 (diff)
[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>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c49
1 files 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 @@ probe_init_failed:
1890 ha->max_queues = 0; 1890 ha->max_queues = 0;
1891 1891
1892probe_failed: 1892probe_failed:
1893 if (base_vha->timer_active)
1894 qla2x00_stop_timer(base_vha);
1895 base_vha->flags.online = 0;
1896 if (ha->dpc_thread) {
1897 struct task_struct *t = ha->dpc_thread;
1898
1899 ha->dpc_thread = NULL;
1900 kthread_stop(t);
1901 }
1902
1893 qla2x00_free_device(base_vha); 1903 qla2x00_free_device(base_vha);
1894 1904
1895 scsi_host_put(base_vha->host); 1905 scsi_host_put(base_vha->host);
@@ -1923,10 +1933,30 @@ qla2x00_remove_one(struct pci_dev *pdev)
1923 1933
1924 set_bit(UNLOADING, &base_vha->dpc_flags); 1934 set_bit(UNLOADING, &base_vha->dpc_flags);
1925 1935
1936 qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
1937
1926 qla2x00_dfs_remove(base_vha); 1938 qla2x00_dfs_remove(base_vha);
1927 1939
1928 qla84xx_put_chip(base_vha); 1940 qla84xx_put_chip(base_vha);
1929 1941
1942 /* Disable timer */
1943 if (base_vha->timer_active)
1944 qla2x00_stop_timer(base_vha);
1945
1946 base_vha->flags.online = 0;
1947
1948 /* Kill the kernel thread for this host */
1949 if (ha->dpc_thread) {
1950 struct task_struct *t = ha->dpc_thread;
1951
1952 /*
1953 * qla2xxx_wake_dpc checks for ->dpc_thread
1954 * so we need to zero it out.
1955 */
1956 ha->dpc_thread = NULL;
1957 kthread_stop(t);
1958 }
1959
1930 qla2x00_free_sysfs_attr(base_vha); 1960 qla2x00_free_sysfs_attr(base_vha);
1931 1961
1932 fc_remove_host(base_vha->host); 1962 fc_remove_host(base_vha->host);
@@ -1955,25 +1985,6 @@ static void
1955qla2x00_free_device(scsi_qla_host_t *vha) 1985qla2x00_free_device(scsi_qla_host_t *vha)
1956{ 1986{
1957 struct qla_hw_data *ha = vha->hw; 1987 struct qla_hw_data *ha = vha->hw;
1958 qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
1959
1960 /* Disable timer */
1961 if (vha->timer_active)
1962 qla2x00_stop_timer(vha);
1963
1964 vha->flags.online = 0;
1965
1966 /* Kill the kernel thread for this host */
1967 if (ha->dpc_thread) {
1968 struct task_struct *t = ha->dpc_thread;
1969
1970 /*
1971 * qla2xxx_wake_dpc checks for ->dpc_thread
1972 * so we need to zero it out.
1973 */
1974 ha->dpc_thread = NULL;
1975 kthread_stop(t);
1976 }
1977 1988
1978 if (ha->flags.fce_enabled) 1989 if (ha->flags.fce_enabled)
1979 qla2x00_disable_fce_trace(vha, NULL, NULL); 1990 qla2x00_disable_fce_trace(vha, NULL, NULL);