diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-09-05 03:17:31 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-09-05 03:17:31 -0400 |
commit | 14e42917216ab0859827c2d8024df45a917301b4 (patch) | |
tree | efbea5d1c54387d62a6fd66a21560232cf312fda /drivers/infiniband/ulp/srp | |
parent | 292f2b6254c9dbb98def6d3521b07a837545ead0 (diff) | |
parent | 4266274836e81575ee82498d84f4bd08ab7a7378 (diff) |
Merge branch 'fixes' of git://git.alsa-project.org/alsa-kernel into for-next
Diffstat (limited to 'drivers/infiniband/ulp/srp')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 87 |
1 files changed, 63 insertions, 24 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bcbf22ee0aa7..1b5b0c730054 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, | |||
586 | scmnd->sc_data_direction); | 586 | scmnd->sc_data_direction); |
587 | } | 587 | } |
588 | 588 | ||
589 | static void srp_remove_req(struct srp_target_port *target, | 589 | /** |
590 | struct srp_request *req, s32 req_lim_delta) | 590 | * srp_claim_req - Take ownership of the scmnd associated with a request. |
591 | * @target: SRP target port. | ||
592 | * @req: SRP request. | ||
593 | * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take | ||
594 | * ownership of @req->scmnd if it equals @scmnd. | ||
595 | * | ||
596 | * Return value: | ||
597 | * Either NULL or a pointer to the SCSI command the caller became owner of. | ||
598 | */ | ||
599 | static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, | ||
600 | struct srp_request *req, | ||
601 | struct scsi_cmnd *scmnd) | ||
602 | { | ||
603 | unsigned long flags; | ||
604 | |||
605 | spin_lock_irqsave(&target->lock, flags); | ||
606 | if (!scmnd) { | ||
607 | scmnd = req->scmnd; | ||
608 | req->scmnd = NULL; | ||
609 | } else if (req->scmnd == scmnd) { | ||
610 | req->scmnd = NULL; | ||
611 | } else { | ||
612 | scmnd = NULL; | ||
613 | } | ||
614 | spin_unlock_irqrestore(&target->lock, flags); | ||
615 | |||
616 | return scmnd; | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * srp_free_req() - Unmap data and add request to the free request list. | ||
621 | */ | ||
622 | static void srp_free_req(struct srp_target_port *target, | ||
623 | struct srp_request *req, struct scsi_cmnd *scmnd, | ||
624 | s32 req_lim_delta) | ||
591 | { | 625 | { |
592 | unsigned long flags; | 626 | unsigned long flags; |
593 | 627 | ||
594 | srp_unmap_data(req->scmnd, target, req); | 628 | srp_unmap_data(scmnd, target, req); |
629 | |||
595 | spin_lock_irqsave(&target->lock, flags); | 630 | spin_lock_irqsave(&target->lock, flags); |
596 | target->req_lim += req_lim_delta; | 631 | target->req_lim += req_lim_delta; |
597 | req->scmnd = NULL; | ||
598 | list_add_tail(&req->list, &target->free_reqs); | 632 | list_add_tail(&req->list, &target->free_reqs); |
599 | spin_unlock_irqrestore(&target->lock, flags); | 633 | spin_unlock_irqrestore(&target->lock, flags); |
600 | } | 634 | } |
601 | 635 | ||
602 | static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) | 636 | static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) |
603 | { | 637 | { |
604 | req->scmnd->result = DID_RESET << 16; | 638 | struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); |
605 | req->scmnd->scsi_done(req->scmnd); | 639 | |
606 | srp_remove_req(target, req, 0); | 640 | if (scmnd) { |
641 | scmnd->result = DID_RESET << 16; | ||
642 | scmnd->scsi_done(scmnd); | ||
643 | srp_free_req(target, req, scmnd, 0); | ||
644 | } | ||
607 | } | 645 | } |
608 | 646 | ||
609 | static int srp_reconnect_target(struct srp_target_port *target) | 647 | static int srp_reconnect_target(struct srp_target_port *target) |
@@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) | |||
1073 | complete(&target->tsk_mgmt_done); | 1111 | complete(&target->tsk_mgmt_done); |
1074 | } else { | 1112 | } else { |
1075 | req = &target->req_ring[rsp->tag]; | 1113 | req = &target->req_ring[rsp->tag]; |
1076 | scmnd = req->scmnd; | 1114 | scmnd = srp_claim_req(target, req, NULL); |
1077 | if (!scmnd) | 1115 | if (!scmnd) { |
1078 | shost_printk(KERN_ERR, target->scsi_host, | 1116 | shost_printk(KERN_ERR, target->scsi_host, |
1079 | "Null scmnd for RSP w/tag %016llx\n", | 1117 | "Null scmnd for RSP w/tag %016llx\n", |
1080 | (unsigned long long) rsp->tag); | 1118 | (unsigned long long) rsp->tag); |
1119 | |||
1120 | spin_lock_irqsave(&target->lock, flags); | ||
1121 | target->req_lim += be32_to_cpu(rsp->req_lim_delta); | ||
1122 | spin_unlock_irqrestore(&target->lock, flags); | ||
1123 | |||
1124 | return; | ||
1125 | } | ||
1081 | scmnd->result = rsp->status; | 1126 | scmnd->result = rsp->status; |
1082 | 1127 | ||
1083 | if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { | 1128 | if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { |
@@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) | |||
1092 | else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) | 1137 | else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) |
1093 | scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); | 1138 | scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); |
1094 | 1139 | ||
1095 | srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); | 1140 | srp_free_req(target, req, scmnd, |
1141 | be32_to_cpu(rsp->req_lim_delta)); | ||
1142 | |||
1096 | scmnd->host_scribble = NULL; | 1143 | scmnd->host_scribble = NULL; |
1097 | scmnd->scsi_done(scmnd); | 1144 | scmnd->scsi_done(scmnd); |
1098 | } | 1145 | } |
@@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *scmnd) | |||
1631 | { | 1678 | { |
1632 | struct srp_target_port *target = host_to_target(scmnd->device->host); | 1679 | struct srp_target_port *target = host_to_target(scmnd->device->host); |
1633 | struct srp_request *req = (struct srp_request *) scmnd->host_scribble; | 1680 | struct srp_request *req = (struct srp_request *) scmnd->host_scribble; |
1634 | int ret = SUCCESS; | ||
1635 | 1681 | ||
1636 | shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); | 1682 | shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); |
1637 | 1683 | ||
1638 | if (!req || target->qp_in_error) | 1684 | if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) |
1639 | return FAILED; | 1685 | return FAILED; |
1640 | if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, | 1686 | srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, |
1641 | SRP_TSK_ABORT_TASK)) | 1687 | SRP_TSK_ABORT_TASK); |
1642 | return FAILED; | 1688 | srp_free_req(target, req, scmnd, 0); |
1643 | 1689 | scmnd->result = DID_ABORT << 16; | |
1644 | if (req->scmnd) { | ||
1645 | if (!target->tsk_mgmt_status) { | ||
1646 | srp_remove_req(target, req, 0); | ||
1647 | scmnd->result = DID_ABORT << 16; | ||
1648 | } else | ||
1649 | ret = FAILED; | ||
1650 | } | ||
1651 | 1690 | ||
1652 | return ret; | 1691 | return SUCCESS; |
1653 | } | 1692 | } |
1654 | 1693 | ||
1655 | static int srp_reset_device(struct scsi_cmnd *scmnd) | 1694 | static int srp_reset_device(struct scsi_cmnd *scmnd) |