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 | 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 | 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 | 59 | const struct uverbs_object_spec_hash *objects; |
| 60 | 60 | int ret = uverbs_ns_idx(&object, object_hash->num_buckets); |
| 61 | 61 | |
| @@ -44,7 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | #include <linux/mutex.h> |
| 45 | 45 | |
| 46 | 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 | 48 | uint16_t object); |
| 49 | 49 | const struct uverbs_method_spec *uverbs_get_method(const struct uverbs_object_spec *object, |
| 50 | 50 | uint16_t method); |
| @@ -46,8 +46,7 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr, · 45 unmodified lines | ||
| 46 | 46 | 0, uattr->len - len); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | −static int uverbs_process_attr(struct ib_device *ibdev, | |
| 50 | − struct ib_ucontext *ucontext, | |
| 49 | +static int uverbs_process_attr(struct ib_uverbs_file *ufile, | |
| 51 | 50 | const struct ib_uverbs_attr *uattr, |
| 52 | 51 | u16 attr_id, |
| 53 | 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 | 144 | if (uattr->attr_data.reserved) |
| 146 | 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 | 149 | return -EINVAL; |
| 150 | 150 | |
| 151 | 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 | 153 | if (!object) |
| 154 | 154 | return -EINVAL; |
| 155 | 155 | |
| 156 | 156 | o_attr->uobject = uverbs_get_uobject_from_context( |
| 157 | 157 | object->type_attrs, |
| 158 | − ucontext, | |
| 158 | + ufile->ucontext, | |
| 159 | 159 | spec->obj.access, |
| 160 | 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 | 230 | return ret; |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | −static int uverbs_uattrs_process(struct ib_device *ibdev, | |
| 234 | − struct ib_ucontext *ucontext, | |
| 233 | +static int uverbs_uattrs_process(struct ib_uverbs_file *ufile, | |
| 235 | 234 | const struct ib_uverbs_attr *uattrs, |
| 236 | 235 | size_t num_uattrs, |
| 237 | 236 | const struct uverbs_method_spec *method, |
| @@ -267,9 +266,9 @@ static int uverbs_uattrs_process(struct ib_device *ibdev, · 29 unmodified lines | ||
| 267 | 266 | num_given_buckets = ret + 1; |
| 268 | 267 | |
| 269 | 268 | attr_spec_bucket = method->attr_buckets[ret]; |
| 270 | − ret = uverbs_process_attr(ibdev, ucontext, uattr, attr_id, | |
| 271 | − attr_spec_bucket, &attr_bundle->hash[ret], | |
| 272 | − uattr_ptr++); | |
| 269 | + ret = uverbs_process_attr(ufile, uattr, attr_id, | |
| 270 | + attr_spec_bucket, | |
| 271 | + &attr_bundle->hash[ret], uattr_ptr++); | |
| 273 | 272 | if (ret) { |
| 274 | 273 | uverbs_finalize_attrs(attr_bundle, |
| 275 | 274 | method->attr_buckets, |
| @@ -324,9 +323,8 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr, · 48 unmodified lines | ||
| 324 | 323 | int finalize_ret; |
| 325 | 324 | int num_given_buckets; |
| 326 | 325 | |
| 327 | − num_given_buckets = uverbs_uattrs_process(ibdev, ufile->ucontext, uattrs, | |
| 328 | − num_uattrs, method_spec, | |
| 329 | − attr_bundle, uattr_ptr); | |
| 326 | + num_given_buckets = uverbs_uattrs_process( | |
| 327 | + ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr); | |
| 330 | 328 | if (num_given_buckets <= 0) |
| 331 | 329 | return -EINVAL; |
| 332 | 330 | |
| @@ -367,7 +365,7 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev, · 34 unmodified lines | ||
| 367 | 365 | if (hdr->driver_id != ib_dev->driver_id) |
| 368 | 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 | 369 | if (!object_spec) |
| 372 | 370 | return -EPROTONOSUPPORT; |
| 373 | 371 | |
| @@ -161,6 +161,7 @@ static void ib_uverbs_release_dev(struct kobject *kobj) · 160 unmodified lines | ||
| 161 | 161 | container_of(kobj, struct ib_uverbs_device, kobj); |
| 162 | 162 | |
| 163 | 163 | cleanup_srcu_struct(&dev->disassociate_srcu); |
| 164 | + uverbs_free_spec_tree(dev->specs_root); | |
| 164 | 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 | 1068 | if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) |
| 1068 | 1069 | goto err_class; |
| 1069 | 1070 | |
| 1070 | − if (!device->specs_root) { | |
| 1071 | + if (!device->driver_specs_root) { | |
| 1071 | 1072 | const struct uverbs_object_tree_def *default_root[] = { |
| 1072 | 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 | 1076 | default_root); |
| 1076 | 1077 | if (IS_ERR(uverbs_dev->specs_root)) |
| 1077 | 1078 | goto err_class; |
| 1078 | − | |
| 1079 | − device->specs_root = uverbs_dev->specs_root; | |
| 1079 | + } else { | |
| 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 | 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 | 1247 | ib_uverbs_comp_dev(uverbs_dev); |
| 1242 | 1248 | if (wait_clients) |
| 1243 | 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 | 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 | 5350 | !WARN_ON(num_trees >= ARRAY_SIZE(default_root))) |
| 5351 | 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 | 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 | 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 | 5364 | static int mlx5_ib_read_counters(struct ib_counters *counters, |
| @@ -2602,7 +2602,7 @@ struct ib_device { · 2601 unmodified lines | ||
| 2602 | 2602 | const struct cpumask *(*get_vector_affinity)(struct ib_device *ibdev, |
| 2603 | 2603 | int comp_vector); |
| 2604 | 2604 | |
| 2605 | − struct uverbs_root_spec *specs_root; | |
| 2605 | + struct uverbs_root_spec *driver_specs_root; | |
| 2606 | 2606 | enum rdma_driver_id driver_id; |
| 2607 | 2607 | }; |
| 2608 | 2608 | |