linux/include/rdma/uverbs_ioctl.h
<<
>>
Prefs
   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>
  37#include <linux/uaccess.h>
  38#include <rdma/rdma_user_ioctl.h>
  39#include <rdma/ib_user_ioctl_verbs.h>
  40#include <rdma/ib_user_ioctl_cmds.h>
  41
  42/*
  43 * =======================================
  44 *      Verbs action specifications
  45 * =======================================
  46 */
  47
  48enum uverbs_attr_type {
  49        UVERBS_ATTR_TYPE_NA,
  50        UVERBS_ATTR_TYPE_PTR_IN,
  51        UVERBS_ATTR_TYPE_PTR_OUT,
  52        UVERBS_ATTR_TYPE_IDR,
  53        UVERBS_ATTR_TYPE_FD,
  54        UVERBS_ATTR_TYPE_ENUM_IN,
  55};
  56
  57enum uverbs_obj_access {
  58        UVERBS_ACCESS_READ,
  59        UVERBS_ACCESS_WRITE,
  60        UVERBS_ACCESS_NEW,
  61        UVERBS_ACCESS_DESTROY
  62};
  63
  64enum {
  65        UVERBS_ATTR_SPEC_F_MANDATORY    = 1U << 0,
  66        /* Support extending attributes by length, validate all unknown size == zero  */
  67        UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
  68};
  69
  70/* Specification of a single attribute inside the ioctl message */
  71struct uverbs_attr_spec {
  72        union {
  73                /* Header shared by all following union members - to reduce space. */
  74                struct {
  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;
  83                        /* Current known size to kernel */
  84                        u16                             len;
  85                        /* User isn't allowed to provide something < min_len */
  86                        u16                             min_len;
  87                } ptr;
  88                struct {
  89                        enum uverbs_attr_type           type;
  90                        /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
  91                        u8                              flags;
  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;
  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;
 111        };
 112};
 113
 114struct uverbs_attr_spec_hash {
 115        size_t                          num_attrs;
 116        unsigned long                   *mandatory_attrs_bitmask;
 117        struct uverbs_attr_spec         attrs[0];
 118};
 119
 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
 162/*
 163 * =======================================
 164 *      Verbs definitions
 165 * =======================================
 166 */
 167
 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
 183struct uverbs_object_def {
 184        u16                                      id;
 185        const struct uverbs_obj_type            *type_attrs;
 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)[];
 193};
 194
 195#define UA_FLAGS(_flags)  .flags = _flags
 196#define __UVERBS_ATTR0(_id, _type, _fld, _attr, ...)              \
 197        ((const struct uverbs_attr_def)                           \
 198         {.id = _id, .attr = {{._fld = {.type = _type, _attr, .flags = 0, } }, } })
 199#define __UVERBS_ATTR1(_id, _type, _fld, _attr, _extra1, ...)      \
 200        ((const struct uverbs_attr_def)                           \
 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
 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 */
 220#define UVERBS_ATTR(_id, _type, _fld, _attr, ...)                       \
 221        __UVERBS_ATTR(_id, _type, _fld, _attr, ##__VA_ARGS__, 2, 1, 0)
 222#define UVERBS_ATTR_PTR_IN_SZ(_id, _len, ...)                           \
 223        UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_IN, ptr, _len, ##__VA_ARGS__)
 224/* If sizeof(_type) <= sizeof(u64), this will be inlined rather than a pointer */
 225#define UVERBS_ATTR_PTR_IN(_id, _type, ...)                             \
 226        UVERBS_ATTR_PTR_IN_SZ(_id, _type, ##__VA_ARGS__)
 227#define UVERBS_ATTR_PTR_OUT_SZ(_id, _len, ...)                          \
 228        UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_OUT, ptr, _len, ##__VA_ARGS__)
 229#define UVERBS_ATTR_PTR_OUT(_id, _type, ...)                            \
 230        UVERBS_ATTR_PTR_OUT_SZ(_id, _type, ##__VA_ARGS__)
 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__)
 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,                                                     \
 249         .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type,  \
 250                            .access = _access, .flags = 0 } }, } })
 251#define ___UVERBS_ATTR_OBJ1(_id, _obj_class, _obj_type, _access, _flags)\
 252        ((const struct uverbs_attr_def)                                 \
 253        {.id = _id,                                                     \
 254        .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type,   \
 255                           .access = _access, _flags} }, } })
 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
 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        }
 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 *))
 300#define _UVERBS_OBJECT(_id, _type_attrs, ...)                           \
 301        ((const struct uverbs_object_def) {                             \
 302         .id = _id,                                                     \
 303         .type_attrs = _type_attrs,                                     \
 304         .num_methods = _UVERBS_OBJECT_METHODS_SZ(__VA_ARGS__),         \
 305         .methods = &(const struct uverbs_method_def * const []){__VA_ARGS__} })
 306#define DECLARE_UVERBS_OBJECT(_name, _id, _type_attrs, ...)             \
 307        const struct uverbs_object_def _name =                          \
 308                _UVERBS_OBJECT(_id, _type_attrs, ##__VA_ARGS__)
 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
 320/* =================================================
 321 *              Parsing infrastructure
 322 * =================================================
 323 */
 324
 325struct uverbs_ptr_attr {
 326        u64             data;
 327        u16             len;
 328        /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
 329        u16             flags;
 330        u8              enum_id;
 331};
 332
 333struct uverbs_obj_attr {
 334        /* pointer to the kernel descriptor -> type, access, etc */
 335        const struct uverbs_obj_type    *type;
 336        struct ib_uobject               *uobject;
 337        /* fd or id in idr of this object */
 338        int                             id;
 339};
 340
 341struct uverbs_attr {
 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        };
 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
 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
 387#define IS_UVERBS_COPY_ERR(_ret)                ((_ret) && (_ret) != -ENOENT)
 388
 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
 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
 411static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
 412                                        u16 idx)
 413{
 414        const struct uverbs_attr *attr;
 415
 416        attr = uverbs_attr_get(attrs_bundle, idx);
 417        if (IS_ERR(attr))
 418                return ERR_CAST(attr);
 419
 420        return attr->obj_attr.uobject->object;
 421}
 422
 423static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
 424                                                         u16 idx)
 425{
 426        const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
 427
 428        if (IS_ERR(attr))
 429                return ERR_CAST(attr);
 430
 431        return attr->obj_attr.uobject;
 432}
 433
 434static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
 435                                 size_t idx, const void *from, size_t size)
 436{
 437        const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
 438        u16 flags;
 439        size_t min_size;
 440
 441        if (IS_ERR(attr))
 442                return PTR_ERR(attr);
 443
 444        min_size = min_t(size_t, attr->ptr_attr.len, size);
 445        if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
 446                return -EFAULT;
 447
 448        flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
 449        if (put_user(flags, &attr->uattr->flags))
 450                return -EFAULT;
 451
 452        return 0;
 453}
 454
 455static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
 456{
 457        return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
 458}
 459
 460static inline int _uverbs_copy_from(void *to,
 461                                    const struct uverbs_attr_bundle *attrs_bundle,
 462                                    size_t idx,
 463                                    size_t size)
 464{
 465        const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
 466
 467        if (IS_ERR(attr))
 468                return PTR_ERR(attr);
 469
 470        /*
 471         * Validation ensures attr->ptr_attr.len >= size. If the caller is
 472         * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
 473         * uverbs_copy_from_or_zero.
 474         */
 475        if (unlikely(size < attr->ptr_attr.len))
 476                return -EINVAL;
 477
 478        if (uverbs_attr_ptr_is_inline(attr))
 479                memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
 480        else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
 481                                attr->ptr_attr.len))
 482                return -EFAULT;
 483
 484        return 0;
 485}
 486
 487static inline int _uverbs_copy_from_or_zero(void *to,
 488                                            const struct uverbs_attr_bundle *attrs_bundle,
 489                                            size_t idx,
 490                                            size_t size)
 491{
 492        const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
 493        size_t min_size;
 494
 495        if (IS_ERR(attr))
 496                return PTR_ERR(attr);
 497
 498        min_size = min_t(size_t, size, attr->ptr_attr.len);
 499
 500        if (uverbs_attr_ptr_is_inline(attr))
 501                memcpy(to, &attr->ptr_attr.data, min_size);
 502        else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
 503                                min_size))
 504                return -EFAULT;
 505
 506        if (size > min_size)
 507                memset(to + min_size, 0, size - min_size);
 508
 509        return 0;
 510}
 511
 512#define uverbs_copy_from(to, attrs_bundle, idx)                               \
 513        _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
 514
 515#define uverbs_copy_from_or_zero(to, attrs_bundle, idx)                       \
 516        _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
 517
 518/* =================================================
 519 *       Definitions -> Specs infrastructure
 520 * =================================================
 521 */
 522
 523/*
 524 * uverbs_alloc_spec_tree - Merges different common and driver specific feature
 525 *      into one parsing tree that every uverbs command will be parsed upon.
 526 *
 527 * @num_trees: Number of trees in the array @trees.
 528 * @trees: Array of pointers to tree root definitions to merge. Each such tree
 529 *         possibly contains objects, methods and attributes definitions.
 530 *
 531 * Returns:
 532 *      uverbs_root_spec *: The root of the merged parsing tree.
 533 *      On error, we return an error code. Error is checked via IS_ERR.
 534 *
 535 * The following merges could take place:
 536 * a. Two trees representing the same method with different handler
 537 *      -> We take the handler of the tree that its handler != NULL
 538 *         and its index in the trees array is greater. The incentive for that
 539 *         is that developers are expected to first merge common trees and then
 540 *         merge trees that gives specialized the behaviour.
 541 * b. Two trees representing the same object with different
 542 *    type_attrs (struct uverbs_obj_type):
 543 *      -> We take the type_attrs of the tree that its type_attr != NULL
 544 *         and its index in the trees array is greater. This could be used
 545 *         in order to override the free function, allocation size, etc.
 546 * c. Two trees representing the same method attribute (same id but possibly
 547 *    different attributes):
 548 *      -> ERROR (-ENOENT), we believe that's not the programmer's intent.
 549 *
 550 * An object without any methods is considered invalid and will abort the
 551 * function with -ENOENT error.
 552 */
 553#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
 554struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
 555                                                const struct uverbs_object_tree_def **trees);
 556void uverbs_free_spec_tree(struct uverbs_root_spec *root);
 557#else
 558static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
 559                                                              const struct uverbs_object_tree_def **trees)
 560{
 561        return NULL;
 562}
 563
 564static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
 565{
 566}
 567#endif
 568
 569#endif
 570