aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c119
1 files changed, 116 insertions, 3 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 2af8cfbc3890..7141f9a675df 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Interface to Linux SCSI midlayer. 4 * Interface to Linux SCSI midlayer.
5 * 5 *
6 * Copyright IBM Corporation 2002, 2008 6 * Copyright IBM Corporation 2002, 2009
7 */ 7 */
8 8
9#define KMSG_COMPONENT "zfcp" 9#define KMSG_COMPONENT "zfcp"
@@ -57,8 +57,8 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
57{ 57{
58 struct zfcp_unit *unit; 58 struct zfcp_unit *unit;
59 struct zfcp_adapter *adapter; 59 struct zfcp_adapter *adapter;
60 int status; 60 int status, scsi_result, ret;
61 int ret; 61 struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
62 62
63 /* reset the status for this request */ 63 /* reset the status for this request */
64 scpnt->result = 0; 64 scpnt->result = 0;
@@ -80,6 +80,14 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
80 return 0; 80 return 0;
81 } 81 }
82 82
83 scsi_result = fc_remote_port_chkready(rport);
84 if (unlikely(scsi_result)) {
85 scpnt->result = scsi_result;
86 zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
87 scpnt->scsi_done(scpnt);
88 return 0;
89 }
90
83 status = atomic_read(&unit->status); 91 status = atomic_read(&unit->status);
84 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) || 92 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
85 !(status & ZFCP_STATUS_COMMON_RUNNING))) { 93 !(status & ZFCP_STATUS_COMMON_RUNNING))) {
@@ -473,6 +481,109 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
473 rport->dev_loss_tmo = timeout; 481 rport->dev_loss_tmo = timeout;
474} 482}
475 483
484/**
485 * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
486 * @rport: The rport that is about to be deleted.
487 */
488static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
489{
490 struct zfcp_port *port = rport->dd_data;
491
492 write_lock_irq(&zfcp_data.config_lock);
493 port->rport = NULL;
494 write_unlock_irq(&zfcp_data.config_lock);
495}
496
497/**
498 * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
499 * @rport: The FC rport where to teminate I/O
500 *
501 * Abort all pending SCSI commands for a port by closing the
502 * port. Using a reopen for avoids a conflict with a shutdown
503 * overwriting a reopen.
504 */
505static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
506{
507 struct zfcp_port *port = rport->dd_data;
508
509 zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
510}
511
512static void zfcp_scsi_rport_register(struct zfcp_port *port)
513{
514 struct fc_rport_identifiers ids;
515 struct fc_rport *rport;
516
517 ids.node_name = port->wwnn;
518 ids.port_name = port->wwpn;
519 ids.port_id = port->d_id;
520 ids.roles = FC_RPORT_ROLE_FCP_TARGET;
521
522 rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
523 if (!rport) {
524 dev_err(&port->adapter->ccw_device->dev,
525 "Registering port 0x%016Lx failed\n",
526 (unsigned long long)port->wwpn);
527 return;
528 }
529
530 rport->dd_data = port;
531 rport->maxframe_size = port->maxframe_size;
532 rport->supported_classes = port->supported_classes;
533 port->rport = rport;
534}
535
536static void zfcp_scsi_rport_block(struct zfcp_port *port)
537{
538 if (port->rport)
539 fc_remote_port_delete(port->rport);
540}
541
542void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
543{
544 zfcp_port_get(port);
545 port->rport_task = RPORT_ADD;
546
547 if (!queue_work(zfcp_data.work_queue, &port->rport_work))
548 zfcp_port_put(port);
549}
550
551void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
552{
553 zfcp_port_get(port);
554 port->rport_task = RPORT_DEL;
555
556 if (!queue_work(zfcp_data.work_queue, &port->rport_work))
557 zfcp_port_put(port);
558}
559
560void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
561{
562 struct zfcp_port *port;
563
564 list_for_each_entry(port, &adapter->port_list_head, list)
565 zfcp_scsi_schedule_rport_block(port);
566}
567
568void zfcp_scsi_rport_work(struct work_struct *work)
569{
570 struct zfcp_port *port = container_of(work, struct zfcp_port,
571 rport_work);
572
573 while (port->rport_task) {
574 if (port->rport_task == RPORT_ADD) {
575 port->rport_task = RPORT_NONE;
576 zfcp_scsi_rport_register(port);
577 } else {
578 port->rport_task = RPORT_NONE;
579 zfcp_scsi_rport_block(port);
580 }
581 }
582
583 zfcp_port_put(port);
584}
585
586
476struct fc_function_template zfcp_transport_functions = { 587struct fc_function_template zfcp_transport_functions = {
477 .show_starget_port_id = 1, 588 .show_starget_port_id = 1,
478 .show_starget_port_name = 1, 589 .show_starget_port_name = 1,
@@ -491,6 +602,8 @@ struct fc_function_template zfcp_transport_functions = {
491 .reset_fc_host_stats = zfcp_reset_fc_host_stats, 602 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
492 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, 603 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
493 .get_host_port_state = zfcp_get_host_port_state, 604 .get_host_port_state = zfcp_get_host_port_state,
605 .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
606 .terminate_rport_io = zfcp_scsi_terminate_rport_io,
494 .show_host_port_state = 1, 607 .show_host_port_state = 1,
495 /* no functions registered for following dynamic attributes but 608 /* no functions registered for following dynamic attributes but
496 directly set by LLDD */ 609 directly set by LLDD */