Commit 8cba2077 authored by David Dillow's avatar David Dillow Committed by Roland Dreier

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: default avatarDavid Dillow <dillowda@ornl.gov>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent a9e527e3
...@@ -930,13 +930,18 @@ static int srp_post_recv(struct srp_target_port *target) ...@@ -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 * req_lim and tx_head. Lock cannot be dropped between call here and
* call to __srp_post_send(). * 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) if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
return NULL; return NULL;
if (unlikely(target->req_lim < 1)) if (target->req_lim < min) {
++target->zero_req_lim; ++target->zero_req_lim;
return NULL;
}
return target->tx_ring[target->tx_head & SRP_SQ_SIZE]; return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
} }
...@@ -993,7 +998,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd, ...@@ -993,7 +998,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
return 0; return 0;
} }
iu = __srp_get_tx_iu(target); iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
if (!iu) if (!iu)
goto err; goto err;
...@@ -1283,7 +1288,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, ...@@ -1283,7 +1288,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
init_completion(&req->done); init_completion(&req->done);
iu = __srp_get_tx_iu(target); iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
if (!iu) if (!iu)
goto out; goto out;
......
...@@ -79,6 +79,11 @@ enum srp_target_state { ...@@ -79,6 +79,11 @@ enum srp_target_state {
SRP_TARGET_REMOVED SRP_TARGET_REMOVED
}; };
enum srp_request_type {
SRP_REQ_NORMAL,
SRP_REQ_TASK_MGMT,
};
struct srp_device { struct srp_device {
struct list_head dev_list; struct list_head dev_list;
struct ib_device *dev; struct ib_device *dev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment