diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 155 |
1 files changed, 112 insertions, 43 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index ebccf9f38af9..e91ebde46481 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -590,7 +590,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, 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; @@ -611,8 +611,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, 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); @@ -622,7 +626,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, } 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; @@ -635,7 +639,7 @@ retry: } 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) @@ -644,11 +648,11 @@ retry: goto err_cq; spin_lock_irq(&file->ucontext->lock); - list_add_tail(&uobj->list, &file->ucontext->cq_list); + list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); spin_unlock_irq(&file->ucontext->lock); 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, @@ -661,11 +665,11 @@ retry: err_list: spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); 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: @@ -680,21 +684,27 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, 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) @@ -703,11 +713,32 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); + 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); @@ -721,7 +752,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_uobject *uobj; + struct ib_uevent_object *uobj; struct ib_pd *pd; struct ib_cq *scq, *rcq; struct ib_srq *srq; @@ -772,8 +803,10 @@ 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->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)) { @@ -786,7 +819,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; + qp->uobject = &uobj->uobject; qp->event_handler = attr.event_handler; qp->qp_context = attr.qp_context; qp->qp_type = attr.qp_type; @@ -805,17 +838,17 @@ retry: 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); + list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); spin_unlock_irq(&file->ucontext->lock); if (copy_to_user((void __user *) (unsigned long) cmd.response, @@ -830,7 +863,7 @@ retry: err_list: spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); err_destroy: @@ -930,21 +963,25 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, 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) @@ -953,11 +990,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); + 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); @@ -1015,7 +1065,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 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; @@ -1050,8 +1100,10 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 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)) { @@ -1061,7 +1113,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 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); @@ -1075,17 +1127,17 @@ retry: 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); + list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); spin_unlock_irq(&file->ucontext->lock); if (copy_to_user((void __user *) (unsigned long) cmd.response, @@ -1100,7 +1152,7 @@ retry: err_list: spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); err_destroy: @@ -1149,21 +1201,25 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, 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) @@ -1172,11 +1228,24 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); spin_lock_irq(&file->ucontext->lock); - list_del(&uobj->list); + list_del(&uobj->uobject.list); spin_unlock_irq(&file->ucontext->lock); + 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); |