|
@@ -815,7 +815,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
struct ib_uverbs_create_qp cmd;
|
|
|
struct ib_uverbs_create_qp_resp resp;
|
|
|
struct ib_udata udata;
|
|
|
- struct ib_uevent_object *uobj;
|
|
|
+ struct ib_uqp_object *uobj;
|
|
|
struct ib_pd *pd;
|
|
|
struct ib_cq *scq, *rcq;
|
|
|
struct ib_srq *srq;
|
|
@@ -866,10 +866,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
attr.cap.max_recv_sge = cmd.max_recv_sge;
|
|
|
attr.cap.max_inline_data = cmd.max_inline_data;
|
|
|
|
|
|
- uobj->uobject.user_handle = cmd.user_handle;
|
|
|
- uobj->uobject.context = file->ucontext;
|
|
|
- uobj->events_reported = 0;
|
|
|
- INIT_LIST_HEAD(&uobj->event_list);
|
|
|
+ uobj->uevent.uobject.user_handle = cmd.user_handle;
|
|
|
+ uobj->uevent.uobject.context = file->ucontext;
|
|
|
+ uobj->uevent.events_reported = 0;
|
|
|
+ INIT_LIST_HEAD(&uobj->uevent.event_list);
|
|
|
+ INIT_LIST_HEAD(&uobj->mcast_list);
|
|
|
|
|
|
qp = pd->device->create_qp(pd, &attr, &udata);
|
|
|
if (IS_ERR(qp)) {
|
|
@@ -882,7 +883,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
qp->send_cq = attr.send_cq;
|
|
|
qp->recv_cq = attr.recv_cq;
|
|
|
qp->srq = attr.srq;
|
|
|
- qp->uobject = &uobj->uobject;
|
|
|
+ qp->uobject = &uobj->uevent.uobject;
|
|
|
qp->event_handler = attr.event_handler;
|
|
|
qp->qp_context = attr.qp_context;
|
|
|
qp->qp_type = attr.qp_type;
|
|
@@ -901,14 +902,14 @@ retry:
|
|
|
goto err_destroy;
|
|
|
}
|
|
|
|
|
|
- ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
|
|
|
+ ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id);
|
|
|
|
|
|
if (ret == -EAGAIN)
|
|
|
goto retry;
|
|
|
if (ret)
|
|
|
goto err_destroy;
|
|
|
|
|
|
- resp.qp_handle = uobj->uobject.id;
|
|
|
+ resp.qp_handle = uobj->uevent.uobject.id;
|
|
|
resp.max_recv_sge = attr.cap.max_recv_sge;
|
|
|
resp.max_send_sge = attr.cap.max_send_sge;
|
|
|
resp.max_recv_wr = attr.cap.max_recv_wr;
|
|
@@ -922,7 +923,7 @@ retry:
|
|
|
}
|
|
|
|
|
|
down(&file->mutex);
|
|
|
- list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
|
|
|
+ list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
|
|
|
up(&file->mutex);
|
|
|
|
|
|
up(&ib_uverbs_idr_mutex);
|
|
@@ -930,7 +931,7 @@ retry:
|
|
|
return in_len;
|
|
|
|
|
|
err_idr:
|
|
|
- idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);
|
|
|
+ idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id);
|
|
|
|
|
|
err_destroy:
|
|
|
ib_destroy_qp(qp);
|
|
@@ -1032,7 +1033,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
|
|
|
struct ib_uverbs_destroy_qp cmd;
|
|
|
struct ib_uverbs_destroy_qp_resp resp;
|
|
|
struct ib_qp *qp;
|
|
|
- struct ib_uevent_object *uobj;
|
|
|
+ struct ib_uqp_object *uobj;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
@@ -1046,7 +1047,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
|
|
|
if (!qp || qp->uobject->context != file->ucontext)
|
|
|
goto out;
|
|
|
|
|
|
- uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
|
|
|
+ uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
|
|
|
+
|
|
|
+ if (!list_empty(&uobj->mcast_list)) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
ret = ib_destroy_qp(qp);
|
|
|
if (ret)
|
|
@@ -1055,12 +1061,12 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
|
|
|
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
|
|
|
|
|
|
down(&file->mutex);
|
|
|
- list_del(&uobj->uobject.list);
|
|
|
+ list_del(&uobj->uevent.uobject.list);
|
|
|
up(&file->mutex);
|
|
|
|
|
|
- ib_uverbs_release_uevent(file, uobj);
|
|
|
+ ib_uverbs_release_uevent(file, &uobj->uevent);
|
|
|
|
|
|
- resp.events_reported = uobj->events_reported;
|
|
|
+ resp.events_reported = uobj->uevent.events_reported;
|
|
|
|
|
|
kfree(uobj);
|
|
|
|
|
@@ -1542,6 +1548,8 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
|
|
|
{
|
|
|
struct ib_uverbs_attach_mcast cmd;
|
|
|
struct ib_qp *qp;
|
|
|
+ struct ib_uqp_object *uobj;
|
|
|
+ struct ib_uverbs_mcast_entry *mcast;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
@@ -1550,9 +1558,36 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
|
|
|
down(&ib_uverbs_idr_mutex);
|
|
|
|
|
|
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
|
|
|
- if (qp && qp->uobject->context == file->ucontext)
|
|
|
- ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
|
|
|
+ if (!qp || qp->uobject->context != file->ucontext)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
|
|
|
+
|
|
|
+ list_for_each_entry(mcast, &uobj->mcast_list, list)
|
|
|
+ if (cmd.mlid == mcast->lid &&
|
|
|
+ !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
|
|
|
+ ret = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
+ mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
|
|
|
+ if (!mcast) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ mcast->lid = cmd.mlid;
|
|
|
+ memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
|
|
|
+
|
|
|
+ ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
|
|
|
+ if (!ret) {
|
|
|
+ uobj = container_of(qp->uobject, struct ib_uqp_object,
|
|
|
+ uevent.uobject);
|
|
|
+ list_add_tail(&mcast->list, &uobj->mcast_list);
|
|
|
+ } else
|
|
|
+ kfree(mcast);
|
|
|
+
|
|
|
+out:
|
|
|
up(&ib_uverbs_idr_mutex);
|
|
|
|
|
|
return ret ? ret : in_len;
|
|
@@ -1563,7 +1598,9 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
|
|
|
int out_len)
|
|
|
{
|
|
|
struct ib_uverbs_detach_mcast cmd;
|
|
|
+ struct ib_uqp_object *uobj;
|
|
|
struct ib_qp *qp;
|
|
|
+ struct ib_uverbs_mcast_entry *mcast;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
if (copy_from_user(&cmd, buf, sizeof cmd))
|
|
@@ -1572,9 +1609,24 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
|
|
|
down(&ib_uverbs_idr_mutex);
|
|
|
|
|
|
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
|
|
|
- if (qp && qp->uobject->context == file->ucontext)
|
|
|
- ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
|
|
|
+ if (!qp || qp->uobject->context != file->ucontext)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
|
|
|
+ uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
|
|
|
+
|
|
|
+ list_for_each_entry(mcast, &uobj->mcast_list, list)
|
|
|
+ if (cmd.mlid == mcast->lid &&
|
|
|
+ !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
|
|
|
+ list_del(&mcast->list);
|
|
|
+ kfree(mcast);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+out:
|
|
|
up(&ib_uverbs_idr_mutex);
|
|
|
|
|
|
return ret ? ret : in_len;
|