]>
Commit | Line | Data |
---|---|---|
3e032c0e JG |
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 | ||
d680e88e JG |
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 | ||
d680e88e JG |
17 | ib_uverbs_init_async_event_file( |
18 | container_of(uobj, struct ib_uverbs_async_event_file, uobj)); | |
d680e88e JG |
19 | return 0; |
20 | } | |
21 | ||
3e032c0e JG |
22 | static int 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); | |
ccfdbaa5 JG |
29 | |
30 | if (why == RDMA_REMOVE_DRIVER_REMOVE) | |
31 | ib_uverbs_async_handler(event_file, 0, IB_EVENT_DEVICE_FATAL, | |
32 | NULL, NULL); | |
3e032c0e JG |
33 | return 0; |
34 | } | |
35 | ||
c485b19d JG |
36 | int uverbs_async_event_release(struct inode *inode, struct file *filp) |
37 | { | |
38 | struct ib_uverbs_async_event_file *event_file; | |
39 | struct ib_uobject *uobj = filp->private_data; | |
40 | int ret; | |
41 | ||
42 | if (!uobj) | |
43 | return uverbs_uobject_fd_release(inode, filp); | |
44 | ||
45 | event_file = | |
46 | container_of(uobj, struct ib_uverbs_async_event_file, uobj); | |
47 | ||
48 | /* | |
49 | * The async event FD has to deliver IB_EVENT_DEVICE_FATAL even after | |
50 | * disassociation, so cleaning the event list must only happen after | |
51 | * release. The user knows it has reached the end of the event stream | |
52 | * when it sees IB_EVENT_DEVICE_FATAL. | |
53 | */ | |
54 | uverbs_uobject_get(uobj); | |
55 | ret = uverbs_uobject_fd_release(inode, filp); | |
56 | ib_uverbs_free_event_queue(&event_file->ev_queue); | |
57 | uverbs_uobject_put(uobj); | |
58 | return ret; | |
59 | } | |
60 | ||
d680e88e JG |
61 | DECLARE_UVERBS_NAMED_METHOD( |
62 | UVERBS_METHOD_ASYNC_EVENT_ALLOC, | |
63 | UVERBS_ATTR_FD(UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE, | |
64 | UVERBS_OBJECT_ASYNC_EVENT, | |
65 | UVERBS_ACCESS_NEW, | |
66 | UA_MANDATORY)); | |
67 | ||
3e032c0e JG |
68 | DECLARE_UVERBS_NAMED_OBJECT( |
69 | UVERBS_OBJECT_ASYNC_EVENT, | |
70 | UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_async_event_file), | |
71 | uverbs_async_event_destroy_uobj, | |
72 | &uverbs_async_event_fops, | |
73 | "[infinibandevent]", | |
d680e88e JG |
74 | O_RDONLY), |
75 | &UVERBS_METHOD(UVERBS_METHOD_ASYNC_EVENT_ALLOC)); | |
3e032c0e JG |
76 | |
77 | const struct uapi_definition uverbs_def_obj_async_fd[] = { | |
78 | UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_ASYNC_EVENT), | |
79 | {} | |
80 | }; |