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.c69
1 files changed, 22 insertions, 47 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b9daf5c05862..f81850624eed 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -31,6 +31,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *,
31 void (*done) (struct scsi_cmnd *)); 31 void (*done) (struct scsi_cmnd *));
32static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); 32static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
33static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); 33static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
34static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *);
34static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); 35static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
35static int zfcp_task_management_function(struct zfcp_unit *, u8, 36static int zfcp_task_management_function(struct zfcp_unit *, u8,
36 struct scsi_cmnd *); 37 struct scsi_cmnd *);
@@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = {
51 .queuecommand = zfcp_scsi_queuecommand, 52 .queuecommand = zfcp_scsi_queuecommand,
52 .eh_abort_handler = zfcp_scsi_eh_abort_handler, 53 .eh_abort_handler = zfcp_scsi_eh_abort_handler,
53 .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, 54 .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
55 .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
54 .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, 56 .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler,
55 .can_queue = 4096, 57 .can_queue = 4096,
56 .this_id = -1, 58 .this_id = -1,
@@ -179,11 +181,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
179 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; 181 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
180 182
181 if (unit) { 183 if (unit) {
182 zfcp_erp_wait(unit->port->adapter);
183 atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); 184 atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
184 sdpnt->hostdata = NULL; 185 sdpnt->hostdata = NULL;
185 unit->device = NULL; 186 unit->device = NULL;
186 zfcp_erp_unit_failed(unit); 187 zfcp_erp_unit_failed(unit, 12, NULL);
187 zfcp_unit_put(unit); 188 zfcp_unit_put(unit);
188 } else 189 } else
189 ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " 190 ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
@@ -442,58 +443,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
442 return retval; 443 return retval;
443} 444}
444 445
445static int 446static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
446zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
447{ 447{
448 int retval; 448 int retval;
449 struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; 449 struct zfcp_unit *unit = scpnt->device->hostdata;
450 450
451 if (!unit) { 451 if (!unit) {
452 ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); 452 WARN_ON(1);
453 retval = SUCCESS; 453 return SUCCESS;
454 goto out;
455 } 454 }
456 ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n", 455 retval = zfcp_task_management_function(unit,
457 unit->fcp_lun, unit->port->wwpn, 456 FCP_LOGICAL_UNIT_RESET,
458 zfcp_get_busid_by_adapter(unit->port->adapter)); 457 scpnt);
458 return retval ? FAILED : SUCCESS;
459}
459 460
460 /* 461static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
461 * If we do not know whether the unit supports 'logical unit reset' 462{
462 * then try 'logical unit reset' and proceed with 'target reset' 463 int retval;
463 * if 'logical unit reset' fails. 464 struct zfcp_unit *unit = scpnt->device->hostdata;
464 * If the unit is known not to support 'logical unit reset' then 465
465 * skip 'logical unit reset' and try 'target reset' immediately. 466 if (!unit) {
466 */ 467 WARN_ON(1);
467 if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, 468 return SUCCESS;
468 &unit->status)) {
469 retval = zfcp_task_management_function(unit,
470 FCP_LOGICAL_UNIT_RESET,
471 scpnt);
472 if (retval) {
473 ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);
474 if (retval == -ENOTSUPP)
475 atomic_set_mask
476 (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,
477 &unit->status);
478 /* fall through and try 'target reset' next */
479 } else {
480 ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",
481 unit);
482 /* avoid 'target reset' */
483 retval = SUCCESS;
484 goto out;
485 }
486 } 469 }
487 retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); 470 retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);
488 if (retval) { 471 return retval ? FAILED : SUCCESS;
489 ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);
490 retval = FAILED;
491 } else {
492 ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);
493 retval = SUCCESS;
494 }
495 out:
496 return retval;
497} 472}
498 473
499static int 474static int
@@ -553,7 +528,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
553 unit->fcp_lun, unit->port->wwpn, 528 unit->fcp_lun, unit->port->wwpn,
554 zfcp_get_busid_by_adapter(unit->port->adapter)); 529 zfcp_get_busid_by_adapter(unit->port->adapter));
555 530
556 zfcp_erp_adapter_reopen(adapter, 0); 531 zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
557 zfcp_erp_wait(adapter); 532 zfcp_erp_wait(adapter);
558 533
559 return SUCCESS; 534 return SUCCESS;