From: Mike Christie <michaelc@xxxxxxxxxxx> zfcp uses the device reset handler to try and send a lun reset. If that fails it then does a target reset. This patch has it do a lun reset in the target reset handler like other drivers, then do a target reset in the target reset handler. scsi_error.c will escalate from device reset to target reset for the driver. This patch is only compile tested since suprisingly I could find a s390 box, but I could not hook storage into the the zfcp adapter (box was remote). Signed-off-by: Mike Christie <michaelc@xxxxxxxxxxx> --- drivers/s390/scsi/zfcp_scsi.c | 67 +++++++++++++++++++++++++---------------- 1 files changed, 41 insertions(+), 26 deletions(-) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b9daf5c..13dceec 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 *, void (*done) (struct scsi_cmnd *)); static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); @@ -51,6 +52,7 @@ struct zfcp_data zfcp_data = { .queuecommand = zfcp_scsi_queuecommand, .eh_abort_handler = zfcp_scsi_eh_abort_handler, .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, + .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, .can_queue = 4096, .this_id = -1, @@ -457,33 +459,46 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_adapter(unit->port->adapter)); - /* - * If we do not know whether the unit supports 'logical unit reset' - * then try 'logical unit reset' and proceed with 'target reset' - * if 'logical unit reset' fails. - * If the unit is known not to support 'logical unit reset' then - * skip 'logical unit reset' and try 'target reset' immediately. - */ - if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, - &unit->status)) { - retval = zfcp_task_management_function(unit, - FCP_LOGICAL_UNIT_RESET, - scpnt); - if (retval) { - ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); - if (retval == -ENOTSUPP) - atomic_set_mask - (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, - &unit->status); - /* fall through and try 'target reset' next */ - } else { - ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n", - unit); - /* avoid 'target reset' */ - retval = SUCCESS; - goto out; - } + if (atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, + &unit->status)) { + ZFCP_LOG_DEBUG("unit reset not supported (unit=%p)\n", unit); + retval = FAILED; + goto out; + } + + retval = zfcp_task_management_function(unit, + FCP_LOGICAL_UNIT_RESET, + scpnt); + if (retval) { + ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); + if (retval == -ENOTSUPP) + atomic_set_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, + &unit->status); + retval = FAILED; + } else { + ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n", unit); + retval = SUCCESS; + } + out: + return retval; +} + +static int +zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) +{ + int retval; + struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; + + if (!unit) { + ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n"); + retval = SUCCESS; + goto out; } + + ZFCP_LOG_NORMAL("resetting target 0x%016Lx on port 0x%016Lx, adapter %s\n", + unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_adapter(unit->port->adapter)); + retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); if (retval) { ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); -- 1.5.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html