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 17:15:37 -0500
commit8cba2077325b361dedf058c7dfc6c33691422497 (patch)
treedef0972f32f690ac7107cbeabdf7c0547abf8f87 /drivers/infiniband
parenta9e527e3f9f4510e9f3450ca3bc51bc3ef2854fd (diff)
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)
930 * req_lim and tx_head. Lock cannot be dropped between call here and 930 * req_lim and tx_head. Lock cannot be dropped between call here and
931 * call to __srp_post_send(). 931 * call to __srp_post_send().
932 */ 932 */
933static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target) 933static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
934 enum srp_request_type req_type)
934{ 935{
936 s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
937
935 if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE) 938 if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
936 return NULL; 939 return NULL;
937 940
938 if (unlikely(target->req_lim < 1)) 941 if (target->req_lim < min) {
939 ++target->zero_req_lim; 942 ++target->zero_req_lim;
943 return NULL;
944 }
940 945
941 return target->tx_ring[target->tx_head & SRP_SQ_SIZE]; 946 return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
942} 947}
@@ -993,7 +998,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
993 return 0; 998 return 0;
994 } 999 }
995 1000
996 iu = __srp_get_tx_iu(target); 1001 iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
997 if (!iu) 1002 if (!iu)
998 goto err; 1003 goto err;
999 1004
@@ -1283,7 +1288,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
1283 1288
1284 init_completion(&req->done); 1289 init_completion(&req->done);
1285 1290
1286 iu = __srp_get_tx_iu(target); 1291 iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
1287 if (!iu) 1292 if (!iu)
1288 goto out; 1293 goto out;
1289 1294
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 {
79 SRP_TARGET_REMOVED 79 SRP_TARGET_REMOVED
80}; 80};
81 81
82enum srp_request_type {
83 SRP_REQ_NORMAL,
84 SRP_REQ_TASK_MGMT,
85};
86
82struct srp_device { 87struct srp_device {
83 struct list_head dev_list; 88 struct list_head dev_list;
84 struct ib_device *dev; 89 struct ib_device *dev;