Commit 87fc2a62 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/uverbs: Store the specs_root in the struct ib_uverbs_device

The specs are required to operate the uverbs file, so they belong inside
the ib_uverbs_device, not inside the ib_device. The spec passed in the
ib_device is just a communication from the driver and should not be used
during runtime.

This also changes the lifetime of the spec memory to match the
ib_uverbs_device, however at this time the spec_root can still contain
driver pointers after disassociation, so it cannot be used if ib_dev is
NULL. This is preparation for another series.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Reviewed-by: default avatarMichael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 8193abb6
...@@ -52,10 +52,10 @@ int uverbs_ns_idx(u16 *id, unsigned int ns_count) ...@@ -52,10 +52,10 @@ int uverbs_ns_idx(u16 *id, unsigned int ns_count)
return ret; return ret;
} }
const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev, const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile,
uint16_t object) uint16_t object)
{ {
const struct uverbs_root_spec *object_hash = ibdev->specs_root; const struct uverbs_root_spec *object_hash = ufile->device->specs_root;
const struct uverbs_object_spec_hash *objects; const struct uverbs_object_spec_hash *objects;
int ret = uverbs_ns_idx(&object, object_hash->num_buckets); int ret = uverbs_ns_idx(&object, object_hash->num_buckets);
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
int uverbs_ns_idx(u16 *id, unsigned int ns_count); int uverbs_ns_idx(u16 *id, unsigned int ns_count);
const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev, const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile,
uint16_t object); uint16_t object);
const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object, const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object,
uint16_t method); uint16_t method);
......
...@@ -46,8 +46,7 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr, ...@@ -46,8 +46,7 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
0, uattr->len - len); 0, uattr->len - len);
} }
static int uverbs_process_attr(struct ib_device *ibdev, static int uverbs_process_attr(struct ib_uverbs_file *ufile,
struct ib_ucontext *ucontext,
const struct ib_uverbs_attr *uattr, const struct ib_uverbs_attr *uattr,
u16 attr_id, u16 attr_id,
const struct uverbs_attr_spec_hash *attr_spec_bucket, const struct uverbs_attr_spec_hash *attr_spec_bucket,
...@@ -145,17 +144,18 @@ static int uverbs_process_attr(struct ib_device *ibdev, ...@@ -145,17 +144,18 @@ static int uverbs_process_attr(struct ib_device *ibdev,
if (uattr->attr_data.reserved) if (uattr->attr_data.reserved)
return -EINVAL; return -EINVAL;
if (uattr->len != 0 || !ucontext || uattr->data > INT_MAX) if (uattr->len != 0 || !ufile->ucontext ||
uattr->data > INT_MAX)
return -EINVAL; return -EINVAL;
o_attr = &e->obj_attr; o_attr = &e->obj_attr;
object = uverbs_get_object(ibdev, spec->obj.obj_type); object = uverbs_get_object(ufile, spec->obj.obj_type);
if (!object) if (!object)
return -EINVAL; return -EINVAL;
o_attr->uobject = uverbs_get_uobject_from_context( o_attr->uobject = uverbs_get_uobject_from_context(
object->type_attrs, object->type_attrs,
ucontext, ufile->ucontext,
spec->obj.access, spec->obj.access,
(int)uattr->data); (int)uattr->data);
...@@ -230,8 +230,7 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle, ...@@ -230,8 +230,7 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
return ret; return ret;
} }
static int uverbs_uattrs_process(struct ib_device *ibdev, static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
struct ib_ucontext *ucontext,
const struct ib_uverbs_attr *uattrs, const struct ib_uverbs_attr *uattrs,
size_t num_uattrs, size_t num_uattrs,
const struct uverbs_method_spec *method, const struct uverbs_method_spec *method,
...@@ -267,9 +266,9 @@ static int uverbs_uattrs_process(struct ib_device *ibdev, ...@@ -267,9 +266,9 @@ static int uverbs_uattrs_process(struct ib_device *ibdev,
num_given_buckets = ret + 1; num_given_buckets = ret + 1;
attr_spec_bucket = method->attr_buckets[ret]; attr_spec_bucket = method->attr_buckets[ret];
ret = uverbs_process_attr(ibdev, ucontext, uattr, attr_id, ret = uverbs_process_attr(ufile, uattr, attr_id,
attr_spec_bucket, &attr_bundle->hash[ret], attr_spec_bucket,
uattr_ptr++); &attr_bundle->hash[ret], uattr_ptr++);
if (ret) { if (ret) {
uverbs_finalize_attrs(attr_bundle, uverbs_finalize_attrs(attr_bundle,
method->attr_buckets, method->attr_buckets,
...@@ -324,9 +323,8 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr, ...@@ -324,9 +323,8 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
int finalize_ret; int finalize_ret;
int num_given_buckets; int num_given_buckets;
num_given_buckets = uverbs_uattrs_process(ibdev, ufile->ucontext, uattrs, num_given_buckets = uverbs_uattrs_process(
num_uattrs, method_spec, ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr);
attr_bundle, uattr_ptr);
if (num_given_buckets <= 0) if (num_given_buckets <= 0)
return -EINVAL; return -EINVAL;
...@@ -367,7 +365,7 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev, ...@@ -367,7 +365,7 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev,
if (hdr->driver_id != ib_dev->driver_id) if (hdr->driver_id != ib_dev->driver_id)
return -EINVAL; return -EINVAL;
object_spec = uverbs_get_object(ib_dev, hdr->object_id); object_spec = uverbs_get_object(file, hdr->object_id);
if (!object_spec) if (!object_spec)
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
......
...@@ -161,6 +161,7 @@ static void ib_uverbs_release_dev(struct kobject *kobj) ...@@ -161,6 +161,7 @@ static void ib_uverbs_release_dev(struct kobject *kobj)
container_of(kobj, struct ib_uverbs_device, kobj); container_of(kobj, struct ib_uverbs_device, kobj);
cleanup_srcu_struct(&dev->disassociate_srcu); cleanup_srcu_struct(&dev->disassociate_srcu);
uverbs_free_spec_tree(dev->specs_root);
kfree(dev); kfree(dev);
} }
...@@ -1067,7 +1068,7 @@ static void ib_uverbs_add_one(struct ib_device *device) ...@@ -1067,7 +1068,7 @@ static void ib_uverbs_add_one(struct ib_device *device)
if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
goto err_class; goto err_class;
if (!device->specs_root) { if (!device->driver_specs_root) {
const struct uverbs_object_tree_def *default_root[] = { const struct uverbs_object_tree_def *default_root[] = {
uverbs_default_get_objects()}; uverbs_default_get_objects()};
...@@ -1075,8 +1076,13 @@ static void ib_uverbs_add_one(struct ib_device *device) ...@@ -1075,8 +1076,13 @@ static void ib_uverbs_add_one(struct ib_device *device)
default_root); default_root);
if (IS_ERR(uverbs_dev->specs_root)) if (IS_ERR(uverbs_dev->specs_root))
goto err_class; goto err_class;
} else {
device->specs_root = uverbs_dev->specs_root; uverbs_dev->specs_root = device->driver_specs_root;
/*
* Take responsibility to free the specs allocated by the
* driver.
*/
device->driver_specs_root = NULL;
} }
ib_set_client_data(device, &uverbs_client, uverbs_dev); ib_set_client_data(device, &uverbs_client, uverbs_dev);
...@@ -1241,10 +1247,6 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) ...@@ -1241,10 +1247,6 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
ib_uverbs_comp_dev(uverbs_dev); ib_uverbs_comp_dev(uverbs_dev);
if (wait_clients) if (wait_clients)
wait_for_completion(&uverbs_dev->comp); wait_for_completion(&uverbs_dev->comp);
if (uverbs_dev->specs_root) {
uverbs_free_spec_tree(uverbs_dev->specs_root);
device->specs_root = NULL;
}
kobject_put(&uverbs_dev->kobj); kobject_put(&uverbs_dev->kobj);
} }
......
...@@ -5350,15 +5350,15 @@ static int populate_specs_root(struct mlx5_ib_dev *dev) ...@@ -5350,15 +5350,15 @@ static int populate_specs_root(struct mlx5_ib_dev *dev)
!WARN_ON(num_trees >= ARRAY_SIZE(default_root))) !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
default_root[num_trees++] = mlx5_ib_get_devx_tree(); default_root[num_trees++] = mlx5_ib_get_devx_tree();
dev->ib_dev.specs_root = dev->ib_dev.driver_specs_root =
uverbs_alloc_spec_tree(num_trees, default_root); uverbs_alloc_spec_tree(num_trees, default_root);
return PTR_ERR_OR_ZERO(dev->ib_dev.specs_root); return PTR_ERR_OR_ZERO(dev->ib_dev.driver_specs_root);
} }
static void depopulate_specs_root(struct mlx5_ib_dev *dev) static void depopulate_specs_root(struct mlx5_ib_dev *dev)
{ {
uverbs_free_spec_tree(dev->ib_dev.specs_root); uverbs_free_spec_tree(dev->ib_dev.driver_specs_root);
} }
static int mlx5_ib_read_counters(struct ib_counters *counters, static int mlx5_ib_read_counters(struct ib_counters *counters,
......
...@@ -2602,7 +2602,7 @@ struct ib_device { ...@@ -2602,7 +2602,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);
struct uverbs_root_spec *specs_root; struct uverbs_root_spec *driver_specs_root;
enum rdma_driver_id driver_id; enum rdma_driver_id driver_id;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment