|
@@ -1400,7 +1400,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
|
|
|
scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
|
|
|
|
|
|
- if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
|
|
|
+ if (!pd || !scq || !rcq ||
|
|
|
+ (cmd.is_srq && (!srq || srq->srq_type != IB_SRQT_BASIC))) {
|
|
|
ret = -EINVAL;
|
|
|
goto err_put;
|
|
|
}
|
|
@@ -2293,108 +2294,199 @@ out_put:
|
|
|
return ret ? ret : in_len;
|
|
|
}
|
|
|
|
|
|
-ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
|
|
|
- const char __user *buf, int in_len,
|
|
|
- int out_len)
|
|
|
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
|
|
|
+ struct ib_uverbs_create_xsrq *cmd,
|
|
|
+ struct ib_udata *udata)
|
|
|
{
|
|
|
- struct ib_uverbs_create_srq cmd;
|
|
|
struct ib_uverbs_create_srq_resp resp;
|
|
|
- struct ib_udata udata;
|
|
|
- struct ib_uevent_object *obj;
|
|
|
+ struct ib_usrq_object *obj;
|
|
|
struct ib_pd *pd;
|
|
|
struct ib_srq *srq;
|
|
|
+ struct ib_uobject *uninitialized_var(xrcd_uobj);
|
|
|
struct ib_srq_init_attr attr;
|
|
|
int ret;
|
|
|
|
|
|
- if (out_len < sizeof resp)
|
|
|
- return -ENOSPC;
|
|
|
-
|
|
|
- if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
|
- return -EFAULT;
|
|
|
-
|
|
|
- INIT_UDATA(&udata, buf + sizeof cmd,
|
|
|
- (unsigned long) cmd.response + sizeof resp,
|
|
|
- in_len - sizeof cmd, out_len - sizeof resp);
|
|
|
-
|
|
|
obj = kmalloc(sizeof *obj, GFP_KERNEL);
|
|
|
if (!obj)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
|
|
|
- down_write(&obj->uobject.mutex);
|
|
|
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
|
|
|
+ down_write(&obj->uevent.uobject.mutex);
|
|
|
|
|
|
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
|
|
|
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
|
|
|
if (!pd) {
|
|
|
ret = -EINVAL;
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC) {
|
|
|
+ attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
|
|
|
+ if (!attr.ext.xrc.cq) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_put_pd;
|
|
|
+ }
|
|
|
+
|
|
|
+ attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
|
|
|
+ if (!attr.ext.xrc.xrcd) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_put_cq;
|
|
|
+ }
|
|
|
+
|
|
|
+ obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
|
|
|
+ atomic_inc(&obj->uxrcd->refcnt);
|
|
|
+ }
|
|
|
+
|
|
|
attr.event_handler = ib_uverbs_srq_event_handler;
|
|
|
attr.srq_context = file;
|
|
|
- attr.srq_type = IB_SRQT_BASIC;
|
|
|
- attr.attr.max_wr = cmd.max_wr;
|
|
|
- attr.attr.max_sge = cmd.max_sge;
|
|
|
- attr.attr.srq_limit = cmd.srq_limit;
|
|
|
+ attr.srq_type = cmd->srq_type;
|
|
|
+ attr.attr.max_wr = cmd->max_wr;
|
|
|
+ attr.attr.max_sge = cmd->max_sge;
|
|
|
+ attr.attr.srq_limit = cmd->srq_limit;
|
|
|
|
|
|
- obj->events_reported = 0;
|
|
|
- INIT_LIST_HEAD(&obj->event_list);
|
|
|
+ obj->uevent.events_reported = 0;
|
|
|
+ INIT_LIST_HEAD(&obj->uevent.event_list);
|
|
|
|
|
|
- srq = pd->device->create_srq(pd, &attr, &udata);
|
|
|
+ srq = pd->device->create_srq(pd, &attr, udata);
|
|
|
if (IS_ERR(srq)) {
|
|
|
ret = PTR_ERR(srq);
|
|
|
goto err_put;
|
|
|
}
|
|
|
|
|
|
- srq->device = pd->device;
|
|
|
- srq->pd = pd;
|
|
|
- srq->uobject = &obj->uobject;
|
|
|
+ srq->device = pd->device;
|
|
|
+ srq->pd = pd;
|
|
|
+ srq->srq_type = cmd->srq_type;
|
|
|
+ srq->uobject = &obj->uevent.uobject;
|
|
|
srq->event_handler = attr.event_handler;
|
|
|
srq->srq_context = attr.srq_context;
|
|
|
+
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC) {
|
|
|
+ srq->ext.xrc.cq = attr.ext.xrc.cq;
|
|
|
+ srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
|
|
|
+ atomic_inc(&attr.ext.xrc.cq->usecnt);
|
|
|
+ atomic_inc(&attr.ext.xrc.xrcd->usecnt);
|
|
|
+ }
|
|
|
+
|
|
|
atomic_inc(&pd->usecnt);
|
|
|
atomic_set(&srq->usecnt, 0);
|
|
|
|
|
|
- obj->uobject.object = srq;
|
|
|
- ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
|
|
|
+ obj->uevent.uobject.object = srq;
|
|
|
+ ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
|
|
|
if (ret)
|
|
|
goto err_destroy;
|
|
|
|
|
|
memset(&resp, 0, sizeof resp);
|
|
|
- resp.srq_handle = obj->uobject.id;
|
|
|
+ resp.srq_handle = obj->uevent.uobject.id;
|
|
|
resp.max_wr = attr.attr.max_wr;
|
|
|
resp.max_sge = attr.attr.max_sge;
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC)
|
|
|
+ resp.srqn = srq->ext.xrc.srq_num;
|
|
|
|
|
|
- if (copy_to_user((void __user *) (unsigned long) cmd.response,
|
|
|
+ if (copy_to_user((void __user *) (unsigned long) cmd->response,
|
|
|
&resp, sizeof resp)) {
|
|
|
ret = -EFAULT;
|
|
|
goto err_copy;
|
|
|
}
|
|
|
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC) {
|
|
|
+ put_uobj_read(xrcd_uobj);
|
|
|
+ put_cq_read(attr.ext.xrc.cq);
|
|
|
+ }
|
|
|
put_pd_read(pd);
|
|
|
|
|
|
mutex_lock(&file->mutex);
|
|
|
- list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
|
|
|
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
|
|
|
mutex_unlock(&file->mutex);
|
|
|
|
|
|
- obj->uobject.live = 1;
|
|
|
+ obj->uevent.uobject.live = 1;
|
|
|
|
|
|
- up_write(&obj->uobject.mutex);
|
|
|
+ up_write(&obj->uevent.uobject.mutex);
|
|
|
|
|
|
- return in_len;
|
|
|
+ return 0;
|
|
|
|
|
|
err_copy:
|
|
|
- idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
|
|
|
+ idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
|
|
|
|
|
|
err_destroy:
|
|
|
ib_destroy_srq(srq);
|
|
|
|
|
|
err_put:
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC) {
|
|
|
+ atomic_dec(&obj->uxrcd->refcnt);
|
|
|
+ put_uobj_read(xrcd_uobj);
|
|
|
+ }
|
|
|
+
|
|
|
+err_put_cq:
|
|
|
+ if (cmd->srq_type == IB_SRQT_XRC)
|
|
|
+ put_cq_read(attr.ext.xrc.cq);
|
|
|
+
|
|
|
+err_put_pd:
|
|
|
put_pd_read(pd);
|
|
|
|
|
|
err:
|
|
|
- put_uobj_write(&obj->uobject);
|
|
|
+ put_uobj_write(&obj->uevent.uobject);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
|
|
|
+ const char __user *buf, int in_len,
|
|
|
+ int out_len)
|
|
|
+{
|
|
|
+ struct ib_uverbs_create_srq cmd;
|
|
|
+ struct ib_uverbs_create_xsrq xcmd;
|
|
|
+ struct ib_uverbs_create_srq_resp resp;
|
|
|
+ struct ib_udata udata;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (out_len < sizeof resp)
|
|
|
+ return -ENOSPC;
|
|
|
+
|
|
|
+ if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ xcmd.response = cmd.response;
|
|
|
+ xcmd.user_handle = cmd.user_handle;
|
|
|
+ xcmd.srq_type = IB_SRQT_BASIC;
|
|
|
+ xcmd.pd_handle = cmd.pd_handle;
|
|
|
+ xcmd.max_wr = cmd.max_wr;
|
|
|
+ xcmd.max_sge = cmd.max_sge;
|
|
|
+ xcmd.srq_limit = cmd.srq_limit;
|
|
|
+
|
|
|
+ INIT_UDATA(&udata, buf + sizeof cmd,
|
|
|
+ (unsigned long) cmd.response + sizeof resp,
|
|
|
+ in_len - sizeof cmd, out_len - sizeof resp);
|
|
|
+
|
|
|
+ ret = __uverbs_create_xsrq(file, &xcmd, &udata);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return in_len;
|
|
|
+}
|
|
|
+
|
|
|
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
|
|
|
+ const char __user *buf, int in_len, int out_len)
|
|
|
+{
|
|
|
+ struct ib_uverbs_create_xsrq cmd;
|
|
|
+ struct ib_uverbs_create_srq_resp resp;
|
|
|
+ struct ib_udata udata;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (out_len < sizeof resp)
|
|
|
+ return -ENOSPC;
|
|
|
+
|
|
|
+ if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ INIT_UDATA(&udata, buf + sizeof cmd,
|
|
|
+ (unsigned long) cmd.response + sizeof resp,
|
|
|
+ in_len - sizeof cmd, out_len - sizeof resp);
|
|
|
+
|
|
|
+ ret = __uverbs_create_xsrq(file, &cmd, &udata);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return in_len;
|
|
|
+}
|
|
|
+
|
|
|
ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
|
|
|
const char __user *buf, int in_len,
|
|
|
int out_len)
|