Commit | Line | Data |
---|---|---|
6bf9d8f6 | 1 | /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ |
38321256 MB |
2 | /* |
3 | * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. | |
38321256 MB |
4 | */ |
5 | ||
6 | #ifndef _UVERBS_TYPES_ | |
7 | #define _UVERBS_TYPES_ | |
8 | ||
9 | #include <linux/kernel.h> | |
10 | #include <rdma/ib_verbs.h> | |
11 | ||
12 | struct uverbs_obj_type; | |
6b0d08f4 | 13 | struct uverbs_api_object; |
38321256 | 14 | |
9867f5c6 JG |
15 | enum rdma_lookup_mode { |
16 | UVERBS_LOOKUP_READ, | |
17 | UVERBS_LOOKUP_WRITE, | |
7452a3c7 JG |
18 | /* |
19 | * Destroy is like LOOKUP_WRITE, except that the uobject is not | |
20 | * locked. uobj_destroy is used to convert a LOOKUP_DESTROY lock into | |
21 | * a LOOKUP_WRITE lock. | |
22 | */ | |
23 | UVERBS_LOOKUP_DESTROY, | |
9867f5c6 JG |
24 | }; |
25 | ||
87ad80ab JG |
26 | /* |
27 | * The following sequences are valid: | |
28 | * Success flow: | |
29 | * alloc_begin | |
30 | * alloc_commit | |
31 | * [..] | |
32 | * Access flow: | |
33 | * lookup_get(exclusive=false) & uverbs_try_lock_object | |
34 | * lookup_put(exclusive=false) via rdma_lookup_put_uobject | |
35 | * Destruction flow: | |
36 | * lookup_get(exclusive=true) & uverbs_try_lock_object | |
37 | * remove_commit | |
0f50d88a | 38 | * remove_handle (optional) |
87ad80ab JG |
39 | * lookup_put(exclusive=true) via rdma_lookup_put_uobject |
40 | * | |
41 | * Allocate Error flow #1 | |
42 | * alloc_begin | |
43 | * alloc_abort | |
44 | * Allocate Error flow #2 | |
45 | * alloc_begin | |
46 | * remove_commit | |
47 | * alloc_abort | |
48 | * Allocate Error flow #3 | |
49 | * alloc_begin | |
50 | * alloc_commit (fails) | |
51 | * remove_commit | |
52 | * alloc_abort | |
53 | * | |
54 | * In all cases the caller must hold the ufile kref until alloc_commit or | |
55 | * alloc_abort returns. | |
56 | */ | |
38321256 | 57 | struct uverbs_obj_type_class { |
6b0d08f4 | 58 | struct ib_uobject *(*alloc_begin)(const struct uverbs_api_object *obj, |
39e83af8 | 59 | struct uverbs_attr_bundle *attrs); |
87ad80ab | 60 | /* This consumes the kref on uobj */ |
849e1490 | 61 | void (*alloc_commit)(struct ib_uobject *uobj); |
87ad80ab | 62 | /* This does not consume the kref on uobj */ |
38321256 MB |
63 | void (*alloc_abort)(struct ib_uobject *uobj); |
64 | ||
6b0d08f4 | 65 | struct ib_uobject *(*lookup_get)(const struct uverbs_api_object *obj, |
1250c304 | 66 | struct ib_uverbs_file *ufile, s64 id, |
9867f5c6 JG |
67 | enum rdma_lookup_mode mode); |
68 | void (*lookup_put)(struct ib_uobject *uobj, enum rdma_lookup_mode mode); | |
87ad80ab | 69 | /* This does not consume the kref on uobj */ |
0f50d88a | 70 | int __must_check (*destroy_hw)(struct ib_uobject *uobj, |
a6a3797d SR |
71 | enum rdma_remove_reason why, |
72 | struct uverbs_attr_bundle *attrs); | |
0f50d88a | 73 | void (*remove_handle)(struct ib_uobject *uobj); |
6e0954b1 JG |
74 | void (*swap_uobjects)(struct ib_uobject *obj_old, |
75 | struct ib_uobject *obj_new); | |
38321256 MB |
76 | }; |
77 | ||
78 | struct uverbs_obj_type { | |
79 | const struct uverbs_obj_type_class * const type_class; | |
80 | size_t obj_size; | |
38321256 MB |
81 | }; |
82 | ||
83 | /* | |
84 | * Objects type classes which support a detach state (object is still alive but | |
85 | * it's not attached to any context need to make sure: | |
86 | * (a) no call through to a driver after a detach is called | |
87 | * (b) detach isn't called concurrently with context_cleanup | |
88 | */ | |
89 | ||
90 | struct uverbs_obj_idr_type { | |
91 | /* | |
92 | * In idr based objects, uverbs_obj_type_class points to a generic | |
93 | * idr operations. In order to specialize the underlying types (e.g. CQ, | |
94 | * QPs, etc.), we add destroy_object specific callbacks. | |
95 | */ | |
96 | struct uverbs_obj_type type; | |
97 | ||
98 | /* Free driver resources from the uobject, make the driver uncallable, | |
99 | * and move the uobject to the detached state. If the object was | |
100 | * destroyed by the user's request, a failure should leave the uobject | |
101 | * completely unchanged. | |
102 | */ | |
103 | int __must_check (*destroy_object)(struct ib_uobject *uobj, | |
a6a3797d SR |
104 | enum rdma_remove_reason why, |
105 | struct uverbs_attr_bundle *attrs); | |
38321256 MB |
106 | }; |
107 | ||
6b0d08f4 | 108 | struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_api_object *obj, |
9867f5c6 | 109 | struct ib_uverbs_file *ufile, s64 id, |
70f06b26 SR |
110 | enum rdma_lookup_mode mode, |
111 | struct uverbs_attr_bundle *attrs); | |
9867f5c6 JG |
112 | void rdma_lookup_put_uobject(struct ib_uobject *uobj, |
113 | enum rdma_lookup_mode mode); | |
6b0d08f4 | 114 | struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_api_object *obj, |
70f06b26 | 115 | struct uverbs_attr_bundle *attrs); |
a6a3797d | 116 | void rdma_alloc_abort_uobject(struct ib_uobject *uobj, |
0ac8903c JG |
117 | struct uverbs_attr_bundle *attrs, |
118 | bool hw_obj_valid); | |
849e1490 JG |
119 | void rdma_alloc_commit_uobject(struct ib_uobject *uobj, |
120 | struct uverbs_attr_bundle *attrs); | |
6e0954b1 JG |
121 | void rdma_assign_uobject(struct ib_uobject *to_uobj, |
122 | struct ib_uobject *new_uobj, | |
123 | struct uverbs_attr_bundle *attrs); | |
38321256 | 124 | |
6898d1c6 JG |
125 | /* |
126 | * uverbs_uobject_get is called in order to increase the reference count on | |
127 | * an uobject. This is useful when a handler wants to keep the uobject's memory | |
128 | * alive, regardless if this uobject is still alive in the context's objects | |
129 | * repository. Objects are put via uverbs_uobject_put. | |
130 | */ | |
131 | static inline void uverbs_uobject_get(struct ib_uobject *uobject) | |
132 | { | |
133 | kref_get(&uobject->ref); | |
134 | } | |
135 | void uverbs_uobject_put(struct ib_uobject *uobject); | |
136 | ||
cf8966b3 MB |
137 | struct uverbs_obj_fd_type { |
138 | /* | |
139 | * In fd based objects, uverbs_obj_type_ops points to generic | |
140 | * fd operations. In order to specialize the underlying types (e.g. | |
141 | * completion_channel), we use fops, name and flags for fd creation. | |
f7c8416c JG |
142 | * destroy_object is called when the uobject is to be destroyed, |
143 | * because the driver is removed or the FD is closed. | |
cf8966b3 MB |
144 | */ |
145 | struct uverbs_obj_type type; | |
c5633a72 LR |
146 | void (*destroy_object)(struct ib_uobject *uobj, |
147 | enum rdma_remove_reason why); | |
cf8966b3 MB |
148 | const struct file_operations *fops; |
149 | const char *name; | |
150 | int flags; | |
151 | }; | |
152 | ||
6be60aed | 153 | extern const struct uverbs_obj_type_class uverbs_idr_class; |
1e7710f3 | 154 | extern const struct uverbs_obj_type_class uverbs_fd_class; |
f7c8416c | 155 | int uverbs_uobject_fd_release(struct inode *inode, struct file *filp); |
6be60aed MB |
156 | |
157 | #define UVERBS_BUILD_BUG_ON(cond) (sizeof(char[1 - 2 * !!(cond)]) - \ | |
158 | sizeof(char)) | |
f7c8416c | 159 | #define UVERBS_TYPE_ALLOC_FD(_obj_size, _destroy_object, _fops, _name, _flags) \ |
5009010f MB |
160 | ((&((const struct uverbs_obj_fd_type) \ |
161 | {.type = { \ | |
5009010f MB |
162 | .type_class = &uverbs_fd_class, \ |
163 | .obj_size = (_obj_size) + \ | |
d0259e82 JG |
164 | UVERBS_BUILD_BUG_ON((_obj_size) < \ |
165 | sizeof(struct ib_uobject)), \ | |
5009010f | 166 | }, \ |
f7c8416c | 167 | .destroy_object = _destroy_object, \ |
5009010f MB |
168 | .fops = _fops, \ |
169 | .name = _name, \ | |
170 | .flags = _flags}))->type) | |
1c77483e | 171 | #define UVERBS_TYPE_ALLOC_IDR_SZ(_size, _destroy_object) \ |
5009010f MB |
172 | ((&((const struct uverbs_obj_idr_type) \ |
173 | {.type = { \ | |
6be60aed MB |
174 | .type_class = &uverbs_idr_class, \ |
175 | .obj_size = (_size) + \ | |
5009010f MB |
176 | UVERBS_BUILD_BUG_ON((_size) < \ |
177 | sizeof(struct ib_uobject)) \ | |
178 | }, \ | |
179 | .destroy_object = _destroy_object,}))->type) | |
1c77483e YH |
180 | #define UVERBS_TYPE_ALLOC_IDR(_destroy_object) \ |
181 | UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uobject), \ | |
5009010f MB |
182 | _destroy_object) |
183 | ||
38321256 | 184 | #endif |