1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved.
5 #include <rdma/uverbs_ioctl.h>
6 #include <rdma/rdma_user_ioctl.h>
7 #include <linux/bitops.h>
11 static void *uapi_add_elm(struct uverbs_api
*uapi
, u32 key
, size_t alloc_size
)
16 if (key
== UVERBS_API_KEY_ERR
)
17 return ERR_PTR(-EOVERFLOW
);
19 elm
= kzalloc(alloc_size
, GFP_KERNEL
);
21 return ERR_PTR(-ENOMEM
);
22 rc
= radix_tree_insert(&uapi
->radix
, key
, elm
);
31 static int uapi_merge_method(struct uverbs_api
*uapi
,
32 struct uverbs_api_object
*obj_elm
, u32 obj_key
,
33 const struct uverbs_method_def
*method
,
36 u32 method_key
= obj_key
| uapi_key_ioctl_method(method
->id
);
37 struct uverbs_api_ioctl_method
*method_elm
;
43 method_elm
= uapi_add_elm(uapi
, method_key
, sizeof(*method_elm
));
44 if (IS_ERR(method_elm
)) {
45 if (method_elm
!= ERR_PTR(-EEXIST
))
46 return PTR_ERR(method_elm
);
49 * This occurs when a driver uses ADD_UVERBS_ATTRIBUTES_SIMPLE
51 if (WARN_ON(method
->handler
))
53 method_elm
= radix_tree_lookup(&uapi
->radix
, method_key
);
54 if (WARN_ON(!method_elm
))
57 WARN_ON(!method
->handler
);
58 rcu_assign_pointer(method_elm
->handler
, method
->handler
);
59 if (method
->handler
!= uverbs_destroy_def_handler
)
60 method_elm
->driver_method
= is_driver
;
63 for (i
= 0; i
!= method
->num_attrs
; i
++) {
64 const struct uverbs_attr_def
*attr
= (*method
->attrs
)[i
];
65 struct uverbs_api_attr
*attr_slot
;
71 * ENUM_IN contains the 'ids' pointer to the driver's .rodata,
72 * so if it is specified by a driver then it always makes this
73 * into a driver method.
75 if (attr
->attr
.type
== UVERBS_ATTR_TYPE_ENUM_IN
)
76 method_elm
->driver_method
|= is_driver
;
79 uapi_add_elm(uapi
, method_key
| uapi_key_attr(attr
->id
),
81 /* Attributes are not allowed to be modified by drivers */
82 if (IS_ERR(attr_slot
))
83 return PTR_ERR(attr_slot
);
85 attr_slot
->spec
= attr
->attr
;
91 static int uapi_merge_tree(struct uverbs_api
*uapi
,
92 const struct uverbs_object_tree_def
*tree
,
101 for (i
= 0; i
!= tree
->num_objects
; i
++) {
102 const struct uverbs_object_def
*obj
= (*tree
->objects
)[i
];
103 struct uverbs_api_object
*obj_elm
;
109 obj_key
= uapi_key_obj(obj
->id
);
110 obj_elm
= uapi_add_elm(uapi
, obj_key
, sizeof(*obj_elm
));
111 if (IS_ERR(obj_elm
)) {
112 if (obj_elm
!= ERR_PTR(-EEXIST
))
113 return PTR_ERR(obj_elm
);
115 /* This occurs when a driver uses ADD_UVERBS_METHODS */
116 if (WARN_ON(obj
->type_attrs
))
118 obj_elm
= radix_tree_lookup(&uapi
->radix
, obj_key
);
119 if (WARN_ON(!obj_elm
))
122 obj_elm
->type_attrs
= obj
->type_attrs
;
123 if (obj
->type_attrs
) {
124 obj_elm
->type_class
=
125 obj
->type_attrs
->type_class
;
127 * Today drivers are only permitted to use
128 * idr_class types. They cannot use FD types
129 * because we currently have no way to revoke
130 * the fops pointer after device
133 if (WARN_ON(is_driver
&&
134 obj
->type_attrs
->type_class
!=
143 for (j
= 0; j
!= obj
->num_methods
; j
++) {
144 const struct uverbs_method_def
*method
=
149 rc
= uapi_merge_method(uapi
, obj_elm
, obj_key
, method
,
160 uapi_finalize_ioctl_method(struct uverbs_api
*uapi
,
161 struct uverbs_api_ioctl_method
*method_elm
,
164 struct radix_tree_iter iter
;
165 unsigned int num_attrs
= 0;
166 unsigned int max_bkey
= 0;
167 bool single_uobj
= false;
170 method_elm
->destroy_bkey
= UVERBS_API_ATTR_BKEY_LEN
;
171 radix_tree_for_each_slot (slot
, &uapi
->radix
, &iter
,
172 uapi_key_attrs_start(method_key
)) {
173 struct uverbs_api_attr
*elm
=
174 rcu_dereference_protected(*slot
, true);
175 u32 attr_key
= iter
.index
& UVERBS_API_ATTR_KEY_MASK
;
176 u32 attr_bkey
= uapi_bkey_attr(attr_key
);
177 u8 type
= elm
->spec
.type
;
179 if (uapi_key_attr_to_method(iter
.index
) !=
180 uapi_key_attr_to_method(method_key
))
183 if (elm
->spec
.mandatory
)
184 __set_bit(attr_bkey
, method_elm
->attr_mandatory
);
186 if (type
== UVERBS_ATTR_TYPE_IDR
||
187 type
== UVERBS_ATTR_TYPE_FD
) {
188 u8 access
= elm
->spec
.u
.obj
.access
;
191 * Verbs specs may only have one NEW/DESTROY, we don't
192 * have the infrastructure to abort multiple NEW's or
193 * cope with multiple DESTROY failure.
195 if (access
== UVERBS_ACCESS_NEW
||
196 access
== UVERBS_ACCESS_DESTROY
) {
197 if (WARN_ON(single_uobj
))
201 if (WARN_ON(!elm
->spec
.mandatory
))
205 if (access
== UVERBS_ACCESS_DESTROY
)
206 method_elm
->destroy_bkey
= attr_bkey
;
209 max_bkey
= max(max_bkey
, attr_bkey
);
213 method_elm
->key_bitmap_len
= max_bkey
+ 1;
214 WARN_ON(method_elm
->key_bitmap_len
> UVERBS_API_ATTR_BKEY_LEN
);
216 uapi_compute_bundle_size(method_elm
, num_attrs
);
220 static int uapi_finalize(struct uverbs_api
*uapi
)
222 struct radix_tree_iter iter
;
226 radix_tree_for_each_slot (slot
, &uapi
->radix
, &iter
, 0) {
227 struct uverbs_api_ioctl_method
*method_elm
=
228 rcu_dereference_protected(*slot
, true);
230 if (uapi_key_is_ioctl_method(iter
.index
)) {
231 rc
= uapi_finalize_ioctl_method(uapi
, method_elm
,
241 void uverbs_destroy_api(struct uverbs_api
*uapi
)
243 struct radix_tree_iter iter
;
249 radix_tree_for_each_slot (slot
, &uapi
->radix
, &iter
, 0) {
250 kfree(rcu_dereference_protected(*slot
, true));
251 radix_tree_iter_delete(&uapi
->radix
, &iter
, slot
);
256 struct uverbs_api
*uverbs_alloc_api(
257 const struct uverbs_object_tree_def
*const *driver_specs
,
258 enum rdma_driver_id driver_id
)
260 struct uverbs_api
*uapi
;
263 uapi
= kzalloc(sizeof(*uapi
), GFP_KERNEL
);
265 return ERR_PTR(-ENOMEM
);
267 INIT_RADIX_TREE(&uapi
->radix
, GFP_KERNEL
);
268 uapi
->driver_id
= driver_id
;
270 rc
= uapi_merge_tree(uapi
, uverbs_default_get_objects(), false);
274 for (; driver_specs
&& *driver_specs
; driver_specs
++) {
275 rc
= uapi_merge_tree(uapi
, *driver_specs
, true);
280 rc
= uapi_finalize(uapi
);
287 pr_err("Setup of uverbs_api failed, kernel parsing tree description is not valid (%d)??\n",
290 uverbs_destroy_api(uapi
);
295 * The pre version is done before destroying the HW objects, it only blocks
296 * off method access. All methods that require the ib_dev or the module data
297 * must test one of these assignments prior to continuing.
299 void uverbs_disassociate_api_pre(struct ib_uverbs_device
*uverbs_dev
)
301 struct uverbs_api
*uapi
= uverbs_dev
->uapi
;
302 struct radix_tree_iter iter
;
305 rcu_assign_pointer(uverbs_dev
->ib_dev
, NULL
);
307 radix_tree_for_each_slot (slot
, &uapi
->radix
, &iter
, 0) {
308 if (uapi_key_is_ioctl_method(iter
.index
)) {
309 struct uverbs_api_ioctl_method
*method_elm
=
310 rcu_dereference_protected(*slot
, true);
312 if (method_elm
->driver_method
)
313 rcu_assign_pointer(method_elm
->handler
, NULL
);
317 synchronize_srcu(&uverbs_dev
->disassociate_srcu
);
321 * Called when a driver disassociates from the ib_uverbs_device. The
322 * assumption is that the driver module will unload after. Replace everything
323 * related to the driver with NULL as a safety measure.
325 void uverbs_disassociate_api(struct uverbs_api
*uapi
)
327 struct radix_tree_iter iter
;
330 radix_tree_for_each_slot (slot
, &uapi
->radix
, &iter
, 0) {
331 if (uapi_key_is_object(iter
.index
)) {
332 struct uverbs_api_object
*object_elm
=
333 rcu_dereference_protected(*slot
, true);
336 * Some type_attrs are in the driver module. We don't
337 * bother to keep track of which since there should be
338 * no use of this after disassociate.
340 object_elm
->type_attrs
= NULL
;
341 } else if (uapi_key_is_attr(iter
.index
)) {
342 struct uverbs_api_attr
*elm
=
343 rcu_dereference_protected(*slot
, true);
345 if (elm
->spec
.type
== UVERBS_ATTR_TYPE_ENUM_IN
)
346 elm
->spec
.u2
.enum_def
.ids
= NULL
;