RDMA/uverbs: Use a linear list to describe the compiled-in uapi

The 'tree' data structure is very hard to build at compile time, and this
makes it very limited. The new radix tree based compiler can handle a more
complex input language that does not require the compiler to perfectly
group everything into a neat tree structure.

Instead use a simple list to describe to input, where the list elements
can be of various different 'opcodes' instructing the radix compiler what
to do. Start out with opcodes chaining to other definition lists and
chaining to the existing 'tree' definition.

Replace the very top level of the 'object tree' with this list type and
get rid of struct uverbs_object_tree_def and DECLARE_UVERBS_OBJECT_TREE.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
This commit is contained in:
Jason Gunthorpe 2018-11-12 22:59:50 +02:00
parent dfb631a187
commit 0cbf432db4
12 changed files with 191 additions and 171 deletions

View File

@ -152,9 +152,8 @@ uapi_get_object(struct uverbs_api *uapi, u16 object_id)
} }
char *uapi_key_format(char *S, unsigned int key); char *uapi_key_format(char *S, unsigned int key);
struct uverbs_api *uverbs_alloc_api( struct uverbs_api *uverbs_alloc_api(const struct uapi_definition *driver_def,
const struct uverbs_object_tree_def *const *driver_specs, enum rdma_driver_id driver_id);
enum rdma_driver_id driver_id);
void uverbs_disassociate_api_pre(struct ib_uverbs_device *uverbs_dev); void uverbs_disassociate_api_pre(struct ib_uverbs_device *uverbs_dev);
void uverbs_disassociate_api(struct uverbs_api *uapi); void uverbs_disassociate_api(struct uverbs_api *uapi);
void uverbs_destroy_api(struct uverbs_api *uapi); void uverbs_destroy_api(struct uverbs_api *uapi);
@ -162,4 +161,6 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
unsigned int num_attrs); unsigned int num_attrs);
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile); void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);
extern const struct uapi_definition uverbs_def_obj_intf[];
#endif /* RDMA_CORE_H */ #endif /* RDMA_CORE_H */

View File

@ -1224,7 +1224,7 @@ static int ib_uverbs_create_uapi(struct ib_device *device,
{ {
struct uverbs_api *uapi; struct uverbs_api *uapi;
uapi = uverbs_alloc_api(device->driver_specs, device->driver_id); uapi = uverbs_alloc_api(device->driver_def, device->driver_id);
if (IS_ERR(uapi)) if (IS_ERR(uapi))
return PTR_ERR(uapi); return PTR_ERR(uapi);

View File

@ -262,25 +262,22 @@ DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,
DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE); DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE);
DECLARE_UVERBS_OBJECT_TREE(uverbs_default_objects, const struct uapi_definition uverbs_def_obj_intf[] = {
&UVERBS_OBJECT(UVERBS_OBJECT_DEVICE), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
&UVERBS_OBJECT(UVERBS_OBJECT_PD), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD),
&UVERBS_OBJECT(UVERBS_OBJECT_MR), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MR),
&UVERBS_OBJECT(UVERBS_OBJECT_COMP_CHANNEL), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL),
&UVERBS_OBJECT(UVERBS_OBJECT_CQ), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_CQ),
&UVERBS_OBJECT(UVERBS_OBJECT_QP), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_QP),
&UVERBS_OBJECT(UVERBS_OBJECT_AH), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_AH),
&UVERBS_OBJECT(UVERBS_OBJECT_MW), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW),
&UVERBS_OBJECT(UVERBS_OBJECT_SRQ), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ),
&UVERBS_OBJECT(UVERBS_OBJECT_FLOW), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW),
&UVERBS_OBJECT(UVERBS_OBJECT_WQ), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ),
&UVERBS_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_RWQ_IND_TBL),
&UVERBS_OBJECT(UVERBS_OBJECT_XRCD), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_XRCD),
&UVERBS_OBJECT(UVERBS_OBJECT_FLOW_ACTION), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW_ACTION),
&UVERBS_OBJECT(UVERBS_OBJECT_DM), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DM),
&UVERBS_OBJECT(UVERBS_OBJECT_COUNTERS)); UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COUNTERS),
{}
const struct uverbs_object_tree_def *uverbs_default_get_objects(void) };
{
return &uverbs_default_objects;
}

