Merge tag 'chrome-platform-for-linus-4.17' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-block.git] / include / rdma / uverbs_ioctl.h
CommitLineData
a0aa309c
MB
1/*
2 * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#ifndef _UVERBS_IOCTL_
34#define _UVERBS_IOCTL_
35
36#include <rdma/uverbs_types.h>
35410306
MB
37#include <linux/uaccess.h>
38#include <rdma/rdma_user_ioctl.h>
d70724f1 39#include <rdma/ib_user_ioctl_verbs.h>
1f7ff9d5 40#include <rdma/ib_user_ioctl_cmds.h>
a0aa309c
MB
41
42/*
43 * =======================================
44 * Verbs action specifications
45 * =======================================
46 */
47
f43dbebf
MB
48enum uverbs_attr_type {
49 UVERBS_ATTR_TYPE_NA,
fac9658c
MB
50 UVERBS_ATTR_TYPE_PTR_IN,
51 UVERBS_ATTR_TYPE_PTR_OUT,
f43dbebf
MB
52 UVERBS_ATTR_TYPE_IDR,
53 UVERBS_ATTR_TYPE_FD,
494c5580 54 UVERBS_ATTR_TYPE_ENUM_IN,
f43dbebf
MB
55};
56
a0aa309c
MB
57enum uverbs_obj_access {
58 UVERBS_ACCESS_READ,
59 UVERBS_ACCESS_WRITE,
60 UVERBS_ACCESS_NEW,
61 UVERBS_ACCESS_DESTROY
62};
63
fac9658c
MB
64enum {
65 UVERBS_ATTR_SPEC_F_MANDATORY = 1U << 0,
c66db311
MB
66 /* Support extending attributes by length, validate all unknown size == zero */
67 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
fac9658c
MB
68};
69
1f07e08f 70/* Specification of a single attribute inside the ioctl message */
f43dbebf 71struct uverbs_attr_spec {
fac9658c 72 union {
1f07e08f 73 /* Header shared by all following union members - to reduce space. */
fac9658c 74 struct {
1f07e08f
MB
75 enum uverbs_attr_type type;
76 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
77 u8 flags;
78 };
79 struct {
80 enum uverbs_attr_type type;
81 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
82 u8 flags;
c66db311 83 /* Current known size to kernel */
1f07e08f 84 u16 len;
c66db311
MB
85 /* User isn't allowed to provide something < min_len */
86 u16 min_len;
1f07e08f
MB
87 } ptr;
88 struct {
89 enum uverbs_attr_type type;
90 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
91 u8 flags;
fac9658c
MB
92 /*
93 * higher bits mean the namespace and lower bits mean
94 * the type id within the namespace.
95 */
96 u16 obj_type;
97 u8 access;
98 } obj;
494c5580
MB
99 struct {
100 enum uverbs_attr_type type;
101 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
102 u8 flags;
103 u8 num_elems;
104 /*
105 * The enum attribute can select one of the attributes
106 * contained in the ids array. Currently only PTR_IN
107 * attributes are supported in the ids array.
108 */
109 const struct uverbs_attr_spec *ids;
110 } enum_def;
fac9658c 111 };
f43dbebf
MB
112};
113
114struct uverbs_attr_spec_hash {
115 size_t num_attrs;
fac9658c 116 unsigned long *mandatory_attrs_bitmask;
f43dbebf
MB
117 struct uverbs_attr_spec attrs[0];
118};
119
fac9658c
MB
120struct uverbs_attr_bundle;
121struct ib_uverbs_file;
122
123enum {
124 /*
125 * Action marked with this flag creates a context (or root for all
126 * objects).
127 */
128 UVERBS_ACTION_FLAG_CREATE_ROOT = 1U << 0,
129};
130
131struct uverbs_method_spec {
132 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
133 u32 flags;
134 size_t num_buckets;
135 size_t num_child_attrs;
136 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
137 struct uverbs_attr_bundle *ctx);
138 struct uverbs_attr_spec_hash *attr_buckets[0];
139};
140
141struct uverbs_method_spec_hash {
142 size_t num_methods;
143 struct uverbs_method_spec *methods[0];
144};
145
146struct uverbs_object_spec {
147 const struct uverbs_obj_type *type_attrs;
148 size_t num_buckets;
149 struct uverbs_method_spec_hash *method_buckets[0];
150};
151
152struct uverbs_object_spec_hash {
153 size_t num_objects;
154 struct uverbs_object_spec *objects[0];
155};
156
157struct uverbs_root_spec {
158 size_t num_buckets;
159 struct uverbs_object_spec_hash *object_buckets[0];
160};
161
5009010f
MB
162/*
163 * =======================================
164 * Verbs definitions
165 * =======================================
166 */
167
09e3ebf8
MB
168struct uverbs_attr_def {
169 u16 id;
170 struct uverbs_attr_spec attr;
171};
172
173struct uverbs_method_def {
174 u16 id;
175 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
176 u32 flags;
177 size_t num_attrs;
178 const struct uverbs_attr_def * const (*attrs)[];
179 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
180 struct uverbs_attr_bundle *ctx);
181};
182
5009010f 183struct uverbs_object_def {
09e3ebf8 184 u16 id;
5009010f 185 const struct uverbs_obj_type *type_attrs;
09e3ebf8
MB
186 size_t num_methods;
187 const struct uverbs_method_def * const (*methods)[];
188};
189
190struct uverbs_object_tree_def {
191 size_t num_objects;
192 const struct uverbs_object_def * const (*objects)[];
5009010f
MB
193};
194
35410306 195#define UA_FLAGS(_flags) .flags = _flags
c66db311 196#define __UVERBS_ATTR0(_id, _type, _fld, _attr, ...) \
35410306 197 ((const struct uverbs_attr_def) \
c66db311
MB
198 {.id = _id, .attr = {{._fld = {.type = _type, _attr, .flags = 0, } }, } })
199#define __UVERBS_ATTR1(_id, _type, _fld, _attr, _extra1, ...) \
35410306 200 ((const struct uverbs_attr_def) \
c66db311
MB
201 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1 } },} })
202#define __UVERBS_ATTR2(_id, _type, _fld, _attr, _extra1, _extra2) \
203 ((const struct uverbs_attr_def) \
204 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1, _extra2 } },} })
205#define __UVERBS_ATTR(_id, _type, _fld, _attr, _extra1, _extra2, _n, ...) \
206 __UVERBS_ATTR##_n(_id, _type, _fld, _attr, _extra1, _extra2)
207
208#define UVERBS_ATTR_TYPE(_type) \
209 .min_len = sizeof(_type), .len = sizeof(_type)
210#define UVERBS_ATTR_STRUCT(_type, _last) \
211 .min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .len = sizeof(_type)
212#define UVERBS_ATTR_SIZE(_min_len, _len) \
213 .min_len = _min_len, .len = _len
214
35410306
MB
215/*
216 * In new compiler, UVERBS_ATTR could be simplified by declaring it as
217 * [_id] = {.type = _type, .len = _len, ##__VA_ARGS__}
218 * But since we support older compilers too, we need the more complex code.
219 */
c66db311
MB
220#define UVERBS_ATTR(_id, _type, _fld, _attr, ...) \
221 __UVERBS_ATTR(_id, _type, _fld, _attr, ##__VA_ARGS__, 2, 1, 0)
35410306 222#define UVERBS_ATTR_PTR_IN_SZ(_id, _len, ...) \
c66db311 223 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_IN, ptr, _len, ##__VA_ARGS__)
35410306
MB
224/* If sizeof(_type) <= sizeof(u64), this will be inlined rather than a pointer */
225#define UVERBS_ATTR_PTR_IN(_id, _type, ...) \
c66db311 226 UVERBS_ATTR_PTR_IN_SZ(_id, _type, ##__VA_ARGS__)
35410306 227#define UVERBS_ATTR_PTR_OUT_SZ(_id, _len, ...) \
c66db311 228 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_OUT, ptr, _len, ##__VA_ARGS__)
35410306 229#define UVERBS_ATTR_PTR_OUT(_id, _type, ...) \
c66db311 230 UVERBS_ATTR_PTR_OUT_SZ(_id, _type, ##__VA_ARGS__)
494c5580
MB
231#define UVERBS_ATTR_ENUM_IN(_id, _enum_arr, ...) \
232 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_ENUM_IN, enum_def, \
233 .ids = (_enum_arr), \
234 .num_elems = ARRAY_SIZE(_enum_arr), ##__VA_ARGS__)
35410306
MB
235
236/*
237 * In new compiler, UVERBS_ATTR_IDR (and FD) could be simplified by declaring
238 * it as
239 * {.id = _id, \
240 * .attr {.type = __obj_class, \
241 * .obj = {.obj_type = _idr_type, \
242 * .access = _access \
243 * }, ##__VA_ARGS__ } }
244 * But since we support older compilers too, we need the more complex code.
245 */
246#define ___UVERBS_ATTR_OBJ0(_id, _obj_class, _obj_type, _access, ...)\
247 ((const struct uverbs_attr_def) \
248 {.id = _id, \
1f07e08f
MB
249 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
250 .access = _access, .flags = 0 } }, } })
35410306
MB
251#define ___UVERBS_ATTR_OBJ1(_id, _obj_class, _obj_type, _access, _flags)\
252 ((const struct uverbs_attr_def) \
253 {.id = _id, \
1f07e08f
MB
254 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
255 .access = _access, _flags} }, } })
35410306
MB
256#define ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, _flags, \
257 _n, ...) \
258 ___UVERBS_ATTR_OBJ##_n(_id, _obj_class, _obj_type, _access, _flags)
259#define __UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, ...) \
260 ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, \
261 ##__VA_ARGS__, 1, 0)
262#define UVERBS_ATTR_IDR(_id, _idr_type, _access, ...) \
263 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_IDR, _idr_type, _access,\
264 ##__VA_ARGS__)
265#define UVERBS_ATTR_FD(_id, _fd_type, _access, ...) \
266 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_FD, _fd_type, \
267 (_access) + BUILD_BUG_ON_ZERO( \
268 (_access) != UVERBS_ACCESS_NEW && \
269 (_access) != UVERBS_ACCESS_READ), \
270 ##__VA_ARGS__)
271#define DECLARE_UVERBS_ATTR_SPEC(_name, ...) \
272 const struct uverbs_attr_def _name = __VA_ARGS__
273
494c5580
MB
274#define DECLARE_UVERBS_ENUM(_name, ...) \
275 const struct uverbs_enum_spec _name = { \
276 .len = ARRAY_SIZE(((struct uverbs_attr_spec[]){__VA_ARGS__})),\
277 .ids = {__VA_ARGS__}, \
278 }
35410306
MB
279#define _UVERBS_METHOD_ATTRS_SZ(...) \
280 (sizeof((const struct uverbs_attr_def * const []){__VA_ARGS__}) /\
281 sizeof(const struct uverbs_attr_def *))
282#define _UVERBS_METHOD(_id, _handler, _flags, ...) \
283 ((const struct uverbs_method_def) { \
284 .id = _id, \
285 .flags = _flags, \
286 .handler = _handler, \
287 .num_attrs = _UVERBS_METHOD_ATTRS_SZ(__VA_ARGS__), \
288 .attrs = &(const struct uverbs_attr_def * const []){__VA_ARGS__} })
289#define DECLARE_UVERBS_METHOD(_name, _id, _handler, ...) \
290 const struct uverbs_method_def _name = \
291 _UVERBS_METHOD(_id, _handler, 0, ##__VA_ARGS__)
292#define DECLARE_UVERBS_CTX_METHOD(_name, _id, _handler, _flags, ...) \
293 const struct uverbs_method_def _name = \
294 _UVERBS_METHOD(_id, _handler, \
295 UVERBS_ACTION_FLAG_CREATE_ROOT, \
296 ##__VA_ARGS__)
297#define _UVERBS_OBJECT_METHODS_SZ(...) \
298 (sizeof((const struct uverbs_method_def * const []){__VA_ARGS__}) / \
299 sizeof(const struct uverbs_method_def *))
5009010f
MB
300#define _UVERBS_OBJECT(_id, _type_attrs, ...) \
301 ((const struct uverbs_object_def) { \
09e3ebf8 302 .id = _id, \
35410306
MB
303 .type_attrs = _type_attrs, \
304 .num_methods = _UVERBS_OBJECT_METHODS_SZ(__VA_ARGS__), \
305 .methods = &(const struct uverbs_method_def * const []){__VA_ARGS__} })
5009010f
MB
306#define DECLARE_UVERBS_OBJECT(_name, _id, _type_attrs, ...) \
307 const struct uverbs_object_def _name = \
308 _UVERBS_OBJECT(_id, _type_attrs, ##__VA_ARGS__)
09e3ebf8
MB
309#define _UVERBS_TREE_OBJECTS_SZ(...) \
310 (sizeof((const struct uverbs_object_def * const []){__VA_ARGS__}) / \
311 sizeof(const struct uverbs_object_def *))
312#define _UVERBS_OBJECT_TREE(...) \
313 ((const struct uverbs_object_tree_def) { \
314 .num_objects = _UVERBS_TREE_OBJECTS_SZ(__VA_ARGS__), \
315 .objects = &(const struct uverbs_object_def * const []){__VA_ARGS__} })
316#define DECLARE_UVERBS_OBJECT_TREE(_name, ...) \
317 const struct uverbs_object_tree_def _name = \
318 _UVERBS_OBJECT_TREE(__VA_ARGS__)
319
fac9658c
MB
320/* =================================================
321 * Parsing infrastructure
322 * =================================================
323 */
324
325struct uverbs_ptr_attr {
2f36028c 326 u64 data;
fac9658c
MB
327 u16 len;
328 /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
329 u16 flags;
494c5580 330 u8 enum_id;
fac9658c
MB
331};
332
f43dbebf 333struct uverbs_obj_attr {
fac9658c
MB
334 /* pointer to the kernel descriptor -> type, access, etc */
335 const struct uverbs_obj_type *type;
f43dbebf 336 struct ib_uobject *uobject;
fac9658c
MB
337 /* fd or id in idr of this object */
338 int id;
f43dbebf
MB
339};
340
341struct uverbs_attr {
fac9658c
MB
342 /*
343 * pointer to the user-space given attribute, in order to write the
344 * new uobject's id or update flags.
345 */
346 struct ib_uverbs_attr __user *uattr;
347 union {
348 struct uverbs_ptr_attr ptr_attr;
349 struct uverbs_obj_attr obj_attr;
350 };
f43dbebf
MB
351};
352
353struct uverbs_attr_bundle_hash {
354 /* if bit i is set, it means attrs[i] contains valid information */
355 unsigned long *valid_bitmap;
356 size_t num_attrs;
357 /*
358 * arrays of attributes, each element corresponds to the specification
359 * of the attribute in the same index.
360 */
361 struct uverbs_attr *attrs;
362};
363
364struct uverbs_attr_bundle {
365 size_t num_buckets;
366 struct uverbs_attr_bundle_hash hash[];
367};
368
369static inline bool uverbs_attr_is_valid_in_hash(const struct uverbs_attr_bundle_hash *attrs_hash,
370 unsigned int idx)
371{
372 return test_bit(idx, attrs_hash->valid_bitmap);
373}
374
35410306
MB
375static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
376 unsigned int idx)
377{
378 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
379
380 if (attrs_bundle->num_buckets <= idx_bucket)
381 return false;
382
383 return uverbs_attr_is_valid_in_hash(&attrs_bundle->hash[idx_bucket],
384 idx & ~UVERBS_ID_NS_MASK);
385}
386
41b2a71f
MB
387#define IS_UVERBS_COPY_ERR(_ret) ((_ret) && (_ret) != -ENOENT)
388
d70724f1
MB
389static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
390 u16 idx)
391{
392 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
393
394 if (!uverbs_attr_is_valid(attrs_bundle, idx))
395 return ERR_PTR(-ENOENT);
396
397 return &attrs_bundle->hash[idx_bucket].attrs[idx & ~UVERBS_ID_NS_MASK];
398}
399
494c5580
MB
400static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
401 u16 idx)
402{
403 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
404
405 if (IS_ERR(attr))
406 return PTR_ERR(attr);
407
408 return attr->ptr_attr.enum_id;
409}
410
be934cca
AL
411static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
412 u16 idx)
413{
414 struct ib_uobject *uobj =
415 uverbs_attr_get(attrs_bundle, idx)->obj_attr.uobject;
416
417 if (IS_ERR(uobj))
418 return uobj;
419
420 return uobj->object;
421}
422
d70724f1 423static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
89d9e8d3 424 size_t idx, const void *from, size_t size)
d70724f1
MB
425{
426 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
427 u16 flags;
89d9e8d3 428 size_t min_size;
d70724f1
MB
429
430 if (IS_ERR(attr))
431 return PTR_ERR(attr);
432
89d9e8d3 433 min_size = min_t(size_t, attr->ptr_attr.len, size);
2f36028c 434 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
89d9e8d3
MB
435 return -EFAULT;
436
d70724f1 437 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
89d9e8d3
MB
438 if (put_user(flags, &attr->uattr->flags))
439 return -EFAULT;
440
441 return 0;
d70724f1
MB
442}
443
89d9e8d3
MB
444static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
445{
446 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
447}
448
449static inline int _uverbs_copy_from(void *to,
d70724f1 450 const struct uverbs_attr_bundle *attrs_bundle,
89d9e8d3
MB
451 size_t idx,
452 size_t size)
d70724f1
MB
453{
454 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
455
456 if (IS_ERR(attr))
457 return PTR_ERR(attr);
458
89d9e8d3
MB
459 /*
460 * Validation ensures attr->ptr_attr.len >= size. If the caller is
c66db311
MB
461 * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
462 * uverbs_copy_from_or_zero.
89d9e8d3
MB
463 */
464 if (unlikely(size < attr->ptr_attr.len))
465 return -EINVAL;
466
467 if (uverbs_attr_ptr_is_inline(attr))
d70724f1 468 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
2f36028c
JG
469 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
470 attr->ptr_attr.len))
d70724f1
MB
471 return -EFAULT;
472
473 return 0;
474}
475
c66db311
MB
476static inline int _uverbs_copy_from_or_zero(void *to,
477 const struct uverbs_attr_bundle *attrs_bundle,
478 size_t idx,
479 size_t size)
480{
481 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
482 size_t min_size;
483
484 if (IS_ERR(attr))
485 return PTR_ERR(attr);
486
487 min_size = min_t(size_t, size, attr->ptr_attr.len);
488
489 if (uverbs_attr_ptr_is_inline(attr))
490 memcpy(to, &attr->ptr_attr.data, min_size);
491 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
492 min_size))
493 return -EFAULT;
494
495 if (size > min_size)
496 memset(to + min_size, 0, size - min_size);
497
498 return 0;
499}
500
d70724f1 501#define uverbs_copy_from(to, attrs_bundle, idx) \
89d9e8d3 502 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
d70724f1 503
c66db311
MB
504#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
505 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
506
118620d3
MB
507/* =================================================
508 * Definitions -> Specs infrastructure
509 * =================================================
510 */
511
512/*
513 * uverbs_alloc_spec_tree - Merges different common and driver specific feature
514 * into one parsing tree that every uverbs command will be parsed upon.
515 *
516 * @num_trees: Number of trees in the array @trees.
517 * @trees: Array of pointers to tree root definitions to merge. Each such tree
518 * possibly contains objects, methods and attributes definitions.
519 *
520 * Returns:
521 * uverbs_root_spec *: The root of the merged parsing tree.
522 * On error, we return an error code. Error is checked via IS_ERR.
523 *
524 * The following merges could take place:
525 * a. Two trees representing the same method with different handler
526 * -> We take the handler of the tree that its handler != NULL
527 * and its index in the trees array is greater. The incentive for that
528 * is that developers are expected to first merge common trees and then
529 * merge trees that gives specialized the behaviour.
530 * b. Two trees representing the same object with different
531 * type_attrs (struct uverbs_obj_type):
532 * -> We take the type_attrs of the tree that its type_attr != NULL
533 * and its index in the trees array is greater. This could be used
534 * in order to override the free function, allocation size, etc.
535 * c. Two trees representing the same method attribute (same id but possibly
536 * different attributes):
537 * -> ERROR (-ENOENT), we believe that's not the programmer's intent.
538 *
539 * An object without any methods is considered invalid and will abort the
540 * function with -ENOENT error.
541 */
52427112 542#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
118620d3
MB
543struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
544 const struct uverbs_object_tree_def **trees);
545void uverbs_free_spec_tree(struct uverbs_root_spec *root);
52427112
MB
546#else
547static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
548 const struct uverbs_object_tree_def **trees)
549{
550 return NULL;
551}
552
553static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
554{
555}
556#endif
a0aa309c 557
118620d3 558#endif