summaryrefslogtreecommitdiffstats
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.c124
1 files changed, 60 insertions, 64 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 7829c72..c17505f 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -87,8 +87,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
return 0;;
}
- ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0,
- ZFCP_REQ_AUTO_CLEANUP);
+ ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
if (unlikely(ret == -EBUSY))
return SCSI_MLQUEUE_DEVICE_BUSY;
else if (unlikely(ret < 0))
@@ -145,79 +144,91 @@ out:
static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
- struct Scsi_Host *scsi_host;
- struct zfcp_adapter *adapter;
- struct zfcp_unit *unit;
- struct zfcp_fsf_req *fsf_req;
+ struct Scsi_Host *scsi_host = scpnt->device->host;
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *) scsi_host->hostdata[0];
+ struct zfcp_unit *unit = scpnt->device->hostdata;
+ struct zfcp_fsf_req *old_req, *abrt_req;
unsigned long flags;
unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
int retval = SUCCESS;
-
- scsi_host = scpnt->device->host;
- adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
- unit = scpnt->device->hostdata;
+ int retry = 3;
/* avoid race condition between late normal completion and abort */
write_lock_irqsave(&adapter->abort_lock, flags);
- /* Check whether corresponding fsf_req is still pending */
spin_lock(&adapter->req_list_lock);
- fsf_req = zfcp_reqlist_find(adapter, old_req_id);
+ old_req = zfcp_reqlist_find(adapter, old_req_id);
spin_unlock(&adapter->req_list_lock);
- if (!fsf_req) {
+ if (!old_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
- return retval;
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
+ old_req_id);
+ return SUCCESS;
}
- fsf_req->data = NULL;
+ old_req->data = NULL;
/* don't access old fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
- fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
- if (!fsf_req) {
- zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
- old_req_id);
- retval = FAILED;
- return retval;
+ while (retry--) {
+ abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
+ if (abrt_req)
+ break;
+
+ zfcp_erp_wait(adapter);
+ if (!(atomic_read(&adapter->status) &
+ ZFCP_STATUS_COMMON_RUNNING)) {
+ zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
+ old_req_id);
+ return SUCCESS;
+ }
}
+ if (!abrt_req)
+ return FAILED;
- __wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_event(abrt_req->completion_wq,
+ abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
- } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
- } else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
+ if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
+ else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
+ else {
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
retval = FAILED;
}
- zfcp_fsf_req_free(fsf_req);
-
+ zfcp_fsf_req_free(abrt_req);
return retval;
}
-static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
- struct scsi_cmnd *scpnt)
+static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
{
+ struct zfcp_unit *unit = scpnt->device->hostdata;
struct zfcp_adapter *adapter = unit->port->adapter;
struct zfcp_fsf_req *fsf_req;
int retval = SUCCESS;
-
- /* issue task management function */
- fsf_req = zfcp_fsf_send_fcp_ctm(adapter, unit, tm_flags, 0);
- if (!fsf_req) {
- zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt);
- return FAILED;
+ int retry = 3;
+
+ while (retry--) {
+ fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
+ if (fsf_req)
+ break;
+
+ zfcp_erp_wait(adapter);
+ if (!(atomic_read(&adapter->status) &
+ ZFCP_STATUS_COMMON_RUNNING)) {
+ zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit,
+ scpnt);
+ return SUCCESS;
+ }
}
+ if (!fsf_req)
+ return FAILED;
- __wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- /*
- * check completion status of task management function
- */
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);
retval = FAILED;
@@ -228,39 +239,24 @@ static int zfcp_task_mgmt_function(struct zfcp_unit *unit, u8 tm_flags,
zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);
zfcp_fsf_req_free(fsf_req);
-
return retval;
}
static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
- struct zfcp_unit *unit = scpnt->device->hostdata;
-
- if (!unit) {
- WARN_ON(1);
- return SUCCESS;
- }
- return zfcp_task_mgmt_function(unit, FCP_LOGICAL_UNIT_RESET, scpnt);
+ return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET);
}
static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
{
- struct zfcp_unit *unit = scpnt->device->hostdata;
-
- if (!unit) {
- WARN_ON(1);
- return SUCCESS;
- }
- return zfcp_task_mgmt_function(unit, FCP_TARGET_RESET, scpnt);
+ return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET);
}
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
- struct zfcp_unit *unit;
- struct zfcp_adapter *adapter;
+ struct zfcp_unit *unit = scpnt->device->hostdata;
+ struct zfcp_adapter *adapter = unit->port->adapter;
- unit = scpnt->device->hostdata;
- adapter = unit->port->adapter;
zfcp_erp_adapter_reopen(adapter, 0, 141, scpnt);
zfcp_erp_wait(adapter);
OpenPOWER on IntegriCloud