diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_dbf.c | 13 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 9 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 63 |
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 | ||
800 | inline void | 799 | inline void |
801 | zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, | 800 | zfcp_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 | ||
810 | inline void | 809 | inline 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 | ||
820 | static int | 819 | static 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 *); |
186 | extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, | 186 | extern 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); |
189 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, | 189 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, |
190 | struct scsi_cmnd *); | 190 | struct scsi_cmnd *); |
191 | extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); | 191 | extern 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 | */ |
381 | int | 381 | int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
382 | zfcp_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 | } |