浏览代码

[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>
Brian King 17 年之前
父节点
当前提交
2d0da2a44e
共有 1 个文件被更改,包括 7 次插入4 次删除
  1. 7 4
      drivers/scsi/ibmvscsi/ibmvfc.c

+ 7 - 4
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)
 static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
 {
 {
 	if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
 	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
 	} else
 		vhost->reinit = 1;
 		vhost->reinit = 1;
 
 
@@ -3811,10 +3812,12 @@ static int ibmvfc_remove(struct vio_dev *vdev)
 
 
 	ENTER;
 	ENTER;
 	ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr);
 	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);
 	kthread_stop(vhost->work_thread);
 	fc_remove_host(vhost->host);
 	fc_remove_host(vhost->host);
 	scsi_remove_host(vhost->host);
 	scsi_remove_host(vhost->host);
-	ibmvfc_release_crq_queue(vhost);
 
 
 	spin_lock_irqsave(vhost->host->host_lock, flags);
 	spin_lock_irqsave(vhost->host->host_lock, flags);
 	ibmvfc_purge_requests(vhost, DID_ERROR);
 	ibmvfc_purge_requests(vhost, DID_ERROR);