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.
Unified · Split
| @@ -52,10 +52,10 @@ int uverbs_ns_idx(u16 *id, unsigned int ns_count) · 51 unmodified lines | |||
| 52 | return ret; | 52 | return ret; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev, | 55 | const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile, |
| 56 | uint16_t object) | 56 | uint16_t object) |
| 57 | { | 57 | { |
| 58 | const struct uverbs_root_spec *object_hash = ibdev->specs_root; | 58 | const struct uverbs_root_spec *object_hash = ufile->device->specs_root; |
| 59 | const struct uverbs_object_spec_hash *objects; | 59 | const struct uverbs_object_spec_hash *objects; |
| 60 | int ret = uverbs_ns_idx(&object, object_hash->num_buckets); | 60 | int ret = uverbs_ns_idx(&object, object_hash->num_buckets); |
| 61 | 61 | ||
| @@ -44,7 +44,7 @@ · 43 unmodified lines | |||
| 44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
| 45 | 45 | ||
| 46 | int uverbs_ns_idx(u16 *id, unsigned int ns_count); | 46 | int uverbs_ns_idx(u16 *id, unsigned int ns_count); |
| 47 | const struct uverbs_object_spec *uverbs_get_object(const struct ib_device *ibdev, | 47 | const struct uverbs_object_spec *uverbs_get_object(struct ib_uverbs_file *ufile, |
| 48 | uint16_t object); | 48 | uint16_t object); |
| 49 | const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object, | 49 | const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object, |
| 50 | uint16_t method); | 50 | uint16_t method); |
| @@ -46,8 +46,7 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr, · 45 unmodified lines | |||
| 46 | 0, uattr->len - len); | 46 | 0, uattr->len - len); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static int uverbs_process_attr(struct ib_device *ibdev, | 49 | static int uverbs_process_attr(struct ib_uverbs_file *ufile, |
| 50 | struct ib_ucontext *ucontext, | ||
| 51 | const struct ib_uverbs_attr *uattr, | 50 | const struct ib_uverbs_attr *uattr, |
| 52 | u16 attr_id, | 51 | u16 attr_id, |
| 53 | const struct uverbs_attr_spec_hash *attr_spec_bucket, | 52 | const struct uverbs_attr_spec_hash *attr_spec_bucket, |
| @@ -145,17 +144,18 @@ static int uverbs_process_attr(struct ib_device *ibdev, · 91 unmodified lines | |||
| 145 | if (uattr->attr_data.reserved) | 144 | if (uattr->attr_data.reserved) |
| 146 | return -EINVAL; | 145 | return -EINVAL; |
| 147 | 146 | ||
| 148 | if (uattr->len != 0 || !ucontext || uattr->data > INT_MAX) | 147 | if (uattr->len != 0 || !ufile->ucontext || |
| 148 | uattr->data > INT_MAX) | ||
| 149 | return -EINVAL; | 149 | return -EINVAL; |
| 150 | 150 | ||
| 151 | o_attr = &e->obj_attr; | 151 | o_attr = &e->obj_attr; |
| 152 | object = uverbs_get_object(ibdev, spec->obj.obj_type); | 152 | object = uverbs_get_object(ufile, spec->obj.obj_type); |
| 153 | if (!object) | 153 | if (!object) |
| 154 | return -EINVAL; | 154 | return -EINVAL; |
| 155 | 155 | ||
| 156 | o_attr->uobject = uverbs_get_uobject_from_context( | 156 | o_attr->uobject = uverbs_get_uobject_from_context( |
| 157 | object->type_attrs, | 157 | object->type_attrs, |
| 158 | ucontext, | 158 | ufile->ucontext, |
| 159 | spec->obj.access, | 159 | spec->obj.access, |
| 160 | (int)uattr->data); | 160 | (int)uattr->data); |
| 161 | 161 | ||
| @@ -230,8 +230,7 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle, · 68 unmodified lines | |||
| 230 | return ret; | 230 | return ret; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static int uverbs_uattrs_process(struct ib_device *ibdev, | 233 | static int uverbs_uattrs_process(struct ib_uverbs_file *ufile, |
| 234 | struct ib_ucontext *ucontext, | ||
| 235 | const struct ib_uverbs_attr *uattrs, | 234 | const struct ib_uverbs_attr *uattrs, |
| 236 | size_t num_uattrs, | 235 | size_t num_uattrs, |
| 237 | const struct uverbs_method_spec *method, | 236 | const struct uverbs_method_spec *method, |
| @@ -267,9 +266,9 @@ static int uverbs_uattrs_process(struct ib_device *ibdev, · 29 unmodified lines | |||
| 267 | num_given_buckets = ret + 1; | 266 | num_given_buckets = ret + 1; |
| 268 | 267 | ||
| 269 | attr_spec_bucket = method->attr_buckets[ret]; | 268 | attr_spec_bucket = method->attr_buckets[ret]; |
| 270 | ret = uverbs_process_attr(ibdev, ucontext, uattr, attr_id, | 269 | ret = uverbs_process_attr(ufile, uattr, attr_id, |
| 271 | attr_spec_bucket, &attr_bundle->hash[ret], | 270 | attr_spec_bucket, |
| 272 | uattr_ptr++); | 271 | &attr_bundle->hash[ret], uattr_ptr++); |
| 273 | if (ret) { | 272 | if (ret) { |
| 274 | uverbs_finalize_attrs(attr_bundle, | 273 | uverbs_finalize_attrs(attr_bundle, |
| 275 | method->attr_buckets, | 274 | method->attr_buckets, |
| @@ -324,9 +323,8 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr, · 48 unmodified lines | |||
| 324 | int finalize_ret; | 323 | int finalize_ret; |
| 325 | int num_given_buckets; | 324 | int num_given_buckets; |
| 326 | 325 | ||
| 327 | num_given_buckets = uverbs_uattrs_process(ibdev, ufile->ucontext, uattrs, | 326 | num_given_buckets = uverbs_uattrs_process( |
| 328 | num_uattrs, method_spec, | 327 | ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr); |
| 329 | attr_bundle, uattr_ptr); | ||
| 330 | if (num_given_buckets <= 0) | 328 | if (num_given_buckets <= 0) |
| 331 | return -EINVAL; | 329 | return -EINVAL; |
| 332 | 330 | ||
| @@ -367,7 +365,7 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev, · 34 unmodified lines | |||
| 367 | if (hdr->driver_id != ib_dev->driver_id) | 365 | if (hdr->driver_id != ib_dev->driver_id) |
| 368 | return -EINVAL; | 366 | return -EINVAL; |
| 369 | 367 | ||
| 370 | object_spec = uverbs_get_object(ib_dev, hdr->object_id); | 368 | object_spec = uverbs_get_object(file, hdr->object_id); |
| 371 | if (!object_spec) | 369 | if (!object_spec) |
| 372 | return -EPROTONOSUPPORT; | 370 | return -EPROTONOSUPPORT; |
| 373 | 371 | ||
| @@ -161,6 +161,7 @@ static void ib_uverbs_release_dev(struct kobject *kobj) · 160 unmodified lines | |||
| 161 | container_of(kobj, struct ib_uverbs_device, kobj); | 161 | container_of(kobj, struct ib_uverbs_device, kobj); |
| 162 | 162 | ||
| 163 | cleanup_srcu_struct(&dev->disassociate_srcu); | 163 | cleanup_srcu_struct(&dev->disassociate_srcu); |
| 164 | uverbs_free_spec_tree(dev->specs_root); | ||
| 164 | kfree(dev); | 165 | kfree(dev); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| @@ -1067,7 +1068,7 @@ static void ib_uverbs_add_one(struct ib_device *device) · 900 unmodified lines | |||
| 1067 | if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) | 1068 | if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) |
| 1068 | goto err_class; | 1069 | goto err_class; |
| 1069 | 1070 | ||
| 1070 | if (!device->specs_root) { | 1071 | if (!device->driver_specs_root) { |
| 1071 | const struct uverbs_object_tree_def *default_root[] = { | 1072 | const struct uverbs_object_tree_def *default_root[] = { |
| 1072 | uverbs_default_get_objects()}; | 1073 | uverbs_default_get_objects()}; |
| 1073 | 1074 | ||
| @@ -1075,8 +1076,13 @@ static void ib_uverbs_add_one(struct ib_device *device) · 1 unmodified line | |||
| 1075 | default_root); | 1076 | default_root); |
| 1076 | if (IS_ERR(uverbs_dev->specs_root)) | 1077 | if (IS_ERR(uverbs_dev->specs_root)) |
| 1077 | goto err_class; | 1078 | goto err_class; |
| 1078 | 1079 | } else { | |
| 1079 | device->specs_root = uverbs_dev->specs_root; | 1080 | uverbs_dev->specs_root = device->driver_specs_root; |
| 1081 | /* | ||
| 1082 | * Take responsibility to free the specs allocated by the | ||
| 1083 | * driver. | ||
| 1084 | */ | ||
| 1085 | device->driver_specs_root = NULL; | ||
| 1080 | } | 1086 | } |
| 1081 | 1087 | ||
| 1082 | ib_set_client_data(device, &uverbs_client, uverbs_dev); | 1088 | 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) · 158 unmodified lines | |||
| 1241 | ib_uverbs_comp_dev(uverbs_dev); | 1247 | ib_uverbs_comp_dev(uverbs_dev); |
| 1242 | if (wait_clients) | 1248 | if (wait_clients) |
| 1243 | wait_for_completion(&uverbs_dev->comp); | 1249 | wait_for_completion(&uverbs_dev->comp); |
| 1244 | if (uverbs_dev->specs_root) { | ||
| 1245 | uverbs_free_spec_tree(uverbs_dev->specs_root); | ||
| 1246 | device->specs_root = NULL; | ||
| 1247 | } | ||
| 1248 | 1250 | ||
| 1249 | kobject_put(&uverbs_dev->kobj); | 1251 | kobject_put(&uverbs_dev->kobj); |
| 1250 | } | 1252 | } |
| @@ -5350,15 +5350,15 @@ static int populate_specs_root(struct mlx5_ib_dev *dev) · 5349 unmodified lines | |||
| 5350 | !WARN_ON(num_trees >= ARRAY_SIZE(default_root))) | 5350 | !WARN_ON(num_trees >= ARRAY_SIZE(default_root))) |
| 5351 | default_root[num_trees++] = mlx5_ib_get_devx_tree(); | 5351 | default_root[num_trees++] = mlx5_ib_get_devx_tree(); |
| 5352 | 5352 | ||
| 5353 | dev->ib_dev.specs_root = | 5353 | dev->ib_dev.driver_specs_root = |
| 5354 | uverbs_alloc_spec_tree(num_trees, default_root); | 5354 | uverbs_alloc_spec_tree(num_trees, default_root); |
| 5355 | 5355 | ||
| 5356 | return PTR_ERR_OR_ZERO(dev->ib_dev.specs_root); | 5356 | return PTR_ERR_OR_ZERO(dev->ib_dev.driver_specs_root); |
| 5357 | } | 5357 | } |
| 5358 | 5358 | ||
| 5359 | static void depopulate_specs_root(struct mlx5_ib_dev *dev) | 5359 | static void depopulate_specs_root(struct mlx5_ib_dev *dev) |
| 5360 | { | 5360 | { |
| 5361 | uverbs_free_spec_tree(dev->ib_dev.specs_root); | 5361 | uverbs_free_spec_tree(dev->ib_dev.driver_specs_root); |
| 5362 | } | 5362 | } |
| 5363 | 5363 | ||
| 5364 | static int mlx5_ib_read_counters(struct ib_counters *counters, | 5364 | static int mlx5_ib_read_counters(struct ib_counters *counters, |
| @@ -2602,7 +2602,7 @@ struct ib_device { · 2601 unmodified lines | |||
| 2602 | const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev, | 2602 | const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev, |
| 2603 | int comp_vector); | 2603 | int comp_vector); |
| 2604 | 2604 | ||
| 2605 | struct uverbs_root_spec *specs_root; | 2605 | struct uverbs_root_spec *driver_specs_root; |
| 2606 | enum rdma_driver_id driver_id; | 2606 | enum rdma_driver_id driver_id; |
| 2607 | }; | 2607 | }; |
| 2608 | 2608 | ||