aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorDavid Dillow <dillowda@ornl.gov>2007-12-19 17:08:43 -0500
committerRoland Dreier <rolandd@cisco.com>2008-01-25 14:15:37 -0800
commit8cba2077325b361dedf058c7dfc6c33691422497 (patch)
treedef0972f32f690ac7107cbeabdf7c0547abf8f87 /drivers/infiniband
parentIPoIB: improve IPv4/IPv6 to IB mcast mapping functions (diff)
downloadlinux-dev-8cba2077325b361dedf058c7dfc6c33691422497.tar.xz
linux-dev-8cba2077325b361dedf058c7dfc6c33691422497.zip
IB/srp: Respect target credit limit
The current SRP initiator will send requests even if it has no credits available. The results of sending extra requests are vendor specific, but on some devices, overrunning credits will cost 85% of peak performance -- e.g. 100 MB/s vs 720 MB/s. Other devices may just drop the requests. This patch will tell the SCSI midlayer to queue requests if there are fewer than two credits remaining, and will not issue a task management request if there are no credits remaining. The mid-layer will retry the queued command once an outstanding command completes. The patch also removes the unlikely() in __srp_get_tx_iu(), as it is not at all unlikely to hit this limit under heavy load. Signed-off-by: David Dillow <dillowda@ornl.gov> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c13
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h5
2 files changed, 14 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index bdb6f8517401..e98d0612d7ac 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -930,13 +930,18 @@ static int srp_post_recv(struct srp_target_port *target)
* req_lim and tx_head. Lock cannot be dropped between call here and
* call to __srp_post_send().
*/
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target)
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+ enum srp_request_type req_type)
{
+ s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
+
if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
return NULL;
- if (unlikely(target->req_lim < 1))
+ if (target->req_lim < min) {
++target->zero_req_lim;
+ return NULL;
+ }
return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
}
@@ -993,7 +998,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
return 0;
}
- iu = __srp_get_tx_iu(target);
+ iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
if (!iu)
goto err;
@@ -1283,7 +1288,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
init_completion(&req->done);
- iu = __srp_get_tx_iu(target);
+ iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
if (!iu)
goto out;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index e3573e7038c4..4a3c1f37e4c2 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -79,6 +79,11 @@ enum srp_target_state {
SRP_TARGET_REMOVED
};
+enum srp_request_type {
+ SRP_REQ_NORMAL,
+ SRP_REQ_TASK_MGMT,
+};
+
struct srp_device {
struct list_head dev_list;
struct ib_device *dev;