Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Andrew Vasquez and committed by
James Bottomley
c795c1e4 19851f13

+12 -4
+1
drivers/scsi/qla2xxx/qla_def.h
··· 2237 2237 #define REGISTER_FDMI_NEEDED 26 2238 2238 #define FCPORT_UPDATE_NEEDED 27 2239 2239 #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ 2240 + #define UNLOADING 29 2240 2241 2241 2242 uint32_t device_flags; 2242 2243 #define DFLG_LOCAL_DEVICES BIT_0
+1 -1
drivers/scsi/qla2xxx/qla_mbx.c
··· 2686 2686 set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); 2687 2687 set_bit(VP_DPC_NEEDED, &ha->dpc_flags); 2688 2688 2689 - wake_up_process(ha->dpc_thread); 2689 + qla2xxx_wake_dpc(ha); 2690 2690 } 2691 2691 } 2692 2692
+10 -3
drivers/scsi/qla2xxx/qla_os.c
··· 1775 1775 static void 1776 1776 qla2x00_remove_one(struct pci_dev *pdev) 1777 1777 { 1778 - scsi_qla_host_t *ha; 1778 + scsi_qla_host_t *ha, *vha, *temp; 1779 1779 1780 1780 ha = pci_get_drvdata(pdev); 1781 + 1782 + list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list) 1783 + fc_vport_terminate(vha->fc_vport); 1784 + 1785 + set_bit(UNLOADING, &ha->dpc_flags); 1781 1786 1782 1787 qla2x00_dfs_remove(ha); 1783 1788 ··· 2455 2450 void 2456 2451 qla2xxx_wake_dpc(scsi_qla_host_t *ha) 2457 2452 { 2458 - if (ha->dpc_thread) 2459 - wake_up_process(ha->dpc_thread); 2453 + struct task_struct *t = ha->dpc_thread; 2454 + 2455 + if (!test_bit(UNLOADING, &ha->dpc_flags) && t) 2456 + wake_up_process(t); 2460 2457 } 2461 2458 2462 2459 /*