hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/vfio/mdev/mdev_core.c
....@@ -1,13 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Mediated device Core Driver
34 *
45 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
56 * Author: Neo Jia <cjia@nvidia.com>
67 * Kirti Wankhede <kwankhede@nvidia.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
118 */
129
1310 #include <linux/module.h>
....@@ -60,9 +57,9 @@
6057 }
6158 EXPORT_SYMBOL(mdev_from_dev);
6259
63
-uuid_le mdev_uuid(struct mdev_device *mdev)
60
+const guid_t *mdev_uuid(struct mdev_device *mdev)
6461 {
65
- return mdev->uuid;
62
+ return &mdev->uuid;
6663 }
6764 EXPORT_SYMBOL(mdev_uuid);
6865
....@@ -88,8 +85,7 @@
8885 put_device(dev);
8986 }
9087
91
-static
92
-inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
88
+static struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
9389 {
9490 if (parent)
9591 kref_get(&parent->ref);
....@@ -97,62 +93,41 @@
9793 return parent;
9894 }
9995
100
-static inline void mdev_put_parent(struct mdev_parent *parent)
96
+static void mdev_put_parent(struct mdev_parent *parent)
10197 {
10298 if (parent)
10399 kref_put(&parent->ref, mdev_release_parent);
104100 }
105101
106
-static int mdev_device_create_ops(struct kobject *kobj,
107
- struct mdev_device *mdev)
102
+/* Caller must hold parent unreg_sem read or write lock */
103
+static void mdev_device_remove_common(struct mdev_device *mdev)
108104 {
109
- struct mdev_parent *parent = mdev->parent;
105
+ struct mdev_parent *parent;
106
+ struct mdev_type *type;
110107 int ret;
111108
112
- ret = parent->ops->create(kobj, mdev);
113
- if (ret)
114
- return ret;
115
-
116
- ret = sysfs_create_groups(&mdev->dev.kobj,
117
- parent->ops->mdev_attr_groups);
118
- if (ret)
119
- parent->ops->remove(mdev);
120
-
121
- return ret;
122
-}
123
-
124
-/*
125
- * mdev_device_remove_ops gets called from sysfs's 'remove' and when parent
126
- * device is being unregistered from mdev device framework.
127
- * - 'force_remove' is set to 'false' when called from sysfs's 'remove' which
128
- * indicates that if the mdev device is active, used by VMM or userspace
129
- * application, vendor driver could return error then don't remove the device.
130
- * - 'force_remove' is set to 'true' when called from mdev_unregister_device()
131
- * which indicate that parent device is being removed from mdev device
132
- * framework so remove mdev device forcefully.
133
- */
134
-static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove)
135
-{
136
- struct mdev_parent *parent = mdev->parent;
137
- int ret;
138
-
139
- /*
140
- * Vendor driver can return error if VMM or userspace application is
141
- * using this mdev device.
142
- */
109
+ type = to_mdev_type(mdev->type_kobj);
110
+ mdev_remove_sysfs_files(&mdev->dev, type);
111
+ device_del(&mdev->dev);
112
+ parent = mdev->parent;
113
+ lockdep_assert_held(&parent->unreg_sem);
143114 ret = parent->ops->remove(mdev);
144
- if (ret && !force_remove)
145
- return -EBUSY;
115
+ if (ret)
116
+ dev_err(&mdev->dev, "Remove failed: err=%d\n", ret);
146117
147
- sysfs_remove_groups(&mdev->dev.kobj, parent->ops->mdev_attr_groups);
148
- return 0;
118
+ /* Balances with device_initialize() */
119
+ put_device(&mdev->dev);
120
+ mdev_put_parent(parent);
149121 }
150122
151123 static int mdev_device_remove_cb(struct device *dev, void *data)
152124 {
153
- if (dev_is_mdev(dev))
154
- mdev_device_remove(dev, true);
125
+ if (dev_is_mdev(dev)) {
126
+ struct mdev_device *mdev;
155127
128
+ mdev = to_mdev_device(dev);
129
+ mdev_device_remove_common(mdev);
130
+ }
156131 return 0;
157132 }
158133
....@@ -168,6 +143,8 @@
168143 {
169144 int ret;
170145 struct mdev_parent *parent;
146
+ char *env_string = "MDEV_STATE=registered";
147
+ char *envp[] = { env_string, NULL };
171148
172149 /* check for mandatory ops */
173150 if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups)
....@@ -194,6 +171,7 @@
194171 }
195172
196173 kref_init(&parent->ref);
174
+ init_rwsem(&parent->unreg_sem);
197175
198176 parent->dev = dev;
199177 parent->ops = ops;
....@@ -218,6 +196,8 @@
218196 mutex_unlock(&parent_list_lock);
219197
220198 dev_info(dev, "MDEV: Registered\n");
199
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
200
+
221201 return 0;
222202
223203 add_dev_err:
....@@ -241,6 +221,8 @@
241221 void mdev_unregister_device(struct device *dev)
242222 {
243223 struct mdev_parent *parent;
224
+ char *env_string = "MDEV_STATE=unregistered";
225
+ char *envp[] = { env_string, NULL };
244226
245227 mutex_lock(&parent_list_lock);
246228 parent = __find_parent_device(dev);
....@@ -252,21 +234,26 @@
252234 dev_info(dev, "MDEV: Unregistering\n");
253235
254236 list_del(&parent->next);
237
+ mutex_unlock(&parent_list_lock);
238
+
239
+ down_write(&parent->unreg_sem);
240
+
255241 class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
256242
257243 device_for_each_child(dev, NULL, mdev_device_remove_cb);
258244
259245 parent_remove_sysfs_files(parent);
246
+ up_write(&parent->unreg_sem);
260247
261
- mutex_unlock(&parent_list_lock);
262248 mdev_put_parent(parent);
249
+
250
+ /* We still have the caller's reference to use for the uevent */
251
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
263252 }
264253 EXPORT_SYMBOL(mdev_unregister_device);
265254
266
-static void mdev_device_release(struct device *dev)
255
+static void mdev_device_free(struct mdev_device *mdev)
267256 {
268
- struct mdev_device *mdev = to_mdev_device(dev);
269
-
270257 mutex_lock(&mdev_list_lock);
271258 list_del(&mdev->next);
272259 mutex_unlock(&mdev_list_lock);
....@@ -275,7 +262,15 @@
275262 kfree(mdev);
276263 }
277264
278
-int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
265
+static void mdev_device_release(struct device *dev)
266
+{
267
+ struct mdev_device *mdev = to_mdev_device(dev);
268
+
269
+ mdev_device_free(mdev);
270
+}
271
+
272
+int mdev_device_create(struct kobject *kobj,
273
+ struct device *dev, const guid_t *uuid)
279274 {
280275 int ret;
281276 struct mdev_device *mdev, *tmp;
....@@ -290,7 +285,7 @@
290285
291286 /* Check for duplicate */
292287 list_for_each_entry(tmp, &mdev_list, next) {
293
- if (!uuid_le_cmp(tmp->uuid, uuid)) {
288
+ if (guid_equal(&tmp->uuid, uuid)) {
294289 mutex_unlock(&mdev_list_lock);
295290 ret = -EEXIST;
296291 goto mdev_fail;
....@@ -304,53 +299,61 @@
304299 goto mdev_fail;
305300 }
306301
307
- memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
302
+ guid_copy(&mdev->uuid, uuid);
308303 list_add(&mdev->next, &mdev_list);
309304 mutex_unlock(&mdev_list_lock);
310305
311306 mdev->parent = parent;
312
- kref_init(&mdev->ref);
313307
314
- mdev->dev.parent = dev;
315
- mdev->dev.bus = &mdev_bus_type;
316
- mdev->dev.release = mdev_device_release;
317
- dev_set_name(&mdev->dev, "%pUl", uuid.b);
318
-
319
- ret = device_register(&mdev->dev);
320
- if (ret) {
321
- put_device(&mdev->dev);
308
+ /* Check if parent unregistration has started */
309
+ if (!down_read_trylock(&parent->unreg_sem)) {
310
+ mdev_device_free(mdev);
311
+ ret = -ENODEV;
322312 goto mdev_fail;
323313 }
324314
325
- ret = mdev_device_create_ops(kobj, mdev);
315
+ device_initialize(&mdev->dev);
316
+ mdev->dev.parent = dev;
317
+ mdev->dev.bus = &mdev_bus_type;
318
+ mdev->dev.release = mdev_device_release;
319
+ dev_set_name(&mdev->dev, "%pUl", uuid);
320
+ mdev->dev.groups = parent->ops->mdev_attr_groups;
321
+ mdev->type_kobj = kobj;
322
+
323
+ ret = parent->ops->create(kobj, mdev);
326324 if (ret)
327
- goto create_fail;
325
+ goto ops_create_fail;
326
+
327
+ ret = device_add(&mdev->dev);
328
+ if (ret)
329
+ goto add_fail;
328330
329331 ret = mdev_create_sysfs_files(&mdev->dev, type);
330
- if (ret) {
331
- mdev_device_remove_ops(mdev, true);
332
- goto create_fail;
333
- }
332
+ if (ret)
333
+ goto sysfs_fail;
334334
335
- mdev->type_kobj = kobj;
336335 mdev->active = true;
337336 dev_dbg(&mdev->dev, "MDEV: created\n");
337
+ up_read(&parent->unreg_sem);
338338
339339 return 0;
340340
341
-create_fail:
342
- device_unregister(&mdev->dev);
341
+sysfs_fail:
342
+ device_del(&mdev->dev);
343
+add_fail:
344
+ parent->ops->remove(mdev);
345
+ops_create_fail:
346
+ up_read(&parent->unreg_sem);
347
+ put_device(&mdev->dev);
343348 mdev_fail:
344349 mdev_put_parent(parent);
345350 return ret;
346351 }
347352
348
-int mdev_device_remove(struct device *dev, bool force_remove)
353
+int mdev_device_remove(struct device *dev)
349354 {
350355 struct mdev_device *mdev, *tmp;
351356 struct mdev_parent *parent;
352
- struct mdev_type *type;
353
- int ret;
354357
355358 mdev = to_mdev_device(dev);
356359
....@@ -373,21 +376,33 @@
373376 mdev->active = false;
374377 mutex_unlock(&mdev_list_lock);
375378
376
- type = to_mdev_type(mdev->type_kobj);
377379 parent = mdev->parent;
380
+ /* Check if parent unregistration has started */
381
+ if (!down_read_trylock(&parent->unreg_sem))
382
+ return -ENODEV;
378383
379
- ret = mdev_device_remove_ops(mdev, force_remove);
380
- if (ret) {
381
- mdev->active = true;
382
- return ret;
383
- }
384
+ mdev_device_remove_common(mdev);
385
+ up_read(&parent->unreg_sem);
386
+ return 0;
387
+}
384388
385
- mdev_remove_sysfs_files(dev, type);
386
- device_unregister(dev);
387
- mdev_put_parent(parent);
389
+int mdev_set_iommu_device(struct device *dev, struct device *iommu_device)
390
+{
391
+ struct mdev_device *mdev = to_mdev_device(dev);
392
+
393
+ mdev->iommu_device = iommu_device;
388394
389395 return 0;
390396 }
397
+EXPORT_SYMBOL(mdev_set_iommu_device);
398
+
399
+struct device *mdev_get_iommu_device(struct device *dev)
400
+{
401
+ struct mdev_device *mdev = to_mdev_device(dev);
402
+
403
+ return mdev->iommu_device;
404
+}
405
+EXPORT_SYMBOL(mdev_get_iommu_device);
391406
392407 static int __init mdev_init(void)
393408 {