View File

@ -98,74 +98,98 @@ static int uapi_merge_method(struct uverbs_api *uapi,
return 0; return 0;
} }
static int uapi_merge_tree(struct uverbs_api *uapi, static int uapi_merge_obj_tree(struct uverbs_api *uapi,
const struct uverbs_object_tree_def *tree, const struct uverbs_object_def *obj,
bool is_driver) bool is_driver)
{ {
unsigned int i, j; struct uverbs_api_object *obj_elm;
unsigned int i;
u32 obj_key;
int rc; int rc;
if (!tree->objects) obj_key = uapi_key_obj(obj->id);
return 0; obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm));
if (IS_ERR(obj_elm)) {
if (obj_elm != ERR_PTR(-EEXIST))
return PTR_ERR(obj_elm);
for (i = 0; i != tree->num_objects; i++) { /* This occurs when a driver uses ADD_UVERBS_METHODS */
const struct uverbs_object_def *obj = (*tree->objects)[i]; if (WARN_ON(obj->type_attrs))
struct uverbs_api_object *obj_elm; return -EINVAL;
u32 obj_key; obj_elm = radix_tree_lookup(&uapi->radix, obj_key);
if (WARN_ON(!obj_elm))
if (!obj) return -EINVAL;
continue; } else {
obj_elm->type_attrs = obj->type_attrs;
obj_key = uapi_key_obj(obj->id); if (obj->type_attrs) {
obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm)); obj_elm->type_class = obj->type_attrs->type_class;
if (IS_ERR(obj_elm)) { /*
if (obj_elm != ERR_PTR(-EEXIST)) * Today drivers are only permitted to use idr_class
return PTR_ERR(obj_elm); * types. They cannot use FD types because we
* currently have no way to revoke the fops pointer
/* This occurs when a driver uses ADD_UVERBS_METHODS */ * after device disassociation.
if (WARN_ON(obj->type_attrs)) */
if (WARN_ON(is_driver && obj->type_attrs->type_class !=
&uverbs_idr_class))
return -EINVAL; return -EINVAL;
obj_elm = radix_tree_lookup(&uapi->radix, obj_key);
if (WARN_ON(!obj_elm))
return -EINVAL;
} else {
obj_elm->type_attrs = obj->type_attrs;
if (obj->type_attrs) {
obj_elm->type_class =
obj->type_attrs->type_class;
/*
* Today drivers are only permitted to use
* idr_class types. They cannot use FD types
* because we currently have no way to revoke
* the fops pointer after device
* disassociation.
*/
if (WARN_ON(is_driver &&
obj->type_attrs->type_class !=
&uverbs_idr_class))
return -EINVAL;
}
}
if (!obj->methods)
continue;
for (j = 0; j != obj->num_methods; j++) {
const struct uverbs_method_def *method =
(*obj->methods)[j];
if (!method)
continue;
rc = uapi_merge_method(uapi, obj_elm, obj_key, method,
is_driver);
if (rc)
return rc;
} }
} }
if (!obj->methods)
return 0;
for (i = 0; i != obj->num_methods; i++) {
const struct uverbs_method_def *method = (*obj->methods)[i];
if (!method)
continue;
rc = uapi_merge_method(uapi, obj_elm, obj_key, method,
is_driver);
if (rc)
return rc;
}
return 0; return 0;
} }
static int uapi_merge_def(struct uverbs_api *uapi,
const struct uapi_definition *def_list,
bool is_driver)
{
const struct uapi_definition *def = def_list;
int rc;
if (!def_list)
return 0;
for (;; def++) {
switch ((enum uapi_definition_kind)def->kind) {
case UAPI_DEF_CHAIN:
rc = uapi_merge_def(uapi, def->chain, is_driver);
if (rc)
return rc;
continue;
case UAPI_DEF_CHAIN_OBJ_TREE:
if (WARN_ON(def->object_start.object_id !=
def->chain_obj_tree->id))
return -EINVAL;
rc = uapi_merge_obj_tree(uapi, def->chain_obj_tree,
is_driver);
if (rc)
return rc;
continue;
case UAPI_DEF_END:
return 0;
}
WARN_ON(true);
return -EINVAL;
}
}
static int static int
uapi_finalize_ioctl_method(struct uverbs_api *uapi, uapi_finalize_ioctl_method(struct uverbs_api *uapi,
struct uverbs_api_ioctl_method *method_elm, struct uverbs_api_ioctl_method *method_elm,
@ -263,9 +287,13 @@ void uverbs_destroy_api(struct uverbs_api *uapi)
kfree(uapi); kfree(uapi);
} }
struct uverbs_api *uverbs_alloc_api( static const struct uapi_definition uverbs_core_api[] = {
const struct uverbs_object_tree_def *const *driver_specs, UAPI_DEF_CHAIN(uverbs_def_obj_intf),
enum rdma_driver_id driver_id) {},
};
struct uverbs_api *uverbs_alloc_api(const struct uapi_definition *driver_def,
enum rdma_driver_id driver_id)
{ {
struct uverbs_api *uapi; struct uverbs_api *uapi;
int rc; int rc;
@ -277,15 +305,12 @@ struct uverbs_api *uverbs_alloc_api(
INIT_RADIX_TREE(&uapi->radix, GFP_KERNEL); INIT_RADIX_TREE(&uapi->radix, GFP_KERNEL);
uapi->driver_id = driver_id; uapi->driver_id = driver_id;
rc = uapi_merge_tree(uapi, uverbs_default_get_objects(), false); rc = uapi_merge_def(uapi, uverbs_core_api, false);
if (rc)
goto err;
rc = uapi_merge_def(uapi, driver_def, true);
if (rc) if (rc)
goto err; goto err;
for (; driver_specs && *driver_specs; driver_specs++) {
rc = uapi_merge_tree(uapi, *driver_specs, true);
if (rc)
goto err;
}
rc = uapi_finalize(uapi); rc = uapi_finalize(uapi);
if (rc) if (rc)

View File

@ -1323,12 +1323,9 @@ DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG), &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG)); &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
DECLARE_UVERBS_OBJECT_TREE(devx_objects, const struct uapi_definition mlx5_ib_devx_defs[] = {
&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX),
&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ), UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX_OBJ),
&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM)); UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX_UMEM),
{},
const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void) };
{
return &devx_objects;
}

View File

@ -610,16 +610,10 @@ DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
&UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE), &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
&UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY)); &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
DECLARE_UVERBS_OBJECT_TREE(flow_objects, const struct uapi_definition mlx5_ib_flow_defs[] = {
&UVERBS_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER)); UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_FLOW_MATCHER),
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW, &mlx5_ib_fs),
int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root) UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
{ &mlx5_ib_flow_actions),
int i = 0; {},
};
root[i++] = &flow_objects;
root[i++] = &mlx5_ib_fs;
root[i++] = &mlx5_ib_flow_actions;
return i;
}

View File

@ -5550,23 +5550,34 @@ ADD_UVERBS_ATTRIBUTES_SIMPLE(
UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS, UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
enum mlx5_ib_uapi_flow_action_flags)); enum mlx5_ib_uapi_flow_action_flags));
static const struct uapi_definition mlx5_ib_defs[] = {
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
UAPI_DEF_CHAIN(mlx5_ib_flow_defs),
#endif
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
&mlx5_ib_flow_action),
UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_DM, &mlx5_ib_dm),
{}
};
static int populate_specs_root(struct mlx5_ib_dev *dev) static int populate_specs_root(struct mlx5_ib_dev *dev)
{ {
const struct uverbs_object_tree_def **trees = dev->driver_trees; struct uapi_definition *defs = dev->driver_defs;
size_t num_trees = 0;
trees[num_trees++] = &mlx5_ib_flow_action;
trees[num_trees++] = &mlx5_ib_dm;
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
if (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) & if (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &
MLX5_GENERAL_OBJ_TYPES_CAP_UCTX) MLX5_GENERAL_OBJ_TYPES_CAP_UCTX)
trees[num_trees++] = mlx5_ib_get_devx_tree(); *defs++ = (struct uapi_definition)UAPI_DEF_CHAIN(
mlx5_ib_devx_defs);
#endif
num_trees += mlx5_ib_get_flow_trees(trees + num_trees); *defs++ = (struct uapi_definition)UAPI_DEF_CHAIN(mlx5_ib_defs);
*defs++ = (struct uapi_definition){};
WARN_ON(defs - dev->driver_defs >= ARRAY_SIZE(dev->driver_defs));
WARN_ON(num_trees >= ARRAY_SIZE(dev->driver_trees)); if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))
trees[num_trees] = NULL; dev->ib_dev.driver_def = dev->driver_defs;
dev->ib_dev.driver_specs = trees;
return 0; return 0;
} }

