diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 69 |
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 *)); |
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, |
@@ -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 | ||
445 | static int | 446 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) |
446 | zfcp_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 | /* | 461 | 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' | 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 | ||
499 | static int | 474 | static 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; |