aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2010-07-08 03:53:07 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:46:38 -0400
commit5a7de559b4e0169ff4cfca654b4e4f0014996e57 (patch)
tree46e13cf400f672eb7d26e6ffdb4c990256e18c76 /drivers/s390
parent097ef3bd0cd4f156fee039e52855d095b7ba3db4 (diff)
[SCSI] zfcp: Register SCSI devices after successful fc_remote_port_add
When the successful return of an adisc is the final step to set the port online, the registration of SCSI devices might be omitted. SCSI devices that have been removed before (due to a short dev_loss_tmo setting) might not be attached again. The problem is that the registration of SCSI devices is done only after erp has finished. The correct place would be after the call to fc_remote_port_add to mimick the scan in the FC transport class. Change the registration of SCSI devices to be triggered after the fc_remote_port_add call. For the initial inquiry command to succeed, the unit must also be open. If the unit reopen is still pending, the inquiry command to the LUN will be deferred with DID_IMM_RETRY, so there is no harm from this approach. Reviewed-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c6
-rw-r--r--drivers/s390/scsi/zfcp_ext.h3
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c37
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c2
5 files changed, 33 insertions, 17 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index e331df2122f7..6e9c7f33e276 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -314,7 +314,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
314 } 314 }
315 retval = -EINVAL; 315 retval = -EINVAL;
316 316
317 INIT_WORK(&unit->scsi_work, zfcp_scsi_scan); 317 INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
318 318
319 spin_lock_init(&unit->latencies.lock); 319 spin_lock_init(&unit->latencies.lock);
320 unit->latencies.write.channel.min = 0xFFFFFFFF; 320 unit->latencies.write.channel.min = 0xFFFFFFFF;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 5a71b73211df..03cd6365ed04 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1192,12 +1192,6 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1192 1192
1193 switch (act->action) { 1193 switch (act->action) {
1194 case ZFCP_ERP_ACTION_REOPEN_UNIT: 1194 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1195 if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
1196 get_device(&unit->dev);
1197 if (scsi_queue_work(unit->port->adapter->scsi_host,
1198 &unit->scsi_work) <= 0)
1199 put_device(&unit->dev);
1200 }
1201 put_device(&unit->dev); 1195 put_device(&unit->dev);
1202 break; 1196 break;
1203 1197
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 48a8f93b72f5..6abe2909e75b 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -159,7 +159,8 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
159extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); 159extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
160extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); 160extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
161extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); 161extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
162extern void zfcp_scsi_scan(struct work_struct *); 162extern void zfcp_scsi_scan(struct zfcp_unit *);
163extern void zfcp_scsi_scan_work(struct work_struct *);
163 164
164/* zfcp_sysfs.c */ 165/* zfcp_sysfs.c */
165extern struct attribute_group zfcp_sysfs_unit_attrs; 166extern struct attribute_group zfcp_sysfs_unit_attrs;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index be5d2c60453d..153f69b26e78 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -524,6 +524,20 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
524 } 524 }
525} 525}
526 526
527static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
528{
529 struct zfcp_unit *unit;
530
531 read_lock_irq(&port->unit_list_lock);
532 list_for_each_entry(unit, &port->unit_list, list) {
533 get_device(&unit->dev);
534 if (scsi_queue_work(port->adapter->scsi_host,
535 &unit->scsi_work) <= 0)
536 put_device(&unit->dev);
537 }
538 read_unlock_irq(&port->unit_list_lock);
539}
540
527static void zfcp_scsi_rport_register(struct zfcp_port *port) 541static void zfcp_scsi_rport_register(struct zfcp_port *port)
528{ 542{
529 struct fc_rport_identifiers ids; 543 struct fc_rport_identifiers ids;
@@ -548,6 +562,8 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
548 rport->maxframe_size = port->maxframe_size; 562 rport->maxframe_size = port->maxframe_size;
549 rport->supported_classes = port->supported_classes; 563 rport->supported_classes = port->supported_classes;
550 port->rport = rport; 564 port->rport = rport;
565
566 zfcp_scsi_queue_unit_register(port);
551} 567}
552 568
553static void zfcp_scsi_rport_block(struct zfcp_port *port) 569static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -610,21 +626,26 @@ void zfcp_scsi_rport_work(struct work_struct *work)
610 put_device(&port->dev); 626 put_device(&port->dev);
611} 627}
612 628
613 629/**
614void zfcp_scsi_scan(struct work_struct *work) 630 * zfcp_scsi_scan - Register LUN with SCSI midlayer
631 * @unit: The LUN/unit to register
632 */
633void zfcp_scsi_scan(struct zfcp_unit *unit)
615{ 634{
616 struct zfcp_unit *unit = container_of(work, struct zfcp_unit, 635 struct fc_rport *rport = unit->port->rport;
617 scsi_work);
618 struct fc_rport *rport;
619
620 flush_work(&unit->port->rport_work);
621 rport = unit->port->rport;
622 636
623 if (rport && rport->port_state == FC_PORTSTATE_ONLINE) 637 if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
624 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, 638 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
625 scsilun_to_int((struct scsi_lun *) 639 scsilun_to_int((struct scsi_lun *)
626 &unit->fcp_lun), 0); 640 &unit->fcp_lun), 0);
641}
642
643void zfcp_scsi_scan_work(struct work_struct *work)
644{
645 struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
646 scsi_work);
627 647
648 zfcp_scsi_scan(unit);
628 put_device(&unit->dev); 649 put_device(&unit->dev);
629} 650}
630 651
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index f5f60698dc4c..205b9f8056e2 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -275,7 +275,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
275 275
276 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); 276 zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
277 zfcp_erp_wait(unit->port->adapter); 277 zfcp_erp_wait(unit->port->adapter);
278 flush_work(&unit->scsi_work); 278 zfcp_scsi_scan(unit);
279out: 279out:
280 put_device(&port->dev); 280 put_device(&port->dev);
281 return retval ? retval : (ssize_t) count; 281 return retval ? retval : (ssize_t) count;