]> err.no Git - linux-2.6/commitdiff
[SCSI] ibmvfc: Fix hang on module removal
authorBrian King <brking@linux.vnet.ibm.com>
Tue, 22 Jul 2008 13:31:42 +0000 (08:31 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Sat, 26 Jul 2008 19:14:57 +0000 (15:14 -0400)
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>
drivers/scsi/ibmvscsi/ibmvfc.c

index 1781cec97fba5121a679dbc4513b9819e6c791aa..f1e5fac1c1dd8bedd44e3d4bfd01479d7c158a5b 100644 (file)
@@ -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) {
 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;
 
        } 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);
 
        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);
        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);
 
        spin_lock_irqsave(vhost->host->host_lock, flags);
        ibmvfc_purge_requests(vhost, DID_ERROR);