Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cbf432d authored by Jason Gunthorpe's avatar Jason Gunthorpe
Browse files

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: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent dfb631a1
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -152,8 +152,7 @@ uapi_get_object(struct uverbs_api *uapi, u16 object_id)
}

char *uapi_key_format(char *S, unsigned int key);
struct uverbs_api *uverbs_alloc_api(
	const struct uverbs_object_tree_def *const *driver_specs,
struct uverbs_api *uverbs_alloc_api(const struct uapi_definition *driver_def,
				    enum rdma_driver_id driver_id);
void uverbs_disassociate_api_pre(struct ib_uverbs_device *uverbs_dev);
void uverbs_disassociate_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);
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);

extern const struct uapi_definition uverbs_def_obj_intf[];

#endif /* RDMA_CORE_H */
+1 −1
Original line number Diff line number Diff line
@@ -1224,7 +1224,7 @@ static int ib_uverbs_create_uapi(struct ib_device *device,
{
	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))
		return PTR_ERR(uapi);

+19 −22
Original line number Diff line number Diff line
@@ -262,25 +262,22 @@ DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,

DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE);

DECLARE_UVERBS_OBJECT_TREE(uverbs_default_objects,
			   &UVERBS_OBJECT(UVERBS_OBJECT_DEVICE),
			   &UVERBS_OBJECT(UVERBS_OBJECT_PD),
			   &UVERBS_OBJECT(UVERBS_OBJECT_MR),
			   &UVERBS_OBJECT(UVERBS_OBJECT_COMP_CHANNEL),
			   &UVERBS_OBJECT(UVERBS_OBJECT_CQ),
			   &UVERBS_OBJECT(UVERBS_OBJECT_QP),
			   &UVERBS_OBJECT(UVERBS_OBJECT_AH),
			   &UVERBS_OBJECT(UVERBS_OBJECT_MW),
			   &UVERBS_OBJECT(UVERBS_OBJECT_SRQ),
			   &UVERBS_OBJECT(UVERBS_OBJECT_FLOW),
			   &UVERBS_OBJECT(UVERBS_OBJECT_WQ),
			   &UVERBS_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL),
			   &UVERBS_OBJECT(UVERBS_OBJECT_XRCD),
			   &UVERBS_OBJECT(UVERBS_OBJECT_FLOW_ACTION),
			   &UVERBS_OBJECT(UVERBS_OBJECT_DM),
			   &UVERBS_OBJECT(UVERBS_OBJECT_COUNTERS));

const struct uverbs_object_tree_def *uverbs_default_get_objects(void)
{
	return &uverbs_default_objects;
}
const struct uapi_definition uverbs_def_obj_intf[] = {
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MR),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_CQ),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_QP),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_AH),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_RWQ_IND_TBL),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_XRCD),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW_ACTION),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DM),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COUNTERS),
	{}
};
+84 −59
Original line number Diff line number Diff line
@@ -98,23 +98,14 @@ static int uapi_merge_method(struct uverbs_api *uapi,
	return 0;
}

static int uapi_merge_tree(struct uverbs_api *uapi,
			   const struct uverbs_object_tree_def *tree,
static int uapi_merge_obj_tree(struct uverbs_api *uapi,
			       const struct uverbs_object_def *obj,
			       bool is_driver)
{
	unsigned int i, j;
	int rc;

	if (!tree->objects)
		return 0;

	for (i = 0; i != tree->num_objects; i++) {
		const struct uverbs_object_def *obj = (*tree->objects)[i];
	struct uverbs_api_object *obj_elm;
	unsigned int i;
	u32 obj_key;

		if (!obj)
			continue;
	int rc;

	obj_key = uapi_key_obj(obj->id);
	obj_elm = uapi_add_elm(uapi, obj_key, sizeof(*obj_elm));
@@ -131,28 +122,25 @@ static int uapi_merge_tree(struct uverbs_api *uapi,
	} else {
		obj_elm->type_attrs = obj->type_attrs;
		if (obj->type_attrs) {
				obj_elm->type_class =
					obj->type_attrs->type_class;
			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.
			 * 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 !=
			if (WARN_ON(is_driver && obj->type_attrs->type_class !=
							 &uverbs_idr_class))
				return -EINVAL;
		}
	}

	if (!obj->methods)
			continue;
		return 0;

	for (i = 0; i != obj->num_methods; i++) {
		const struct uverbs_method_def *method = (*obj->methods)[i];

		for (j = 0; j != obj->num_methods; j++) {
			const struct uverbs_method_def *method =
				(*obj->methods)[j];
		if (!method)
			continue;

@@ -161,10 +149,46 @@ static int uapi_merge_tree(struct uverbs_api *uapi,
		if (rc)
			return rc;
	}

	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
uapi_finalize_ioctl_method(struct uverbs_api *uapi,
@@ -263,8 +287,12 @@ void uverbs_destroy_api(struct uverbs_api *uapi)
	kfree(uapi);
}

struct uverbs_api *uverbs_alloc_api(
	const struct uverbs_object_tree_def *const *driver_specs,
static const struct uapi_definition uverbs_core_api[] = {
	UAPI_DEF_CHAIN(uverbs_def_obj_intf),
	{},
};

struct uverbs_api *uverbs_alloc_api(const struct uapi_definition *driver_def,
				    enum rdma_driver_id driver_id)
{
	struct uverbs_api *uapi;
@@ -277,15 +305,12 @@ struct uverbs_api *uverbs_alloc_api(
	INIT_RADIX_TREE(&uapi->radix, GFP_KERNEL);
	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;

	for (; driver_specs && *driver_specs; driver_specs++) {
		rc = uapi_merge_tree(uapi, *driver_specs, true);
	rc = uapi_merge_def(uapi, driver_def, true);
	if (rc)
		goto err;
	}

	rc = uapi_finalize(uapi);
	if (rc)
+6 −9
Original line number Diff line number Diff line
@@ -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_DEREG));

DECLARE_UVERBS_OBJECT_TREE(devx_objects,
			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
			   &UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));

const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void)
{
	return &devx_objects;
}
const struct uapi_definition mlx5_ib_devx_defs[] = {
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX_OBJ),
	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_DEVX_UMEM),
	{},
};
Loading