aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi/ibmvfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c122
1 files changed, 83 insertions, 39 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 182c8e75aaf0..76ae266b07c4 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -431,6 +431,8 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
431 case IBMVFC_TGT_ACTION_DEL_RPORT: 431 case IBMVFC_TGT_ACTION_DEL_RPORT:
432 break; 432 break;
433 default: 433 default:
434 if (action == IBMVFC_TGT_ACTION_DEL_RPORT)
435 tgt->add_rport = 0;
434 tgt->action = action; 436 tgt->action = action;
435 break; 437 break;
436 } 438 }
@@ -483,7 +485,7 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
483 switch (vhost->action) { 485 switch (vhost->action) {
484 case IBMVFC_HOST_ACTION_INIT_WAIT: 486 case IBMVFC_HOST_ACTION_INIT_WAIT:
485 case IBMVFC_HOST_ACTION_NONE: 487 case IBMVFC_HOST_ACTION_NONE:
486 case IBMVFC_HOST_ACTION_TGT_ADD: 488 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
487 vhost->action = action; 489 vhost->action = action;
488 break; 490 break;
489 default: 491 default:
@@ -498,7 +500,6 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
498 case IBMVFC_HOST_ACTION_TGT_DEL: 500 case IBMVFC_HOST_ACTION_TGT_DEL:
499 case IBMVFC_HOST_ACTION_QUERY_TGTS: 501 case IBMVFC_HOST_ACTION_QUERY_TGTS:
500 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: 502 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
501 case IBMVFC_HOST_ACTION_TGT_ADD:
502 case IBMVFC_HOST_ACTION_NONE: 503 case IBMVFC_HOST_ACTION_NONE:
503 default: 504 default:
504 vhost->action = action; 505 vhost->action = action;
@@ -2306,7 +2307,7 @@ static int ibmvfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
2306 done = 1; 2307 done = 1;
2307 } 2308 }
2308 2309
2309 if (vhost->state != IBMVFC_NO_CRQ && vhost->action == IBMVFC_HOST_ACTION_NONE) 2310 if (vhost->scan_complete)
2310 done = 1; 2311 done = 1;
2311 spin_unlock_irqrestore(shost->host_lock, flags); 2312 spin_unlock_irqrestore(shost->host_lock, flags);
2312 return done; 2313 return done;
@@ -2820,7 +2821,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
2820 tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; 2821 tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
2821 if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) 2822 if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
2822 tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; 2823 tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
2823 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); 2824 tgt->add_rport = 1;
2824 } else 2825 } else
2825 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 2826 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2826 } else if (prli_rsp[index].retry) 2827 } else if (prli_rsp[index].retry)
@@ -3660,7 +3661,6 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost)
3660 return 1; 3661 return 1;
3661 case IBMVFC_HOST_ACTION_INIT: 3662 case IBMVFC_HOST_ACTION_INIT:
3662 case IBMVFC_HOST_ACTION_ALLOC_TGTS: 3663 case IBMVFC_HOST_ACTION_ALLOC_TGTS:
3663 case IBMVFC_HOST_ACTION_TGT_ADD:
3664 case IBMVFC_HOST_ACTION_TGT_DEL: 3664 case IBMVFC_HOST_ACTION_TGT_DEL:
3665 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: 3665 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
3666 case IBMVFC_HOST_ACTION_QUERY: 3666 case IBMVFC_HOST_ACTION_QUERY:
@@ -3715,25 +3715,26 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
3715static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) 3715static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
3716{ 3716{
3717 struct ibmvfc_host *vhost = tgt->vhost; 3717 struct ibmvfc_host *vhost = tgt->vhost;
3718 struct fc_rport *rport = tgt->rport; 3718 struct fc_rport *rport;
3719 unsigned long flags; 3719 unsigned long flags;
3720 3720
3721 if (rport) { 3721 tgt_dbg(tgt, "Adding rport\n");
3722 tgt_dbg(tgt, "Setting rport roles\n"); 3722 rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
3723 fc_remote_port_rolechg(rport, tgt->ids.roles); 3723 spin_lock_irqsave(vhost->host->host_lock, flags);
3724 spin_lock_irqsave(vhost->host->host_lock, flags); 3724
3725 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); 3725 if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
3726 tgt_dbg(tgt, "Deleting rport\n");
3727 list_del(&tgt->queue);
3726 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3728 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3729 fc_remote_port_delete(rport);
3730 del_timer_sync(&tgt->timer);
3731 kref_put(&tgt->kref, ibmvfc_release_tgt);
3727 return; 3732 return;
3728 } 3733 }
3729 3734
3730 tgt_dbg(tgt, "Adding rport\n");
3731 rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
3732 spin_lock_irqsave(vhost->host->host_lock, flags);
3733 tgt->rport = rport;
3734 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
3735 if (rport) { 3735 if (rport) {
3736 tgt_dbg(tgt, "rport add succeeded\n"); 3736 tgt_dbg(tgt, "rport add succeeded\n");
3737 tgt->rport = rport;
3737 rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff; 3738 rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
3738 rport->supported_classes = 0; 3739 rport->supported_classes = 0;
3739 tgt->target_id = rport->scsi_target_id; 3740 tgt->target_id = rport->scsi_target_id;
@@ -3811,11 +3812,21 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3811 3812
3812 if (vhost->state == IBMVFC_INITIALIZING) { 3813 if (vhost->state == IBMVFC_INITIALIZING) {
3813 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) { 3814 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) {
3814 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE); 3815 if (vhost->reinit) {
3815 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_ADD); 3816 vhost->reinit = 0;
3816 vhost->init_retries = 0; 3817 scsi_block_requests(vhost->host);
3817 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3818 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
3818 scsi_unblock_requests(vhost->host); 3819 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3820 } else {
3821 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE);
3822 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
3823 wake_up(&vhost->init_wait_q);
3824 schedule_work(&vhost->rport_add_work_q);
3825 vhost->init_retries = 0;
3826 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3827 scsi_unblock_requests(vhost->host);
3828 }
3829
3819 return; 3830 return;
3820 } else { 3831 } else {
3821 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 3832 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
@@ -3846,24 +3857,6 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3846 if (!ibmvfc_dev_init_to_do(vhost)) 3857 if (!ibmvfc_dev_init_to_do(vhost))
3847 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL_FAILED); 3858 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL_FAILED);
3848 break; 3859 break;
3849 case IBMVFC_HOST_ACTION_TGT_ADD:
3850 list_for_each_entry(tgt, &vhost->targets, queue) {
3851 if (tgt->action == IBMVFC_TGT_ACTION_ADD_RPORT) {
3852 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3853 ibmvfc_tgt_add_rport(tgt);
3854 return;
3855 }
3856 }
3857
3858 if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
3859 vhost->reinit = 0;
3860 scsi_block_requests(vhost->host);
3861 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
3862 } else {
3863 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
3864 wake_up(&vhost->init_wait_q);
3865 }
3866 break;
3867 default: 3860 default:
3868 break; 3861 break;
3869 }; 3862 };
@@ -4093,6 +4086,56 @@ nomem:
4093} 4086}
4094 4087
4095/** 4088/**
4089 * ibmvfc_rport_add_thread - Worker thread for rport adds
4090 * @work: work struct
4091 *
4092 **/
4093static void ibmvfc_rport_add_thread(struct work_struct *work)
4094{
4095 struct ibmvfc_host *vhost = container_of(work, struct ibmvfc_host,
4096 rport_add_work_q);
4097 struct ibmvfc_target *tgt;
4098 struct fc_rport *rport;
4099 unsigned long flags;
4100 int did_work;
4101
4102 ENTER;
4103 spin_lock_irqsave(vhost->host->host_lock, flags);
4104 do {
4105 did_work = 0;
4106 if (vhost->state != IBMVFC_ACTIVE)
4107 break;
4108
4109 list_for_each_entry(tgt, &vhost->targets, queue) {
4110 if (tgt->add_rport) {
4111 did_work = 1;
4112 tgt->add_rport = 0;
4113 kref_get(&tgt->kref);
4114 rport = tgt->rport;
4115 if (!rport) {
4116 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4117 ibmvfc_tgt_add_rport(tgt);
4118 } else if (get_device(&rport->dev)) {
4119 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4120 tgt_dbg(tgt, "Setting rport roles\n");
4121 fc_remote_port_rolechg(rport, tgt->ids.roles);
4122 put_device(&rport->dev);
4123 }
4124
4125 kref_put(&tgt->kref, ibmvfc_release_tgt);
4126 spin_lock_irqsave(vhost->host->host_lock, flags);
4127 break;
4128 }
4129 }
4130 } while(did_work);
4131
4132 if (vhost->state == IBMVFC_ACTIVE)
4133 vhost->scan_complete = 1;
4134 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4135 LEAVE;
4136}
4137
4138/**
4096 * ibmvfc_probe - Adapter hot plug add entry point 4139 * ibmvfc_probe - Adapter hot plug add entry point
4097 * @vdev: vio device struct 4140 * @vdev: vio device struct
4098 * @id: vio device id struct 4141 * @id: vio device id struct
@@ -4135,6 +4178,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
4135 strcpy(vhost->partition_name, "UNKNOWN"); 4178 strcpy(vhost->partition_name, "UNKNOWN");
4136 init_waitqueue_head(&vhost->work_wait_q); 4179 init_waitqueue_head(&vhost->work_wait_q);
4137 init_waitqueue_head(&vhost->init_wait_q); 4180 init_waitqueue_head(&vhost->init_wait_q);
4181 INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread);
4138 4182
4139 if ((rc = ibmvfc_alloc_mem(vhost))) 4183 if ((rc = ibmvfc_alloc_mem(vhost)))
4140 goto free_scsi_host; 4184 goto free_scsi_host;