View File

@ -891,7 +891,7 @@ struct mlx5_ib_pf_eq {
struct mlx5_ib_dev { struct mlx5_ib_dev {
struct ib_device ib_dev; struct ib_device ib_dev;
const struct uverbs_object_tree_def *driver_trees[7]; struct uapi_definition driver_defs[7];
struct mlx5_core_dev *mdev; struct mlx5_core_dev *mdev;
struct mlx5_roce roce[MLX5_MAX_PORTS]; struct mlx5_roce roce[MLX5_MAX_PORTS];
int num_ports; int num_ports;
@ -1264,29 +1264,23 @@ void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *dev,
int mlx5_ib_devx_create(struct mlx5_ib_dev *dev); int mlx5_ib_devx_create(struct mlx5_ib_dev *dev);
void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid); void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid);
const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void); const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void);
extern const struct uapi_definition mlx5_ib_devx_defs[];
extern const struct uapi_definition mlx5_ib_flow_defs[];
struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add( struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add(
struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher, struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
struct mlx5_flow_act *flow_act, void *cmd_in, int inlen, struct mlx5_flow_act *flow_act, void *cmd_in, int inlen,
int dest_id, int dest_type); int dest_id, int dest_type);
bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type); bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction); void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
#else #else
static inline int static inline int
mlx5_ib_devx_create(struct mlx5_ib_dev *dev) { return -EOPNOTSUPP; }; mlx5_ib_devx_create(struct mlx5_ib_dev *dev) { return -EOPNOTSUPP; };
static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) {} static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev, u16 uid) {}
static inline const struct uverbs_object_tree_def *
mlx5_ib_get_devx_tree(void) { return NULL; }
static inline bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, static inline bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id,
int *dest_type) int *dest_type)
{ {
return false; return false;
} }
static inline int
mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
{
return 0;
}
static inline void static inline void
mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction) mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
{ {

View File

@ -2600,7 +2600,7 @@ struct ib_device {
const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev, const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev,
int comp_vector); int comp_vector);
const struct uverbs_object_tree_def *const *driver_specs; const struct uapi_definition *driver_def;
enum rdma_driver_id driver_id; enum rdma_driver_id driver_id;
}; };

View File

@ -296,11 +296,43 @@ struct uverbs_object_def {
const struct uverbs_method_def * const (*methods)[]; const struct uverbs_method_def * const (*methods)[];
}; };
struct uverbs_object_tree_def { enum uapi_definition_kind {
size_t num_objects; UAPI_DEF_END = 0,
const struct uverbs_object_def * const (*objects)[]; UAPI_DEF_CHAIN_OBJ_TREE,
UAPI_DEF_CHAIN,
}; };
struct uapi_definition {
u8 kind;
union {
struct {
u16 object_id;
} object_start;
};
union {
const struct uapi_definition *chain;
const struct uverbs_object_def *chain_obj_tree;
};
};
/* Include another struct uapi_definition in this one */
#define UAPI_DEF_CHAIN(_def_var) \
{ \
.kind = UAPI_DEF_CHAIN, .chain = _def_var, \
}
/* Temporary until the tree base description is replaced */
#define UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, _object_ptr) \
{ \
.kind = UAPI_DEF_CHAIN_OBJ_TREE, \
.object_start = { .object_id = _object_enum }, \
.chain_obj_tree = _object_ptr, \
}
#define UAPI_DEF_CHAIN_OBJ_TREE_NAMED(_object_enum, ...) \
UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, &UVERBS_OBJECT(_object_enum)), \
##__VA_ARGS__
/* /*
* ======================================= * =======================================
* Attribute Specifications * Attribute Specifications
@ -438,21 +470,6 @@ struct uverbs_object_tree_def {
UVERBS_ATTR_MIN_SIZE(0), \ UVERBS_ATTR_MIN_SIZE(0), \
UA_OPTIONAL) UA_OPTIONAL)
/*
* =======================================
* Declaration helpers
* =======================================
*/
#define DECLARE_UVERBS_OBJECT_TREE(_name, ...) \
static const struct uverbs_object_def *const _name##_ptr[] = { \
__VA_ARGS__, \
}; \
static const struct uverbs_object_tree_def _name = { \
.num_objects = ARRAY_SIZE(_name##_ptr), \
.objects = &_name##_ptr, \
}
/* ================================================= /* =================================================
* Parsing infrastructure * Parsing infrastructure
* ================================================= * =================================================

View File

@ -102,18 +102,11 @@
#define ADD_UVERBS_METHODS(_name, _object_id, ...) \ #define ADD_UVERBS_METHODS(_name, _object_id, ...) \
static const struct uverbs_method_def *const UVERBS_OBJECT_METHODS( \ static const struct uverbs_method_def *const UVERBS_OBJECT_METHODS( \
_object_id)[] = { __VA_ARGS__ }; \ _object_id)[] = { __VA_ARGS__ }; \
static const struct uverbs_object_def _name##_struct = { \ static const struct uverbs_object_def _name = { \
.id = _object_id, \ .id = _object_id, \
.num_methods = ARRAY_SIZE(UVERBS_OBJECT_METHODS(_object_id)), \ .num_methods = ARRAY_SIZE(UVERBS_OBJECT_METHODS(_object_id)), \
.methods = &UVERBS_OBJECT_METHODS(_object_id) \ .methods = &UVERBS_OBJECT_METHODS(_object_id) \
}; \ };
static const struct uverbs_object_def *const _name##_ptrs[] = { \
&_name##_struct, \
}; \
static const struct uverbs_object_tree_def _name = { \
.num_objects = 1, \
.objects = &_name##_ptrs, \
}
/* Used by drivers to declare a complete parsing tree for a single method that /* Used by drivers to declare a complete parsing tree for a single method that
* differs only in having additional driver specific attributes. * differs only in having additional driver specific attributes.

View File

@ -37,15 +37,6 @@
#include <rdma/uverbs_ioctl.h> #include <rdma/uverbs_ioctl.h>
#include <rdma/ib_user_ioctl_verbs.h> #include <rdma/ib_user_ioctl_verbs.h>
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
const struct uverbs_object_tree_def *uverbs_default_get_objects(void);
#else
static inline const struct uverbs_object_tree_def *uverbs_default_get_objects(void)
{
return NULL;
}
#endif
/* Returns _id, or causes a compile error if _id is not a u32. /* Returns _id, or causes a compile error if _id is not a u32.
* *
* The uobj APIs should only be used with the write based uAPI to access * The uobj APIs should only be used with the write based uAPI to access