1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* 3 * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved. 4 */ 5 6 #include <rdma/uverbs_std_types.h> 7 #include <rdma/uverbs_ioctl.h> 8 #include "rdma_core.h" 9 #include "uverbs.h" 10 11 static int UVERBS_HANDLER(UVERBS_METHOD_ASYNC_EVENT_ALLOC)( 12 struct uverbs_attr_bundle *attrs) 13 { 14 struct ib_uobject *uobj = 15 uverbs_attr_get_uobject(attrs, UVERBS_METHOD_ASYNC_EVENT_ALLOC); 16 17 ib_uverbs_init_async_event_file( 18 container_of(uobj, struct ib_uverbs_async_event_file, uobj)); 19 return 0; 20 } 21 22 static void uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, 23 enum rdma_remove_reason why) 24 { 25 struct ib_uverbs_async_event_file *event_file = 26 container_of(uobj, struct ib_uverbs_async_event_file, uobj); 27 28 ib_unregister_event_handler(&event_file->event_handler); 29 30 if (why == RDMA_REMOVE_DRIVER_REMOVE) 31 ib_uverbs_async_handler(event_file, 0, IB_EVENT_DEVICE_FATAL, 32 NULL, NULL); 33 } 34 35 int uverbs_async_event_release(struct inode *inode, struct file *filp) 36 { 37 struct ib_uverbs_async_event_file *event_file; 38 struct ib_uobject *uobj = filp->private_data; 39 int ret; 40 41 if (!uobj) 42 return uverbs_uobject_fd_release(inode, filp); 43 44 event_file = 45 container_of(uobj, struct ib_uverbs_async_event_file, uobj); 46 47 /* 48 * The async event FD has to deliver IB_EVENT_DEVICE_FATAL even after 49 * disassociation, so cleaning the event list must only happen after 50 * release. The user knows it has reached the end of the event stream 51 * when it sees IB_EVENT_DEVICE_FATAL. 52 */ 53 uverbs_uobject_get(uobj); 54 ret = uverbs_uobject_fd_release(inode, filp); 55 ib_uverbs_free_event_queue(&event_file->ev_queue); 56 uverbs_uobject_put(uobj); 57 return ret; 58 } 59 60 DECLARE_UVERBS_NAMED_METHOD( 61 UVERBS_METHOD_ASYNC_EVENT_ALLOC, 62 UVERBS_ATTR_FD(UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE, 63 UVERBS_OBJECT_ASYNC_EVENT, 64 UVERBS_ACCESS_NEW, 65 UA_MANDATORY)); 66 67 DECLARE_UVERBS_NAMED_OBJECT( 68 UVERBS_OBJECT_ASYNC_EVENT, 69 UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_async_event_file), 70 uverbs_async_event_destroy_uobj, 71 &uverbs_async_event_fops, 72 "[infinibandevent]", 73 O_RDONLY), 74 &UVERBS_METHOD(UVERBS_METHOD_ASYNC_EVENT_ALLOC)); 75 76 const struct uapi_definition uverbs_def_obj_async_fd[] = { 77 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_ASYNC_EVENT), 78 {} 79 }; 80