diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2008-08-13 21:37:01 -0700 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-08-16 10:24:12 -0500 |
commit | c795c1e4b68a74536f0fb18744d0e381ceb1f37e (patch) | |
tree | 5078b0f569d05c3a5a8108da139e83baf716854f /drivers/scsi/qla2xxx/qla_os.c | |
parent | 19851f136ab37d7ac6f7c865329d13db54712ec0 (diff) |
[SCSI] qla2xxx: Explicitly tear-down vports during PCI remove_one().
During internal testing, we've seen issues (hangs) with the
'deferred' vport tear-down-processing typically accompanied with
the fc_remove_host() call. This is due to the current
implementation's back-end vport handling being performed by the
physical-HA's DPC thread where premature shutdown could lead to
latent vport requests without a processor.
This should also address a problem reported by Gal Rosen
(http://marc.info/?l=linux-scsi&m=121731664417358&w=2) where the
driver would attempt to awaken a previously torn-down DPC thread
from interrupt context by implicitly calling wake_up_process()
rather than the driver's qla2xxx_wake_dpc() helper. Rather, than
reshuffle the remove_one() device-removal code, during unload,
depend on the driver's timer to wake-up the DPC process, by
limiting wake-ups based on an 'unloading' flag.
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 | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e0880ad243b..26afe44265c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1775,10 +1775,15 @@ probe_out: static void qla2x00_remove_one(struct pci_dev *pdev) { - scsi_qla_host_t *ha; + scsi_qla_host_t *ha, *vha, *temp; ha = pci_get_drvdata(pdev); + list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list) + fc_vport_terminate(vha->fc_vport); + + set_bit(UNLOADING, &ha->dpc_flags); + qla2x00_dfs_remove(ha); qla84xx_put_chip(ha); @@ -2450,8 +2455,10 @@ qla2x00_do_dpc(void *data) void qla2xxx_wake_dpc(scsi_qla_host_t *ha) { - if (ha->dpc_thread) - wake_up_process(ha->dpc_thread); + struct task_struct *t = ha->dpc_thread; + + if (!test_bit(UNLOADING, &ha->dpc_flags) && t) + wake_up_process(t); } /* |