aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c4
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c13
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c9
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c63
5 files changed, 42 insertions, 49 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index d2b094d9c34f..504c9219961c 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -189,6 +189,10 @@ struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
189 struct zfcp_fsf_req *request, *tmp; 189 struct zfcp_fsf_req *request, *tmp;
190 unsigned int i; 190 unsigned int i;
191 191
192 /* 0 is reserved as an invalid req_id */
193 if (req_id == 0)
194 return NULL;
195
192 i = req_id % REQUEST_LIST_SIZE; 196 i = req_id % REQUEST_LIST_SIZE;
193 197
194 list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) 198 list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index c033145d0f19..0aa3b1ac76af 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -707,7 +707,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
707 struct zfcp_adapter *adapter, 707 struct zfcp_adapter *adapter,
708 struct scsi_cmnd *scsi_cmnd, 708 struct scsi_cmnd *scsi_cmnd,
709 struct zfcp_fsf_req *fsf_req, 709 struct zfcp_fsf_req *fsf_req,
710 struct zfcp_fsf_req *old_fsf_req) 710 unsigned long old_req_id)
711{ 711{
712 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; 712 struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
713 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; 713 struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
@@ -768,8 +768,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
768 rec->fsf_seqno = fsf_req->seq_no; 768 rec->fsf_seqno = fsf_req->seq_no;
769 rec->fsf_issued = fsf_req->issued; 769 rec->fsf_issued = fsf_req->issued;
770 } 770 }
771 rec->type.old_fsf_reqid = 771 rec->type.old_fsf_reqid = old_req_id;
772 (unsigned long) old_fsf_req;
773 } else { 772 } else {
774 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); 773 strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
775 dump->total_size = buflen; 774 dump->total_size = buflen;
@@ -794,17 +793,17 @@ zfcp_scsi_dbf_event_result(const char *tag, int level,
794 struct zfcp_fsf_req *fsf_req) 793 struct zfcp_fsf_req *fsf_req)
795{ 794{
796 _zfcp_scsi_dbf_event_common("rslt", tag, level, 795 _zfcp_scsi_dbf_event_common("rslt", tag, level,
797 adapter, scsi_cmnd, fsf_req, NULL); 796 adapter, scsi_cmnd, fsf_req, 0);
798} 797}
799 798
800inline void 799inline void
801zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, 800zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
802 struct scsi_cmnd *scsi_cmnd, 801 struct scsi_cmnd *scsi_cmnd,
803 struct zfcp_fsf_req *new_fsf_req, 802 struct zfcp_fsf_req *new_fsf_req,
804 struct zfcp_fsf_req *old_fsf_req) 803 unsigned long old_req_id)
805{ 804{
806 _zfcp_scsi_dbf_event_common("abrt", tag, 1, 805 _zfcp_scsi_dbf_event_common("abrt", tag, 1,
807 adapter, scsi_cmnd, new_fsf_req, old_fsf_req); 806 adapter, scsi_cmnd, new_fsf_req, old_req_id);
808} 807}
809 808
810inline void 809inline void
@@ -814,7 +813,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
814 struct zfcp_adapter *adapter = unit->port->adapter; 813 struct zfcp_adapter *adapter = unit->port->adapter;
815 814
816 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", 815 _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
817 tag, 1, adapter, scsi_cmnd, NULL, NULL); 816 tag, 1, adapter, scsi_cmnd, NULL, 0);
818} 817}
819 818
820static int 819static int
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 4f4ef0c4ca7b..710ebbf89929 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -185,7 +185,7 @@ extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
185 struct zfcp_fsf_req *); 185 struct zfcp_fsf_req *);
186extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, 186extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
187 struct scsi_cmnd *, struct zfcp_fsf_req *, 187 struct scsi_cmnd *, struct zfcp_fsf_req *,
188 struct zfcp_fsf_req *); 188 unsigned long);
189extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, 189extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
190 struct scsi_cmnd *); 190 struct scsi_cmnd *);
191extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); 191extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 4913ffbb2fc8..a66b5193b70e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -3527,7 +3527,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
3527 fsf_req->unit = unit; 3527 fsf_req->unit = unit;
3528 3528
3529 /* associate FSF request with SCSI request (for look up on abort) */ 3529 /* associate FSF request with SCSI request (for look up on abort) */
3530 scsi_cmnd->host_scribble = (char *) fsf_req; 3530 scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id;
3531 3531
3532 /* associate SCSI command with FSF request */ 3532 /* associate SCSI command with FSF request */
3533 fsf_req->data = (unsigned long) scsi_cmnd; 3533 fsf_req->data = (unsigned long) scsi_cmnd;
@@ -4667,7 +4667,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
4667{ 4667{
4668 volatile struct qdio_buffer_element *sbale; 4668 volatile struct qdio_buffer_element *sbale;
4669 struct zfcp_fsf_req *fsf_req = NULL; 4669 struct zfcp_fsf_req *fsf_req = NULL;
4670 unsigned long flags;
4671 int ret = 0; 4670 int ret = 0;
4672 struct zfcp_qdio_queue *req_queue = &adapter->request_queue; 4671 struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
4673 4672
@@ -4684,10 +4683,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
4684 fsf_req->fsf_command = fsf_cmd; 4683 fsf_req->fsf_command = fsf_cmd;
4685 INIT_LIST_HEAD(&fsf_req->list); 4684 INIT_LIST_HEAD(&fsf_req->list);
4686 4685
4687 /* unique request id */ 4686 /* this is serialized (we are holding req_queue-lock of adapter */
4688 spin_lock_irqsave(&adapter->req_list_lock, flags); 4687 if (adapter->req_no == 0)
4688 adapter->req_no++;
4689 fsf_req->req_id = adapter->req_no++; 4689 fsf_req->req_id = adapter->req_no++;
4690 spin_unlock_irqrestore(&adapter->req_list_lock, flags);
4691 4690
4692 zfcp_fsf_req_qtcb_init(fsf_req); 4691 zfcp_fsf_req_qtcb_init(fsf_req);
4693 4692
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 4857cccb1d5b..043ed7c0a7ed 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -378,16 +378,15 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
378 * will handle late commands. (Usually, the normal completion of late 378 * will handle late commands. (Usually, the normal completion of late
379 * commands is ignored with respect to the running abort operation.) 379 * commands is ignored with respect to the running abort operation.)
380 */ 380 */
381int 381int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
382zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
383{ 382{
384 struct Scsi_Host *scsi_host; 383 struct Scsi_Host *scsi_host;
385 struct zfcp_adapter *adapter; 384 struct zfcp_adapter *adapter;
386 struct zfcp_unit *unit; 385 struct zfcp_unit *unit;
387 int retval = SUCCESS; 386 struct zfcp_fsf_req *fsf_req;
388 struct zfcp_fsf_req *new_fsf_req = NULL;
389 struct zfcp_fsf_req *old_fsf_req;
390 unsigned long flags; 387 unsigned long flags;
388 unsigned long old_req_id;
389 int retval = SUCCESS;
391 390
392 scsi_host = scpnt->device->host; 391 scsi_host = scpnt->device->host;
393 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; 392 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
@@ -399,55 +398,47 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
399 /* avoid race condition between late normal completion and abort */ 398 /* avoid race condition between late normal completion and abort */
400 write_lock_irqsave(&adapter->abort_lock, flags); 399 write_lock_irqsave(&adapter->abort_lock, flags);
401 400
402 /* 401 /* Check whether corresponding fsf_req is still pending */
403 * Check whether command has just completed and can not be aborted. 402 spin_lock(&adapter->req_list_lock);
404 * Even if the command has just been completed late, we can access 403 fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
405 * scpnt since the SCSI stack does not release it at least until 404 scpnt->host_scribble);
406 * this routine returns. (scpnt is parameter passed to this routine 405 spin_unlock(&adapter->req_list_lock);
407 * and must not disappear during abort even on late completion.) 406 if (!fsf_req) {
408 */
409 old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
410 if (!old_fsf_req) {
411 write_unlock_irqrestore(&adapter->abort_lock, flags); 407 write_unlock_irqrestore(&adapter->abort_lock, flags);
412 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL); 408 zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
413 retval = SUCCESS; 409 retval = SUCCESS;
414 goto out; 410 goto out;
415 } 411 }
416 old_fsf_req->data = 0; 412 fsf_req->data = 0;
417 old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; 413 fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
414 old_req_id = fsf_req->req_id;
418 415
419 /* don't access old_fsf_req after releasing the abort_lock */ 416 /* don't access old fsf_req after releasing the abort_lock */
420 write_unlock_irqrestore(&adapter->abort_lock, flags); 417 write_unlock_irqrestore(&adapter->abort_lock, flags);
421 /* call FSF routine which does the abort */ 418
422 new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, 419 fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
423 adapter, unit, 0); 420 if (!fsf_req) {
424 if (!new_fsf_req) {
425 ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); 421 ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
426 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL, 422 zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
427 old_fsf_req); 423 old_req_id);
428 retval = FAILED; 424 retval = FAILED;
429 goto out; 425 goto out;
430 } 426 }
431 427
432 /* wait for completion of abort */ 428 __wait_event(fsf_req->completion_wq,
433 __wait_event(new_fsf_req->completion_wq, 429 fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
434 new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
435 430
436 /* status should be valid since signals were not permitted */ 431 if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
437 if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { 432 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
438 zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
439 NULL);
440 retval = SUCCESS; 433 retval = SUCCESS;
441 } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { 434 } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
442 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req, 435 zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
443 NULL);
444 retval = SUCCESS; 436 retval = SUCCESS;
445 } else { 437 } else {
446 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req, 438 zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
447 NULL);
448 retval = FAILED; 439 retval = FAILED;
449 } 440 }
450 zfcp_fsf_req_free(new_fsf_req); 441 zfcp_fsf_req_free(fsf_req);
451 out: 442 out:
452 return retval; 443 return retval;
453} 444}