aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorArun Easi <arun.easi@qlogic.com>2011-05-10 14:18:16 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-17 03:29:10 -0400
commit43ebf16d762b082663976b679b813e1b546548d1 (patch)
tree322a7baa171c3c15782d13705ed0347a18553c62 /drivers/scsi/qla2xxx/qla_os.c
parentfa96d927362a422405d65491326f8ef763572e84 (diff)
[SCSI] qla2xxx: Fix hang during driver unload when vport is active.
Bumping ref count during fc_vport_terminate() was the cause. vport delete would wait for ref count to drop to zero and that would never happen. Cc: stable@kernel.org Signed-off-by: Arun Easi <arun.easi@qlogic.com> Signed-off-by: Madhuranath Iyengar <Madhu.Iyengar@qlogic.com> Signed-off-by: James Bottomley <jbottomley@parallels.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7168e7f2443..010f560ab99 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2368,21 +2368,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
2368 base_vha = pci_get_drvdata(pdev); 2368 base_vha = pci_get_drvdata(pdev);
2369 ha = base_vha->hw; 2369 ha = base_vha->hw;
2370 2370
2371 spin_lock_irqsave(&ha->vport_slock, flags); 2371 mutex_lock(&ha->vport_lock);
2372 list_for_each_entry(vha, &ha->vp_list, list) { 2372 while (ha->cur_vport_count) {
2373 atomic_inc(&vha->vref_count); 2373 struct Scsi_Host *scsi_host;
2374 2374
2375 if (vha->fc_vport) { 2375 spin_lock_irqsave(&ha->vport_slock, flags);
2376 spin_unlock_irqrestore(&ha->vport_slock, flags);
2377 2376
2378 fc_vport_terminate(vha->fc_vport); 2377 BUG_ON(base_vha->list.next == &ha->vp_list);
2378 /* This assumes first entry in ha->vp_list is always base vha */
2379 vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
2380 scsi_host = scsi_host_get(vha->host);
2379 2381
2380 spin_lock_irqsave(&ha->vport_slock, flags); 2382 spin_unlock_irqrestore(&ha->vport_slock, flags);
2381 } 2383 mutex_unlock(&ha->vport_lock);
2384
2385 fc_vport_terminate(vha->fc_vport);
2386 scsi_host_put(vha->host);
2382 2387
2383 atomic_dec(&vha->vref_count); 2388 mutex_lock(&ha->vport_lock);
2384 } 2389 }
2385 spin_unlock_irqrestore(&ha->vport_slock, flags); 2390 mutex_unlock(&ha->vport_lock);
2386 2391
2387 set_bit(UNLOADING, &base_vha->dpc_flags); 2392 set_bit(UNLOADING, &base_vha->dpc_flags);
2388 2393