diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2008-07-22 09:31:42 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-26 15:14:57 -0400 |
commit | 2d0da2a44e065a5bdd90bed2ebe0b9216c27f682 (patch) | |
tree | 6658ff20477018a5dc749d0637ee1fea6d37ccc2 /drivers | |
parent | b3c10489cb464b12a74dda65f826433f71f2c2e2 (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')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 11 |
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, | |||
521 | static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) | 521 | static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) |
522 | { | 522 | { |
523 | if (vhost->action == IBMVFC_HOST_ACTION_NONE) { | 523 | if (vhost->action == IBMVFC_HOST_ACTION_NONE) { |
524 | scsi_block_requests(vhost->host); | 524 | if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { |
525 | ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING); | 525 | scsi_block_requests(vhost->host); |
526 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); | 526 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); |
527 | } | ||
527 | } else | 528 | } else |
528 | vhost->reinit = 1; | 529 | vhost->reinit = 1; |
529 | 530 | ||
@@ -3811,10 +3812,12 @@ static int ibmvfc_remove(struct vio_dev *vdev) | |||
3811 | 3812 | ||
3812 | ENTER; | 3813 | ENTER; |
3813 | ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr); | 3814 | ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr); |
3815 | ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); | ||
3816 | ibmvfc_wait_while_resetting(vhost); | ||
3817 | ibmvfc_release_crq_queue(vhost); | ||
3814 | kthread_stop(vhost->work_thread); | 3818 | kthread_stop(vhost->work_thread); |
3815 | fc_remove_host(vhost->host); | 3819 | fc_remove_host(vhost->host); |
3816 | scsi_remove_host(vhost->host); | 3820 | scsi_remove_host(vhost->host); |
3817 | ibmvfc_release_crq_queue(vhost); | ||
3818 | 3821 | ||
3819 | spin_lock_irqsave(vhost->host->host_lock, flags); | 3822 | spin_lock_irqsave(vhost->host->host_lock, flags); |
3820 | ibmvfc_purge_requests(vhost, DID_ERROR); | 3823 | ibmvfc_purge_requests(vhost, DID_ERROR); |