diff options
author | Steffen Maier <maier@linux.ibm.com> | 2018-05-17 19:14:56 +0200 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-05-18 17:22:11 +0200 |
commit | 674595d8519fdf4f78e1a4cceb2130ffa46bcdeb (patch) | |
tree | 603439caa6e137290a0e7740e536daae599a0fbc /drivers/s390/scsi/zfcp_scsi.c | |
parent | scsi: zfcp: decouple TMFs from scsi_cmnd by using fc_block_rport (diff) | |
download | linux-674595d8519fdf4f78e1a4cceb2130ffa46bcdeb.tar.xz linux-674595d8519fdf4f78e1a4cceb2130ffa46bcdeb.zip |
scsi: zfcp: decouple our scsi_eh callbacks from scsi_cmnd
Note: zfcp_scsi_eh_host_reset_handler() will be converted in a later patch.
zfcp_scsi_eh_device_reset_handler() now only depends on scsi_device.
zfcp_scsi_eh_target_reset_handler() now only depends on scsi_target.
All derive other objects from these intended callback arguments.
zfcp_scsi_eh_target_reset_handler() is special: The FCP channel requires a
valid LUN handle so we try to find ourselves a stand-in scsi_device as
suggested by Hannes Reinecke. If it cannot find a stand-in scsi device,
trace a record like the following (formatted with zfcpdbf from s390-tools):
Timestamp : ...
Area : SCSI
Subarea : 00
Level : 1
Exception : -
CPU ID : ..
Caller : 0x...
Record ID : 1
Tag : tr_nosd target reset, no SCSI device
Request ID : 0x0000000000000000 none (invalid)
SCSI ID : 0x00000000 SCSI ID/target denoting scope
SCSI LUN : 0xffffffff none (invalid)
SCSI LUN high : 0xffffffff none (invalid)
SCSI result : 0x00002003 field re-used for midlayer value: FAILED
SCSI retries : 0xff none (invalid)
SCSI allowed : 0xff none (invalid)
SCSI scribble : 0xffffffffffffffff none (invalid)
SCSI opcode : ffffffff ffffffff ffffffff ffffffff none (invalid)
FCP rsp inf cod: 0xff none (invalid)
FCP rsp IU : 00000000 00000000 00000000 00000000 none (invalid)
00000000 00000000
Actually change the signature of zfcp_task_mgmt_function() used by
zfcp_scsi_eh_device_reset_handler() & zfcp_scsi_eh_target_reset_handler().
Since it was prepared in a previous patch, we only need to delete a local
auto variable which is now the intended argument.
Suggested-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e0c5735cf3db..fcc832b73960 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -265,9 +265,14 @@ static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags) write_unlock_irqrestore(&adapter->abort_lock, flags); } -static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) +/** + * zfcp_task_mgmt_function() - Synchronously send a task management function. + * @sdev: Pointer to SCSI device to send the task management command to. + * @tm_flags: Task management flags, + * here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET. + */ +static int zfcp_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags) { - struct scsi_device *sdev = scpnt->device; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); @@ -315,12 +320,40 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET); + struct scsi_device *sdev = scpnt->device; + + return zfcp_task_mgmt_function(sdev, FCP_TMF_LUN_RESET); } static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) { - return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET); + struct scsi_target *starget = scsi_target(scpnt->device); + struct fc_rport *rport = starget_to_rport(starget); + struct Scsi_Host *shost = rport_to_shost(rport); + struct scsi_device *sdev = NULL, *tmp_sdev; + struct zfcp_adapter *adapter = + (struct zfcp_adapter *)shost->hostdata[0]; + int ret; + + shost_for_each_device(tmp_sdev, shost) { + if (tmp_sdev->id == starget->id) { + sdev = tmp_sdev; + break; + } + } + if (!sdev) { + ret = FAILED; + zfcp_dbf_scsi_eh("tr_nosd", adapter, starget->id, ret); + return ret; + } + + ret = zfcp_task_mgmt_function(sdev, FCP_TMF_TGT_RESET); + + /* release reference from above shost_for_each_device */ + if (sdev) + scsi_device_put(tmp_sdev); + + return ret; } static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |