diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_std_types.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_std_types.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c index a514556139e7..7f26af5ea066 100644 --- a/drivers/infiniband/core/uverbs_std_types.c +++ b/drivers/infiniband/core/uverbs_std_types.c @@ -145,7 +145,11 @@ int uverbs_free_cq(struct ib_uobject *uobject, ret = ib_destroy_cq(cq); if (!ret || why != RDMA_REMOVE_DESTROY) - ib_uverbs_release_ucq(uobject->context->ufile, ev_file, ucq); + ib_uverbs_release_ucq(uobject->context->ufile, ev_file ? + container_of(ev_file, + struct ib_uverbs_completion_event_file, + ev_file) : NULL, + ucq); return ret; } @@ -186,6 +190,33 @@ int uverbs_free_pd(struct ib_uobject *uobject, return 0; } +int uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_file, + enum rdma_remove_reason why) +{ + struct ib_uverbs_completion_event_file *comp_event_file = + container_of(uobj_file, struct ib_uverbs_completion_event_file, + uobj_file); + struct ib_uverbs_event_file *event_file = &comp_event_file->ev_file; + + spin_lock_irq(&event_file->lock); + event_file->is_closed = 1; + spin_unlock_irq(&event_file->lock); + + if (why == RDMA_REMOVE_DRIVER_REMOVE) { + wake_up_interruptible(&event_file->poll_wait); + kill_fasync(&event_file->async_queue, SIGIO, POLL_IN); + } + return 0; +}; + +const struct uverbs_obj_fd_type uverbs_type_attrs_comp_channel = { + .type = UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), 0), + .context_closed = uverbs_hot_unplug_completion_event_file, + .fops = &uverbs_event_fops, + .name = "[infinibandevent]", + .flags = O_RDONLY, +}; + const struct uverbs_obj_idr_type uverbs_type_attrs_cq = { .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), 0), .destroy_object = uverbs_free_cq, |