diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2009-03-24 12:08:05 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-03 10:22:47 -0400 |
commit | b9978769877c6c90c8d6777df13b9ae427af40b7 (patch) | |
tree | fd894c6499004b80893ae68917ec5ba18126d586 /drivers/scsi/qla2xxx/qla_os.c | |
parent | e612d46591e2d4fbc35541377d18ab483c211768 (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.c | 49 |
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 | ||
1892 | probe_failed: | 1892 | probe_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 | |||
1955 | qla2x00_free_device(scsi_qla_host_t *vha) | 1985 | qla2x00_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); |