diff options
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 64 |
2 files changed, 20 insertions, 45 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 9e9f6c1e4e5d..662c70f537ec 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -634,7 +634,6 @@ do { \ | |||
634 | ZFCP_STATUS_PORT_NO_SCSI_ID) | 634 | ZFCP_STATUS_PORT_NO_SCSI_ID) |
635 | 635 | ||
636 | /* logical unit status */ | 636 | /* logical unit status */ |
637 | #define ZFCP_STATUS_UNIT_NOTSUPPUNITRESET 0x00000001 | ||
638 | #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 | 637 | #define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002 |
639 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 | 638 | #define ZFCP_STATUS_UNIT_SHARED 0x00000004 |
640 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 | 639 | #define ZFCP_STATUS_UNIT_READONLY 0x00000008 |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b9daf5c05862..ff97a61ad964 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 *)); |
32 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); | 32 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); |
33 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); | 33 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); |
34 | static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *); | ||
34 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); | 35 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); |
35 | static int zfcp_task_management_function(struct zfcp_unit *, u8, | 36 | static 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, |
@@ -442,58 +444,32 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
442 | return retval; | 444 | return retval; |
443 | } | 445 | } |
444 | 446 | ||
445 | static int | 447 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) |
446 | zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | ||
447 | { | 448 | { |
448 | int retval; | 449 | int retval; |
449 | struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; | 450 | struct zfcp_unit *unit = scpnt->device->hostdata; |
450 | 451 | ||
451 | if (!unit) { | 452 | if (!unit) { |
452 | ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); | 453 | WARN_ON(1); |
453 | retval = SUCCESS; | 454 | return SUCCESS; |
454 | goto out; | ||
455 | } | 455 | } |
456 | ZFCP_LOG_NORMAL("resetting unit 0x%016Lx on port 0x%016Lx, adapter %s\n", | 456 | retval = zfcp_task_management_function(unit, |
457 | unit->fcp_lun, unit->port->wwpn, | 457 | FCP_LOGICAL_UNIT_RESET, |
458 | zfcp_get_busid_by_adapter(unit->port->adapter)); | 458 | scpnt); |
459 | return retval ? FAILED : SUCCESS; | ||
460 | } | ||
459 | 461 | ||
460 | /* | 462 | static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) |
461 | * If we do not know whether the unit supports 'logical unit reset' | 463 | { |
462 | * then try 'logical unit reset' and proceed with 'target reset' | 464 | int retval; |
463 | * if 'logical unit reset' fails. | 465 | struct zfcp_unit *unit = scpnt->device->hostdata; |
464 | * If the unit is known not to support 'logical unit reset' then | 466 | |
465 | * skip 'logical unit reset' and try 'target reset' immediately. | 467 | if (!unit) { |
466 | */ | 468 | WARN_ON(1); |
467 | if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, | 469 | 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 | } | 470 | } |
487 | retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); | 471 | retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); |
488 | if (retval) { | 472 | 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 | } | 473 | } |
498 | 474 | ||
499 | static int | 475 | static int |