struct ib_uverbs_get_context_resp resp;
struct ib_udata udata;
struct ib_device *ibdev = file->device->ib_dev;
+ struct ib_ucontext *ucontext;
int i;
- int ret = in_len;
+ int ret;
if (out_len < sizeof resp)
return -ENOSPC;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ down(&file->mutex);
+
+ if (file->ucontext) {
+ ret = -EINVAL;
+ goto err;
+ }
+
INIT_UDATA(&udata, buf + sizeof cmd,
(unsigned long) cmd.response + sizeof resp,
in_len - sizeof cmd, out_len - sizeof resp);
- file->ucontext = ibdev->alloc_ucontext(ibdev, &udata);
- if (IS_ERR(file->ucontext)) {
- ret = PTR_ERR(file->ucontext);
- file->ucontext = NULL;
- return ret;
- }
+ ucontext = ibdev->alloc_ucontext(ibdev, &udata);
+ if (IS_ERR(ucontext))
+ return PTR_ERR(file->ucontext);
- file->ucontext->device = ibdev;
- INIT_LIST_HEAD(&file->ucontext->pd_list);
- INIT_LIST_HEAD(&file->ucontext->mr_list);
- INIT_LIST_HEAD(&file->ucontext->mw_list);
- INIT_LIST_HEAD(&file->ucontext->cq_list);
- INIT_LIST_HEAD(&file->ucontext->qp_list);
- INIT_LIST_HEAD(&file->ucontext->srq_list);
- INIT_LIST_HEAD(&file->ucontext->ah_list);
- spin_lock_init(&file->ucontext->lock);
+ ucontext->device = ibdev;
+ INIT_LIST_HEAD(&ucontext->pd_list);
+ INIT_LIST_HEAD(&ucontext->mr_list);
+ INIT_LIST_HEAD(&ucontext->mw_list);
+ INIT_LIST_HEAD(&ucontext->cq_list);
+ INIT_LIST_HEAD(&ucontext->qp_list);
+ INIT_LIST_HEAD(&ucontext->srq_list);
+ INIT_LIST_HEAD(&ucontext->ah_list);
resp.async_fd = file->async_file.fd;
for (i = 0; i < file->device->num_comp; ++i)
if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
i * sizeof (__u32),
- &file->comp_file[i].fd, sizeof (__u32)))
- goto err;
+ &file->comp_file[i].fd, sizeof (__u32))) {
+ ret = -EFAULT;
+ goto err_free;
+ }
if (copy_to_user((void __user *) (unsigned long) cmd.response,
- &resp, sizeof resp))
- goto err;
+ &resp, sizeof resp)) {
+ ret = -EFAULT;
+ goto err_free;
+ }
+
+ file->ucontext = ucontext;
+ up(&file->mutex);
return in_len;
-err:
- ibdev->dealloc_ucontext(file->ucontext);
- file->ucontext = NULL;
+err_free:
+ ibdev->dealloc_ucontext(ucontext);
- return -EFAULT;
+err:
+ up(&file->mutex);
+ return ret;
}
ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
if (ret)
goto err_pd;
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
memset(&resp, 0, sizeof resp);
resp.pd_handle = uobj->id;
return in_len;
err_list:
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
down(&ib_uverbs_idr_mutex);
idr_remove(&ib_uverbs_pd_idr, uobj->id);
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
kfree(uobj);
resp.mr_handle = obj->uobject.id;
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
return in_len;
err_list:
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&obj->uobject.list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
err_unreg:
ib_dereg_mr(mr);
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
- spin_lock_irq(&file->ucontext->lock);
+ down(&file->mutex);
list_del(&memobj->uobject.list);
- spin_unlock_irq(&file->ucontext->lock);
+ up(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj);
struct ib_uverbs_create_cq cmd;
struct ib_uverbs_create_cq_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_ucq_object *uobj;
struct ib_cq *cq;
int ret;
if (!uobj)
return -ENOMEM;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->comp_events_reported = 0;
+ uobj->async_events_reported = 0;
+ INIT_LIST_HEAD(&uobj->comp_list);
+ INIT_LIST_HEAD(&uobj->async_list);
cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
file->ucontext, &udata);
}
cq->device = file->device->ib_dev;
- cq->uobject = uobj;
+ cq->uobject = &uobj->uobject;
cq->comp_handler = ib_uverbs_comp_handler;
cq->event_handler = ib_uverbs_cq_event_handler;
cq->cq_context = file;
}
down(&ib_uverbs_idr_mutex);
- ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
up(&ib_uverbs_idr_mutex);
if (ret == -EAGAIN)
if (ret)
goto err_cq;
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->cq_list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+ up(&file->mutex);
memset(&resp, 0, sizeof resp);
- resp.cq_handle = uobj->id;
+ resp.cq_handle = uobj->uobject.id;
resp.cqe = cq->cqe;
if (copy_to_user((void __user *) (unsigned long) cmd.response,
return in_len;
err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
down(&ib_uverbs_idr_mutex);
- idr_remove(&ib_uverbs_cq_idr, uobj->id);
+ idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
up(&ib_uverbs_idr_mutex);
err_cq:
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_cq cmd;
- struct ib_cq *cq;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_cq cmd;
+ struct ib_uverbs_destroy_cq_resp resp;
+ struct ib_cq *cq;
+ struct ib_ucq_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ u64 user_handle;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext)
goto out;
- uobj = cq->uobject;
+ user_handle = cq->uobject->user_handle;
+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
ret = ib_destroy_cq(cq);
if (ret)
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ spin_lock_irq(&file->comp_file[0].lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->comp_file[0].lock);
+
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.comp_events_reported = uobj->comp_events_reported;
+ resp.async_events_reported = uobj->async_events_reported;
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);
struct ib_uverbs_create_qp cmd;
struct ib_uverbs_create_qp_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_uevent_object *uobj;
struct ib_pd *pd;
struct ib_cq *scq, *rcq;
struct ib_srq *srq;
attr.cap.max_recv_sge = cmd.max_recv_sge;
attr.cap.max_inline_data = cmd.max_inline_data;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
qp = pd->device->create_qp(pd, &attr, &udata);
if (IS_ERR(qp)) {
qp->send_cq = attr.send_cq;
qp->recv_cq = attr.recv_cq;
qp->srq = attr.srq;
- qp->uobject = uobj;
+ qp->uobject = &uobj->uobject;
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
goto err_destroy;
}
- ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
if (ret == -EAGAIN)
goto retry;
if (ret)
goto err_destroy;
- resp.qp_handle = uobj->id;
+ resp.qp_handle = uobj->uobject.id;
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->qp_list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
+ up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
return in_len;
err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
err_destroy:
ib_destroy_qp(qp);
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_qp cmd;
- struct ib_qp *qp;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_qp cmd;
+ struct ib_uverbs_destroy_qp_resp resp;
+ struct ib_qp *qp;
+ struct ib_uevent_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
+ memset(&resp, 0, sizeof resp);
+
down(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
goto out;
- uobj = qp->uobject;
+ uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
ret = ib_destroy_qp(qp);
if (ret)
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.events_reported = uobj->events_reported;
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);
struct ib_uverbs_create_srq cmd;
struct ib_uverbs_create_srq_resp resp;
struct ib_udata udata;
- struct ib_uobject *uobj;
+ struct ib_uevent_object *uobj;
struct ib_pd *pd;
struct ib_srq *srq;
struct ib_srq_init_attr attr;
attr.attr.max_sge = cmd.max_sge;
attr.attr.srq_limit = cmd.srq_limit;
- uobj->user_handle = cmd.user_handle;
- uobj->context = file->ucontext;
+ uobj->uobject.user_handle = cmd.user_handle;
+ uobj->uobject.context = file->ucontext;
+ uobj->events_reported = 0;
+ INIT_LIST_HEAD(&uobj->event_list);
srq = pd->device->create_srq(pd, &attr, &udata);
if (IS_ERR(srq)) {
srq->device = pd->device;
srq->pd = pd;
- srq->uobject = uobj;
+ srq->uobject = &uobj->uobject;
srq->event_handler = attr.event_handler;
srq->srq_context = attr.srq_context;
atomic_inc(&pd->usecnt);
goto err_destroy;
}
- ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id);
+ ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
if (ret == -EAGAIN)
goto retry;
if (ret)
goto err_destroy;
- resp.srq_handle = uobj->id;
+ resp.srq_handle = uobj->uobject.id;
- spin_lock_irq(&file->ucontext->lock);
- list_add_tail(&uobj->list, &file->ucontext->srq_list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+ up(&file->mutex);
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
return in_len;
err_list:
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
err_destroy:
ib_destroy_srq(srq);
const char __user *buf, int in_len,
int out_len)
{
- struct ib_uverbs_destroy_srq cmd;
- struct ib_srq *srq;
- struct ib_uobject *uobj;
- int ret = -EINVAL;
+ struct ib_uverbs_destroy_srq cmd;
+ struct ib_uverbs_destroy_srq_resp resp;
+ struct ib_srq *srq;
+ struct ib_uevent_object *uobj;
+ struct ib_uverbs_event *evt, *tmp;
+ int ret = -EINVAL;
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
down(&ib_uverbs_idr_mutex);
+ memset(&resp, 0, sizeof resp);
+
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
if (!srq || srq->uobject->context != file->ucontext)
goto out;
- uobj = srq->uobject;
+ uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
ret = ib_destroy_srq(srq);
if (ret)
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
- spin_lock_irq(&file->ucontext->lock);
- list_del(&uobj->list);
- spin_unlock_irq(&file->ucontext->lock);
+ down(&file->mutex);
+ list_del(&uobj->uobject.list);
+ up(&file->mutex);
+
+ spin_lock_irq(&file->async_file.lock);
+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+ list_del(&evt->list);
+ kfree(evt);
+ }
+ spin_unlock_irq(&file->async_file.lock);
+
+ resp.events_reported = uobj->events_reported;
kfree(uobj);
+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
+ &resp, sizeof resp))
+ ret = -EFAULT;
+
out:
up(&ib_uverbs_idr_mutex);