IB/srp: Make HCA completion vector configurable
Several InfiniBand HCAs allow configuring the completion vector per CQ. This allows spreading the workload created by IB completion interrupts over multiple MSI-X vectors and hence over multiple CPU cores. In other words, configuring the completion vector properly not only allows reducing latency on an initiator connected to multiple SRP targets but also allows improving throughput. Signed-off-by: Bart Van Assche <bvanassche@acm.org> Acked-by: David Dillow <dillowda@ornl.gov> Signed-off-by: Roland Dreier <roland@purestorage.com>
这个提交包含在:
@@ -231,14 +231,16 @@ static int srp_create_target_ib(struct srp_target_port *target)
|
||||
return -ENOMEM;
|
||||
|
||||
recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
|
||||
srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
|
||||
srp_recv_completion, NULL, target, SRP_RQ_SIZE,
|
||||
target->comp_vector);
|
||||
if (IS_ERR(recv_cq)) {
|
||||
ret = PTR_ERR(recv_cq);
|
||||
goto err;
|
||||
}
|
||||
|
||||
send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
|
||||
srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
|
||||
srp_send_completion, NULL, target, SRP_SQ_SIZE,
|
||||
target->comp_vector);
|
||||
if (IS_ERR(send_cq)) {
|
||||
ret = PTR_ERR(send_cq);
|
||||
goto err_recv_cq;
|
||||
@@ -1898,6 +1900,14 @@ static ssize_t show_local_ib_device(struct device *dev,
|
||||
return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
|
||||
}
|
||||
|
||||
static ssize_t show_comp_vector(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct srp_target_port *target = host_to_target(class_to_shost(dev));
|
||||
|
||||
return sprintf(buf, "%d\n", target->comp_vector);
|
||||
}
|
||||
|
||||
static ssize_t show_cmd_sg_entries(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -1924,6 +1934,7 @@ static DEVICE_ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
|
||||
static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
|
||||
static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
|
||||
static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
|
||||
static DEVICE_ATTR(comp_vector, S_IRUGO, show_comp_vector, NULL);
|
||||
static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL);
|
||||
static DEVICE_ATTR(allow_ext_sg, S_IRUGO, show_allow_ext_sg, NULL);
|
||||
|
||||
@@ -1938,6 +1949,7 @@ static struct device_attribute *srp_host_attrs[] = {
|
||||
&dev_attr_zero_req_lim,
|
||||
&dev_attr_local_ib_port,
|
||||
&dev_attr_local_ib_device,
|
||||
&dev_attr_comp_vector,
|
||||
&dev_attr_cmd_sg_entries,
|
||||
&dev_attr_allow_ext_sg,
|
||||
NULL
|
||||
@@ -2061,6 +2073,7 @@ enum {
|
||||
SRP_OPT_CMD_SG_ENTRIES = 1 << 9,
|
||||
SRP_OPT_ALLOW_EXT_SG = 1 << 10,
|
||||
SRP_OPT_SG_TABLESIZE = 1 << 11,
|
||||
SRP_OPT_COMP_VECTOR = 1 << 12,
|
||||
SRP_OPT_ALL = (SRP_OPT_ID_EXT |
|
||||
SRP_OPT_IOC_GUID |
|
||||
SRP_OPT_DGID |
|
||||
@@ -2081,6 +2094,7 @@ static const match_table_t srp_opt_tokens = {
|
||||
{ SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" },
|
||||
{ SRP_OPT_ALLOW_EXT_SG, "allow_ext_sg=%u" },
|
||||
{ SRP_OPT_SG_TABLESIZE, "sg_tablesize=%u" },
|
||||
{ SRP_OPT_COMP_VECTOR, "comp_vector=%u" },
|
||||
{ SRP_OPT_ERR, NULL }
|
||||
};
|
||||
|
||||
@@ -2236,6 +2250,14 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
|
||||
target->sg_tablesize = token;
|
||||
break;
|
||||
|
||||
case SRP_OPT_COMP_VECTOR:
|
||||
if (match_int(args, &token) || token < 0) {
|
||||
pr_warn("bad comp_vector parameter '%s'\n", p);
|
||||
goto out;
|
||||
}
|
||||
target->comp_vector = token;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_warn("unknown parameter or missing value '%s' in target creation request\n",
|
||||
p);
|
||||
|
在新工单中引用
屏蔽一个用户