diff options
author | Arun Easi <arun.easi@qlogic.com> | 2011-05-10 14:18:16 -0400 |
---|---|---|
committer | James Bottomley <jbottomley@parallels.com> | 2011-05-17 03:29:10 -0400 |
commit | 43ebf16d762b082663976b679b813e1b546548d1 (patch) | |
tree | 322a7baa171c3c15782d13705ed0347a18553c62 /drivers/scsi | |
parent | fa96d927362a422405d65491326f8ef763572e84 (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')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7168e7f24437..010f560ab99d 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 | ||