summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2008-07-22 08:31:42 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-26 15:14:57 -0400
commit2d0da2a44e065a5bdd90bed2ebe0b9216c27f682 (patch)
tree6658ff20477018a5dc749d0637ee1fea6d37ccc2 /drivers/scsi
parentb3c10489cb464b12a74dda65f826433f71f2c2e2 (diff)
[SCSI] ibmvfc: Fix hang on module removal
If certain ELS events are received during module removal, after the kthread is stopped, the rmmod can hang. This fixes the ibmvfc driver so that ELS events during rmmod are ignored by stopping all device activity prior to killing the kthread and also changes reinitialization to not attempt a reinit if the adapter has been taken offline. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 1781cec97fba..f1e5fac1c1dd 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -521,9 +521,10 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
{
if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
- scsi_block_requests(vhost->host);
- ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING);
- ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+ if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
+ scsi_block_requests(vhost->host);
+ ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+ }
} else
vhost->reinit = 1;
@@ -3811,10 +3812,12 @@ static int ibmvfc_remove(struct vio_dev *vdev)
ENTER;
ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr);
+ ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
+ ibmvfc_wait_while_resetting(vhost);
+ ibmvfc_release_crq_queue(vhost);
kthread_stop(vhost->work_thread);
fc_remove_host(vhost->host);
scsi_remove_host(vhost->host);
- ibmvfc_release_crq_queue(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);