@@ -163,6 +163,10 @@ struct ib_ucq_object {
u32 async_events_reported;
};
+struct ib_udct_object {
+ struct ib_uevent_object uevent;
+};
+
extern spinlock_t ib_uverbs_idr_lock;
extern struct idr ib_uverbs_pd_idr;
extern struct idr ib_uverbs_mr_idr;
@@ -173,6 +177,7 @@ extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
extern struct idr ib_uverbs_xrcd_idr;
extern struct idr ib_uverbs_rule_idr;
+extern struct idr ib_uverbs_dct_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -189,6 +194,7 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_dct_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
@@ -259,5 +265,10 @@ IB_UVERBS_DECLARE_CMD(close_xrcd);
IB_UVERBS_DECLARE_EX_CMD(create_flow);
IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
IB_UVERBS_DECLARE_EX_CMD(query_device);
+IB_UVERBS_DECLARE_EX_CMD(create_dct);
+IB_UVERBS_DECLARE_EX_CMD(destroy_dct);
+IB_UVERBS_DECLARE_EX_CMD(query_dct);
+IB_UVERBS_DECLARE_EX_CMD(arm_dct);
+IB_UVERBS_DECLARE_EX_CMD(modify_qp);
#endif /* UVERBS_H */
@@ -56,6 +56,7 @@ static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
+static struct uverbs_lock_class dct_lock_class = { .name = "DCT-uobj" };
/*
* The ib_uobject locking scheme is as follows:
@@ -258,6 +259,16 @@ static void put_qp_write(struct ib_qp *qp)
put_uobj_write(qp->uobject);
}
+static struct ib_dct *idr_read_dct(int dct_handle, struct ib_ucontext *context)
+{
+ return idr_read_obj(&ib_uverbs_dct_idr, dct_handle, context, 0);
+}
+
+static void put_dct_read(struct ib_dct *dct)
+{
+ put_uobj_read(dct->uobject);
+}
+
static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
{
return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
@@ -325,6 +336,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&ucontext->ah_list);
INIT_LIST_HEAD(&ucontext->xrcd_list);
INIT_LIST_HEAD(&ucontext->rule_list);
+ INIT_LIST_HEAD(&ucontext->dct_list);
ucontext->closing = 0;
resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -1990,86 +2002,79 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
}
}
-ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
- const char __user *buf, int in_len,
- int out_len)
+static ssize_t modify_qp(struct ib_uverbs_file *file,
+ struct ib_uverbs_modify_qp_ex *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);
-
attr = kmalloc(sizeof *attr, GFP_KERNEL);
if (!attr)
return -ENOMEM;
- qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+ qp = idr_read_qp(cmd->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->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;
+ attr->dct_key = cmd->dct_key;
+
+ 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;
if (qp->real_qp == qp) {
- ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
+ ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd->attr_mask);
if (ret)
goto out;
ret = qp->device->modify_qp(qp, attr,
- modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+ modify_qp_mask(qp->qp_type, cmd->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->attr_mask));
}
put_qp_read(qp);
@@ -2077,7 +2082,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
if (ret)
goto out;
- ret = in_len;
+ return 0;
out:
kfree(attr);
@@ -2085,6 +2090,30 @@ out:
return ret;
}
+ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_modify_qp_ex xcmd;
+ struct ib_uverbs_modify_qp cmd;
+ struct ib_udata udata;
+ 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);
+
+ memset(&xcmd, 0, sizeof(xcmd));
+ memcpy(&xcmd.dest, &cmd, sizeof(cmd));
+ ret = modify_qp(file, &xcmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -3300,9 +3329,332 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
resp.atomics.max_fa_bit_boundary = 0;
resp.atomics.log_max_atomic_inline = 0;
}
+ if (cmd.comp_mask & IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2) {
+ resp.device_cap_flags2 = (__u32)(attr.device_cap_flags >> 32);
+ resp.comp_mask |= IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2;
+ }
+
+ if (cmd.comp_mask & IB_UVERBS_EX_QUERY_DEV_DC_PARAMS) {
+ resp.dc_rd_req = attr.dc_rd_req;
+ resp.dc_rd_res = attr.dc_rd_res;
+ resp.comp_mask |= IB_UVERBS_EX_QUERY_DEV_DC_PARAMS;
+ }
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int ib_uverbs_ex_create_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_create_dct *cmd;
+ struct ib_uverbs_create_dct_resp resp;
+ struct ib_udct_object *obj;
+ struct ib_dct *dct;
+ int err;
+ struct ib_dct_init_attr *attr;
+ struct ib_pd *pd = NULL;
+ struct ib_cq *cq = NULL;
+ struct ib_srq *srq = NULL;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr || !cmd) {
+ err = -ENOMEM;
+ goto err_cmd_attr;
+ }
+
+ err = ib_copy_from_udata(cmd, ucore, sizeof(*cmd));
+ if (err)
+ goto err_cmd_attr;
+
+ if (cmd->comp_mask) {
+ err = -EINVAL;
+ goto err_cmd_attr;
+ }
+
+ obj = kmalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj) {
+ err = -ENOMEM;
+ goto err_cmd_attr;
+ }
+
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
+ &dct_lock_class);
+ down_write(&obj->uevent.uobject.mutex);
+
+ srq = idr_read_srq(cmd->srq_handle, file->ucontext);
+ if (!srq) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+ if (!cq) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
+ if (!pd) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ if (cmd->create_flags & ~IB_DCT_CREATE_FLAGS_MASK) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ attr->cq = cq;
+ attr->access_flags = cmd->access_flags;
+ attr->min_rnr_timer = cmd->min_rnr_timer;
+ attr->srq = srq;
+ attr->tclass = cmd->tclass;
+ attr->flow_label = cmd->flow_label;
+ attr->dc_key = cmd->dc_key;
+ attr->mtu = cmd->mtu;
+ attr->port = cmd->port;
+ attr->pkey_index = cmd->pkey_index;
+ attr->gid_index = cmd->gid_index;
+ attr->hop_limit = cmd->hop_limit;
+ attr->create_flags = cmd->create_flags;
+ attr->inline_size = cmd->inline_size;
+ attr->event_handler = ib_uverbs_dct_event_handler;
+ attr->dct_context = file;
+
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
+ dct = ib_create_dct(pd, attr, uhw);
+ if (IS_ERR(dct)) {
+ err = PTR_ERR(dct);
+ goto err_put;
+ }
+
+ dct->device = file->device->ib_dev;
+ dct->uobject = &obj->uevent.uobject;
+ dct->event_handler = attr->event_handler;
+ dct->dct_context = attr->dct_context;
+
+ obj->uevent.uobject.object = dct;
+ err = idr_add_uobj(&ib_uverbs_dct_idr, &obj->uevent.uobject);
+ if (err)
+ goto err_dct;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.dct_handle = obj->uevent.uobject.id;
+ resp.dctn = dct->dct_num;
+ resp.inline_size = attr->inline_size;
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+ if (err)
+ goto err_copy;
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->dct_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uevent.uobject.live = 1;
+
+ put_pd_read(pd);
+ put_cq_read(cq);
+ put_srq_read(srq);
+
+ up_write(&obj->uevent.uobject.mutex);
+ kfree(attr);
+ kfree(cmd);
+
+ return 0;
+
+err_copy:
+ idr_remove_uobj(&ib_uverbs_dct_idr, &obj->uevent.uobject);
+
+err_dct:
+ ib_destroy_dct(dct, uhw);
+
+err_put:
+ if (pd)
+ put_pd_read(pd);
+ if (cq)
+ put_cq_read(cq);
+ if (srq)
+ put_srq_read(srq);
+
+ put_uobj_write(&obj->uevent.uobject);
+
+err_cmd_attr:
+ kfree(attr);
+ kfree(cmd);
+ return err;
+}
+
+int ib_uverbs_ex_destroy_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_destroy_dct cmd;
+ struct ib_uverbs_destroy_dct_resp resp;
+ struct ib_uobject *uobj;
+ struct ib_udct_object *obj;
+ struct ib_dct *dct;
+ int err;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ uobj = idr_write_uobj(&ib_uverbs_dct_idr, cmd.dct_handle, file->ucontext);
+ if (!uobj)
+ return -EINVAL;
+
+ dct = uobj->object;
+ obj = container_of(uobj, struct ib_udct_object, uevent.uobject);
+
+ err = ib_destroy_dct(dct, uhw);
+ if (!err)
+ uobj->live = 0;
+
+ put_uobj_write(uobj);
+
+ if (err)
+ return err;
+
+ idr_remove_uobj(&ib_uverbs_dct_idr, uobj);
+
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ memset(&resp, 0, sizeof(resp));
+ resp.events_reported = obj->uevent.events_reported;
+
+ put_uobj(uobj);
+
err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
if (err)
return err;
return 0;
}
+
+int ib_uverbs_ex_arm_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_arm_dct cmd;
+ struct ib_dct *dct;
+ int err;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ dct = idr_read_dct(cmd.dct_handle, file->ucontext);
+ if (!dct)
+ return -EINVAL;
+
+ err = ib_arm_dct(dct, uhw);
+ put_dct_read(dct);
+ if (err)
+ return err;
+
+ return err;
+}
+
+int ib_uverbs_ex_query_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_query_dct cmd;
+ struct ib_uverbs_query_dct_resp resp;
+ struct ib_dct *dct;
+ struct ib_dct_attr *attr;
+ int err;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ dct = idr_read_dct(cmd.dct_handle, file->ucontext);
+ if (!dct) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = ib_query_dct(dct, attr, uhw);
+
+ put_dct_read(dct);
+
+ if (err)
+ goto out;
+
+ memset(&resp, 0, sizeof(resp));
+
+ resp.dc_key = attr->dc_key;
+ resp.access_flags = attr->access_flags;
+ resp.flow_label = attr->flow_label;
+ resp.key_violations = attr->key_violations;
+ resp.port = attr->port;
+ resp.min_rnr_timer = attr->min_rnr_timer;
+ resp.tclass = attr->tclass;
+ resp.mtu = attr->mtu;
+ resp.pkey_index = attr->pkey_index;
+ resp.gid_index = attr->gid_index;
+ resp.hop_limit = attr->hop_limit;
+ resp.state = attr->state;
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+
+out:
+ kfree(attr);
+
+ return err;
+}
+
+int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_modify_qp_ex cmd;
+ int err;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask > IB_UVERBS_EX_MODIFY_QP_MAX_MASK)
+ return -EINVAL;
+
+ return modify_qp(file, &cmd, ucore);
+}
@@ -74,6 +74,7 @@ DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr);
DEFINE_IDR(ib_uverbs_xrcd_idr);
DEFINE_IDR(ib_uverbs_rule_idr);
+DEFINE_IDR(ib_uverbs_dct_idr);
static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -123,7 +124,12 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
struct ib_udata *uhw) = {
[IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
[IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
- [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device
+ [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
+ [IB_USER_VERBS_EX_CMD_CREATE_DCT] = ib_uverbs_ex_create_dct,
+ [IB_USER_VERBS_EX_CMD_DESTROY_DCT] = ib_uverbs_ex_destroy_dct,
+ [IB_USER_VERBS_EX_CMD_QUERY_DCT] = ib_uverbs_ex_query_dct,
+ [IB_USER_VERBS_EX_CMD_ARM_DCT] = ib_uverbs_ex_arm_dct,
+ [IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp,
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -199,6 +205,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
struct ib_ucontext *context)
{
struct ib_uobject *uobj, *tmp;
+ int err;
if (!context)
return 0;
@@ -246,6 +253,20 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uqp);
}
+ list_for_each_entry_safe(uobj, tmp, &context->dct_list, list) {
+ struct ib_dct *dct = uobj->object;
+ struct ib_udct_object *udct =
+ container_of(uobj, struct ib_udct_object, uevent.uobject);
+
+ idr_remove_uobj(&ib_uverbs_dct_idr, uobj);
+
+ err = ib_destroy_dct(dct, NULL);
+ if (err)
+ pr_warn("destroying uverbs dct failed: err %d\n", err);
+
+ kfree(udct);
+ }
+
list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
struct ib_cq *cq = uobj->object;
struct ib_uverbs_event_file *ev_file = cq->cq_context;
@@ -516,6 +537,18 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
&uobj->events_reported);
}
+void ib_uverbs_dct_event_handler(struct ib_event *event, void *context_ptr)
+{
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.dct->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
+}
+
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
{
struct ib_uevent_object *uobj;
@@ -1147,6 +1147,7 @@ struct ib_ucontext {
struct list_head ah_list;
struct list_head xrcd_list;
struct list_head rule_list;
+ struct list_head dct_list;
int closing;
};
@@ -91,8 +91,13 @@ enum {
enum {
IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE,
+ IB_USER_VERBS_EX_CMD_MODIFY_QP = IB_USER_VERBS_CMD_MODIFY_QP,
IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
+ IB_USER_VERBS_EX_CMD_CREATE_DCT,
+ IB_USER_VERBS_EX_CMD_DESTROY_DCT,
+ IB_USER_VERBS_EX_CMD_QUERY_DCT,
+ IB_USER_VERBS_EX_CMD_ARM_DCT,
};
/*
@@ -204,7 +209,9 @@ struct ib_uverbs_query_device_resp {
enum {
IB_UVERBS_EX_QUERY_DEV_MASKED_ATOMIC = 1 << 0,
- IB_UVERBS_EX_QUERY_DEV_LAST = 1 << 1,
+ IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2 = 1 << 1,
+ IB_UVERBS_EX_QUERY_DEV_DC_PARAMS = 1 << 2,
+ IB_UVERBS_EX_QUERY_DEV_LAST = 1 << 3,
IB_UVERBS_EX_QUERY_DEV_MAX_MASK = IB_UVERBS_EX_QUERY_DEV_LAST - 1,
};
@@ -223,6 +230,9 @@ struct ib_uverbs_ex_query_device_resp {
struct ib_uverbs_query_device_resp base;
__u32 comp_mask;
struct ib_uverbs_ex_atomic_caps atomics;
+ __u32 device_cap_flags2;
+ __u32 dc_rd_req;
+ __u32 dc_rd_res;
};
struct ib_uverbs_query_port {
@@ -613,6 +623,46 @@ struct ib_uverbs_modify_qp {
struct ib_uverbs_modify_qp_resp {
};
+enum {
+ IB_UVERBS_EX_MODIFY_QP_DCT_KEY = 1 << 0,
+ IB_UVERBS_EX_MODIFY_QP_MAX_MASK = (1 << (0 /*last shift value */ + 1)) - 1,
+};
+
+struct ib_uverbs_modify_qp_ex {
+ __u32 comp_mask;
+ struct ib_uverbs_qp_dest dest;
+ struct ib_uverbs_qp_dest alt_dest;
+ __u32 qp_handle;
+ __u32 attr_mask;
+ __u32 qkey;
+ __u32 rq_psn;
+ __u32 sq_psn;
+ __u32 dest_qp_num;
+ __u32 qp_access_flags;
+ __u16 pkey_index;
+ __u16 alt_pkey_index;
+ __u8 qp_state;
+ __u8 cur_qp_state;
+ __u8 path_mtu;
+ __u8 path_mig_state;
+ __u8 en_sqd_async_notify;
+ __u8 max_rd_atomic;
+ __u8 max_dest_rd_atomic;
+ __u8 min_rnr_timer;
+ __u8 port_num;
+ __u8 timeout;
+ __u8 retry_cnt;
+ __u8 rnr_retry;
+ __u8 alt_port_num;
+ __u8 alt_timeout;
+ __u8 reserved[6];
+ __u64 dct_key;
+ __u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp_ex_resp {
+};
+
struct ib_uverbs_destroy_qp {
__u64 response;
__u32 qp_handle;
@@ -901,4 +951,78 @@ struct ib_uverbs_destroy_srq_resp {
__u32 events_reported;
};
+struct ib_uverbs_create_dct {
+ __u32 comp_mask;
+ __u32 reserved;
+ __u64 user_handle;
+ __u32 pd_handle;
+ __u32 cq_handle;
+ __u32 srq_handle;
+ __u32 access_flags;
+ __u64 dc_key;
+ __u32 flow_label;
+ __u8 min_rnr_timer;
+ __u8 tclass;
+ __u8 port;
+ __u8 pkey_index;
+ __u8 gid_index;
+ __u8 hop_limit;
+ __u8 mtu;
+ __u8 reserved0;
+ __u32 create_flags;
+ __u32 inline_size;
+ __u32 reserved1;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_create_dct_resp {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 dctn;
+ __u32 inline_size;
+ __u64 rsvd;
+};
+
+struct ib_uverbs_destroy_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_destroy_dct_resp {
+ __u32 events_reported;
+ __u32 reserved;
+};
+
+struct ib_uverbs_query_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_query_dct_resp {
+ __u64 dc_key;
+ __u32 access_flags;
+ __u32 flow_label;
+ __u32 key_violations;
+ __u8 port;
+ __u8 min_rnr_timer;
+ __u8 tclass;
+ __u8 mtu;
+ __u8 pkey_index;
+ __u8 gid_index;
+ __u8 hop_limit;
+ __u8 state;
+ __u32 rsvd;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_arm_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+ __u32 driver_data[0];
+};
+
#endif /* IB_USER_VERBS_H */
Signed-off-by: Eli Cohen <eli@mellanox.com> --- drivers/infiniband/core/uverbs.h | 11 + drivers/infiniband/core/uverbs_cmd.c | 474 +++++++++++++++++++++++++++++----- drivers/infiniband/core/uverbs_main.c | 35 ++- include/rdma/ib_verbs.h | 1 + include/uapi/rdma/ib_user_verbs.h | 126 ++++++++- 5 files changed, 584 insertions(+), 63 deletions(-)