|
@@ -2328,96 +2328,88 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
|
|
|
- struct ib_device *ib_dev,
|
|
|
- const char __user *buf, int in_len,
|
|
|
- int out_len)
|
|
|
+static int modify_qp(struct ib_uverbs_file *file,
|
|
|
+ struct ib_uverbs_ex_modify_qp *cmd, struct ib_udata *udata)
|
|
|
{
|
|
|
- struct ib_uverbs_modify_qp cmd;
|
|
|
- struct ib_udata udata;
|
|
|
- struct ib_qp *qp;
|
|
|
- struct ib_qp_attr *attr;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
|
|
|
- out_len);
|
|
|
+ struct ib_qp_attr *attr;
|
|
|
+ struct ib_qp *qp;
|
|
|
+ int ret;
|
|
|
|
|
|
attr = kmalloc(sizeof *attr, GFP_KERNEL);
|
|
|
if (!attr)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- qp = idr_read_qp(cmd.qp_handle, file->ucontext);
|
|
|
+ qp = idr_read_qp(cmd->base.qp_handle, file->ucontext);
|
|
|
if (!qp) {
|
|
|
ret = -EINVAL;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- attr->qp_state = cmd.qp_state;
|
|
|
- attr->cur_qp_state = cmd.cur_qp_state;
|
|
|
- attr->path_mtu = cmd.path_mtu;
|
|
|
- attr->path_mig_state = cmd.path_mig_state;
|
|
|
- attr->qkey = cmd.qkey;
|
|
|
- attr->rq_psn = cmd.rq_psn;
|
|
|
- attr->sq_psn = cmd.sq_psn;
|
|
|
- attr->dest_qp_num = cmd.dest_qp_num;
|
|
|
- attr->qp_access_flags = cmd.qp_access_flags;
|
|
|
- attr->pkey_index = cmd.pkey_index;
|
|
|
- attr->alt_pkey_index = cmd.alt_pkey_index;
|
|
|
- attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
|
|
|
- attr->max_rd_atomic = cmd.max_rd_atomic;
|
|
|
- attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic;
|
|
|
- attr->min_rnr_timer = cmd.min_rnr_timer;
|
|
|
- attr->port_num = cmd.port_num;
|
|
|
- attr->timeout = cmd.timeout;
|
|
|
- attr->retry_cnt = cmd.retry_cnt;
|
|
|
- attr->rnr_retry = cmd.rnr_retry;
|
|
|
- attr->alt_port_num = cmd.alt_port_num;
|
|
|
- attr->alt_timeout = cmd.alt_timeout;
|
|
|
-
|
|
|
- memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
|
|
|
- attr->ah_attr.grh.flow_label = cmd.dest.flow_label;
|
|
|
- attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index;
|
|
|
- attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit;
|
|
|
- attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class;
|
|
|
- attr->ah_attr.dlid = cmd.dest.dlid;
|
|
|
- attr->ah_attr.sl = cmd.dest.sl;
|
|
|
- attr->ah_attr.src_path_bits = cmd.dest.src_path_bits;
|
|
|
- attr->ah_attr.static_rate = cmd.dest.static_rate;
|
|
|
- attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0;
|
|
|
- attr->ah_attr.port_num = cmd.dest.port_num;
|
|
|
-
|
|
|
- memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
|
|
|
- attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label;
|
|
|
- attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index;
|
|
|
- attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit;
|
|
|
- attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
|
|
|
- attr->alt_ah_attr.dlid = cmd.alt_dest.dlid;
|
|
|
- attr->alt_ah_attr.sl = cmd.alt_dest.sl;
|
|
|
- attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits;
|
|
|
- attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate;
|
|
|
- attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
|
|
|
- attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
|
|
|
+ attr->qp_state = cmd->base.qp_state;
|
|
|
+ attr->cur_qp_state = cmd->base.cur_qp_state;
|
|
|
+ attr->path_mtu = cmd->base.path_mtu;
|
|
|
+ attr->path_mig_state = cmd->base.path_mig_state;
|
|
|
+ attr->qkey = cmd->base.qkey;
|
|
|
+ attr->rq_psn = cmd->base.rq_psn;
|
|
|
+ attr->sq_psn = cmd->base.sq_psn;
|
|
|
+ attr->dest_qp_num = cmd->base.dest_qp_num;
|
|
|
+ attr->qp_access_flags = cmd->base.qp_access_flags;
|
|
|
+ attr->pkey_index = cmd->base.pkey_index;
|
|
|
+ attr->alt_pkey_index = cmd->base.alt_pkey_index;
|
|
|
+ attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify;
|
|
|
+ attr->max_rd_atomic = cmd->base.max_rd_atomic;
|
|
|
+ attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic;
|
|
|
+ attr->min_rnr_timer = cmd->base.min_rnr_timer;
|
|
|
+ attr->port_num = cmd->base.port_num;
|
|
|
+ attr->timeout = cmd->base.timeout;
|
|
|
+ attr->retry_cnt = cmd->base.retry_cnt;
|
|
|
+ attr->rnr_retry = cmd->base.rnr_retry;
|
|
|
+ attr->alt_port_num = cmd->base.alt_port_num;
|
|
|
+ attr->alt_timeout = cmd->base.alt_timeout;
|
|
|
+ attr->rate_limit = cmd->rate_limit;
|
|
|
+
|
|
|
+ memcpy(attr->ah_attr.grh.dgid.raw, cmd->base.dest.dgid, 16);
|
|
|
+ attr->ah_attr.grh.flow_label = cmd->base.dest.flow_label;
|
|
|
+ attr->ah_attr.grh.sgid_index = cmd->base.dest.sgid_index;
|
|
|
+ attr->ah_attr.grh.hop_limit = cmd->base.dest.hop_limit;
|
|
|
+ attr->ah_attr.grh.traffic_class = cmd->base.dest.traffic_class;
|
|
|
+ attr->ah_attr.dlid = cmd->base.dest.dlid;
|
|
|
+ attr->ah_attr.sl = cmd->base.dest.sl;
|
|
|
+ attr->ah_attr.src_path_bits = cmd->base.dest.src_path_bits;
|
|
|
+ attr->ah_attr.static_rate = cmd->base.dest.static_rate;
|
|
|
+ attr->ah_attr.ah_flags = cmd->base.dest.is_global ?
|
|
|
+ IB_AH_GRH : 0;
|
|
|
+ attr->ah_attr.port_num = cmd->base.dest.port_num;
|
|
|
+
|
|
|
+ memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->base.alt_dest.dgid, 16);
|
|
|
+ attr->alt_ah_attr.grh.flow_label = cmd->base.alt_dest.flow_label;
|
|
|
+ attr->alt_ah_attr.grh.sgid_index = cmd->base.alt_dest.sgid_index;
|
|
|
+ attr->alt_ah_attr.grh.hop_limit = cmd->base.alt_dest.hop_limit;
|
|
|
+ attr->alt_ah_attr.grh.traffic_class = cmd->base.alt_dest.traffic_class;
|
|
|
+ attr->alt_ah_attr.dlid = cmd->base.alt_dest.dlid;
|
|
|
+ attr->alt_ah_attr.sl = cmd->base.alt_dest.sl;
|
|
|
+ attr->alt_ah_attr.src_path_bits = cmd->base.alt_dest.src_path_bits;
|
|
|
+ attr->alt_ah_attr.static_rate = cmd->base.alt_dest.static_rate;
|
|
|
+ attr->alt_ah_attr.ah_flags = cmd->base.alt_dest.is_global ?
|
|
|
+ IB_AH_GRH : 0;
|
|
|
+ attr->alt_ah_attr.port_num = cmd->base.alt_dest.port_num;
|
|
|
|
|
|
if (qp->real_qp == qp) {
|
|
|
- if (cmd.attr_mask & IB_QP_AV) {
|
|
|
+ if (cmd->base.attr_mask & IB_QP_AV) {
|
|
|
ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr);
|
|
|
if (ret)
|
|
|
goto release_qp;
|
|
|
}
|
|
|
ret = qp->device->modify_qp(qp, attr,
|
|
|
- modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
|
|
|
+ modify_qp_mask(qp->qp_type,
|
|
|
+ cmd->base.attr_mask),
|
|
|
+ udata);
|
|
|
} else {
|
|
|
- ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
|
|
|
+ ret = ib_modify_qp(qp, attr,
|
|
|
+ modify_qp_mask(qp->qp_type,
|
|
|
+ cmd->base.attr_mask));
|
|
|
}
|
|
|
|
|
|
- if (ret)
|
|
|
- goto release_qp;
|
|
|
-
|
|
|
- ret = in_len;
|
|
|
-
|
|
|
release_qp:
|
|
|
put_qp_read(qp);
|
|
|
|
|
@@ -2427,6 +2419,68 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
|
|
|
+ struct ib_device *ib_dev,
|
|
|
+ const char __user *buf, int in_len,
|
|
|
+ int out_len)
|
|
|
+{
|
|
|
+ struct ib_uverbs_ex_modify_qp cmd = {};
|
|
|
+ struct ib_udata udata;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (copy_from_user(&cmd.base, buf, sizeof(cmd.base)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ if (cmd.base.attr_mask &
|
|
|
+ ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL,
|
|
|
+ in_len - sizeof(cmd.base), out_len);
|
|
|
+
|
|
|
+ ret = modify_qp(file, &cmd, &udata);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return in_len;
|
|
|
+}
|
|
|
+
|
|
|
+int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file,
|
|
|
+ struct ib_device *ib_dev,
|
|
|
+ struct ib_udata *ucore,
|
|
|
+ struct ib_udata *uhw)
|
|
|
+{
|
|
|
+ struct ib_uverbs_ex_modify_qp cmd = {};
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Last bit is reserved for extending the attr_mask by
|
|
|
+ * using another field.
|
|
|
+ */
|
|
|
+ BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31));
|
|
|
+
|
|
|
+ if (ucore->inlen < sizeof(cmd.base))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (cmd.base.attr_mask &
|
|
|
+ ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (ucore->inlen > sizeof(cmd)) {
|
|
|
+ if (ib_is_udata_cleared(ucore, sizeof(cmd),
|
|
|
+ ucore->inlen - sizeof(cmd)))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = modify_qp(file, &cmd, uhw);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
|
|
|
struct ib_device *ib_dev,
|
|
|
const char __user *buf, int in_len,
|