Skip to content

Commit 89345d5

Browse files
Christoph Hellwigawilliam
authored andcommitted
vfio/mdev: embedd struct mdev_parent in the parent data structure
Simplify mdev_{un}register_device by requiring the caller to pass in a structure allocate as part of the parent device structure. This removes the need for a list of parents and the separate mdev_parent refcount as we can simplify rely on the reference to the parent device. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Tony Krowiak <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Kirti Wankhede <[email protected]> Reviewed-by: Eric Farman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent bdef2b7 commit 89345d5

File tree

17 files changed

+71
-146
lines changed

17 files changed

+71
-146
lines changed

Documentation/driver-api/vfio-mediated-device.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,19 @@ devices as examples, as these devices are the first devices to use this module::
5858
| MDEV CORE |
5959
| MODULE |
6060
| mdev.ko |
61-
| +-----------+ | mdev_register_device() +--------------+
61+
| +-----------+ | mdev_register_parent() +--------------+
6262
| | | +<------------------------+ |
6363
| | | | | nvidia.ko |<-> physical
6464
| | | +------------------------>+ | device
6565
| | | | callbacks +--------------+
6666
| | Physical | |
67-
| | device | | mdev_register_device() +--------------+
67+
| | device | | mdev_register_parent() +--------------+
6868
| | interface | |<------------------------+ |
6969
| | | | | i915.ko |<-> physical
7070
| | | +------------------------>+ | device
7171
| | | | callbacks +--------------+
7272
| | | |
73-
| | | | mdev_register_device() +--------------+
73+
| | | | mdev_register_parent() +--------------+
7474
| | | +<------------------------+ |
7575
| | | | | ccw_device.ko|<-> physical
7676
| | | +------------------------>+ | device
@@ -125,16 +125,16 @@ vfio_device_ops.
125125
When a driver wants to add the GUID creation sysfs to an existing device it has
126126
probe'd to then it should call::
127127

128-
int mdev_register_device(struct device *dev,
129-
struct mdev_driver *mdev_driver);
128+
int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
129+
struct mdev_driver *mdev_driver);
130130

131131
This will provide the 'mdev_supported_types/XX/create' files which can then be
132132
used to trigger the creation of a mdev_device. The created mdev_device will be
133133
attached to the specified driver.
134134

135135
When the driver needs to remove itself it calls::
136136

137-
void mdev_unregister_device(struct device *dev);
137+
void mdev_unregister_parent(struct mdev_parent *parent);
138138

139139
Which will unbind and destroy all the created mdevs and remove the sysfs files.
140140

Documentation/s390/vfio-ap.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ of the VFIO AP mediated device driver::
297297
| MDEV CORE |
298298
| MODULE |
299299
| mdev.ko |
300-
| +---------+ | mdev_register_device() +--------------+
300+
| +---------+ | mdev_register_parent() +--------------+
301301
| |Physical | +<-----------------------+ |
302302
| | device | | | vfio_ap.ko |<-> matrix
303303
| |interface| +----------------------->+ | device

Documentation/s390/vfio-ccw.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ Below is a high Level block diagram::
156156
| MDEV CORE |
157157
| MODULE |
158158
| mdev.ko |
159-
| +---------+ | mdev_register_device() +--------------+
159+
| +---------+ | mdev_register_parent() +--------------+
160160
| |Physical | +<-----------------------+ |
161161
| | device | | | vfio_ccw.ko |<-> subchannel
162162
| |interface| +----------------------->+ | device

drivers/gpu/drm/i915/gvt/gvt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <uapi/linux/pci_regs.h>
3737
#include <linux/kvm_host.h>
3838
#include <linux/vfio.h>
39+
#include <linux/mdev.h>
3940

4041
#include "i915_drv.h"
4142
#include "intel_gvt.h"
@@ -337,6 +338,7 @@ struct intel_gvt {
337338
struct intel_gvt_workload_scheduler scheduler;
338339
struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
339340
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
341+
struct mdev_parent parent;
340342
struct intel_vgpu_type *types;
341343
unsigned int num_types;
342344
struct intel_vgpu *idle_vgpu;

drivers/gpu/drm/i915/gvt/kvmgt.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,7 +1923,7 @@ static void intel_gvt_clean_device(struct drm_i915_private *i915)
19231923
if (drm_WARN_ON(&i915->drm, !gvt))
19241924
return;
19251925

1926-
mdev_unregister_device(i915->drm.dev);
1926+
mdev_unregister_parent(&gvt->parent);
19271927
intel_gvt_cleanup_vgpu_type_groups(gvt);
19281928
intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
19291929
intel_gvt_clean_vgpu_types(gvt);
@@ -2028,7 +2028,8 @@ static int intel_gvt_init_device(struct drm_i915_private *i915)
20282028
if (ret)
20292029
goto out_destroy_idle_vgpu;
20302030

2031-
ret = mdev_register_device(i915->drm.dev, &intel_vgpu_mdev_driver);
2031+
ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
2032+
&intel_vgpu_mdev_driver);
20322033
if (ret)
20332034
goto out_cleanup_vgpu_type_groups;
20342035

drivers/s390/cio/vfio_ccw_drv.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
221221

222222
dev_set_drvdata(&sch->dev, private);
223223

224-
ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
224+
ret = mdev_register_parent(&private->parent, &sch->dev,
225+
&vfio_ccw_mdev_driver);
225226
if (ret)
226227
goto out_free;
227228

@@ -240,7 +241,7 @@ static void vfio_ccw_sch_remove(struct subchannel *sch)
240241
{
241242
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
242243

243-
mdev_unregister_device(&sch->dev);
244+
mdev_unregister_parent(&private->parent);
244245

245246
dev_set_drvdata(&sch->dev, NULL);
246247

drivers/s390/cio/vfio_ccw_ops.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
*/
1212

1313
#include <linux/vfio.h>
14-
#include <linux/mdev.h>
1514
#include <linux/nospec.h>
1615
#include <linux/slab.h>
1716

drivers/s390/cio/vfio_ccw_private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/workqueue.h>
1919
#include <linux/vfio_ccw.h>
2020
#include <linux/vfio.h>
21+
#include <linux/mdev.h>
2122
#include <asm/crw.h>
2223
#include <asm/debug.h>
2324

@@ -89,6 +90,7 @@ struct vfio_ccw_crw {
8990
* @io_work: work for deferral process of I/O handling
9091
* @crw_work: work for deferral process of CRW handling
9192
* @release_comp: synchronization helper for vfio device release
93+
* @parent: parent data structures for mdevs created
9294
*/
9395
struct vfio_ccw_private {
9496
struct vfio_device vdev;
@@ -116,6 +118,8 @@ struct vfio_ccw_private {
116118
struct work_struct crw_work;
117119

118120
struct completion release_comp;
121+
122+
struct mdev_parent parent;
119123
} __aligned(8);
120124

121125
int vfio_ccw_sch_quiesce(struct subchannel *sch);

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,8 @@ int vfio_ap_mdev_register(void)
18301830
if (ret)
18311831
return ret;
18321832

1833-
ret = mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_driver);
1833+
ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,
1834+
&vfio_ap_matrix_driver);
18341835
if (ret)
18351836
goto err_driver;
18361837
return 0;
@@ -1842,7 +1843,7 @@ int vfio_ap_mdev_register(void)
18421843

18431844
void vfio_ap_mdev_unregister(void)
18441845
{
1845-
mdev_unregister_device(&matrix_dev->device);
1846+
mdev_unregister_parent(&matrix_dev->parent);
18461847
mdev_unregister_driver(&vfio_ap_matrix_driver);
18471848
}
18481849

drivers/s390/crypto/vfio_ap_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct ap_matrix_dev {
5252
struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */
5353
struct ap_driver *vfio_ap_drv;
5454
struct mutex guests_lock; /* serializes access to each KVM guest */
55+
struct mdev_parent parent;
5556
};
5657

5758
extern struct ap_matrix_dev *matrix_dev;

drivers/vfio/mdev/mdev_core.c

Lines changed: 22 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#define DRIVER_AUTHOR "NVIDIA Corporation"
1919
#define DRIVER_DESC "Mediated device Core Driver"
2020

21-
static LIST_HEAD(parent_list);
22-
static DEFINE_MUTEX(parent_list_lock);
2321
static struct class_compat *mdev_bus_compat_class;
2422

2523
static LIST_HEAD(mdev_list);
@@ -61,28 +59,6 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype)
6159
}
6260
EXPORT_SYMBOL(mtype_get_parent_dev);
6361

64-
/* Should be called holding parent_list_lock */
65-
static struct mdev_parent *__find_parent_device(struct device *dev)
66-
{
67-
struct mdev_parent *parent;
68-
69-
list_for_each_entry(parent, &parent_list, next) {
70-
if (parent->dev == dev)
71-
return parent;
72-
}
73-
return NULL;
74-
}
75-
76-
void mdev_release_parent(struct kref *kref)
77-
{
78-
struct mdev_parent *parent = container_of(kref, struct mdev_parent,
79-
ref);
80-
struct device *dev = parent->dev;
81-
82-
kfree(parent);
83-
put_device(dev);
84-
}
85-
8662
/* Caller must hold parent unreg_sem read or write lock */
8763
static void mdev_device_remove_common(struct mdev_device *mdev)
8864
{
@@ -105,125 +81,73 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
10581
}
10682

10783
/*
108-
* mdev_register_device : Register a device
84+
* mdev_register_parent: Register a device as parent for mdevs
85+
* @parent: parent structure registered
10986
* @dev: device structure representing parent device.
11087
* @mdev_driver: Device driver to bind to the newly created mdev
11188
*
112-
* Add device to list of registered parent devices.
89+
* Registers the @parent stucture as a parent for mdev types and thus mdev
90+
* devices. The caller needs to hold a reference on @dev that must not be
91+
* released until after the call to mdev_unregister_parent().
92+
*
11393
* Returns a negative value on error, otherwise 0.
11494
*/
115-
int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver)
95+
int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
96+
struct mdev_driver *mdev_driver)
11697
{
117-
int ret;
118-
struct mdev_parent *parent;
11998
char *env_string = "MDEV_STATE=registered";
12099
char *envp[] = { env_string, NULL };
100+
int ret;
121101

122102
/* check for mandatory ops */
123103
if (!mdev_driver->supported_type_groups)
124104
return -EINVAL;
125105

126-
dev = get_device(dev);
127-
if (!dev)
128-
return -EINVAL;
129-
130-
mutex_lock(&parent_list_lock);
131-
132-
/* Check for duplicate */
133-
parent = __find_parent_device(dev);
134-
if (parent) {
135-
parent = NULL;
136-
ret = -EEXIST;
137-
goto add_dev_err;
138-
}
139-
140-
parent = kzalloc(sizeof(*parent), GFP_KERNEL);
141-
if (!parent) {
142-
ret = -ENOMEM;
143-
goto add_dev_err;
144-
}
145-
146-
kref_init(&parent->ref);
106+
memset(parent, 0, sizeof(*parent));
147107
init_rwsem(&parent->unreg_sem);
148-
149108
parent->dev = dev;
150109
parent->mdev_driver = mdev_driver;
151110

152111
if (!mdev_bus_compat_class) {
153112
mdev_bus_compat_class = class_compat_register("mdev_bus");
154-
if (!mdev_bus_compat_class) {
155-
ret = -ENOMEM;
156-
goto add_dev_err;
157-
}
113+
if (!mdev_bus_compat_class)
114+
return -ENOMEM;
158115
}
159116

160117
ret = parent_create_sysfs_files(parent);
161118
if (ret)
162-
goto add_dev_err;
119+
return ret;
163120

164121
ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL);
165122
if (ret)
166123
dev_warn(dev, "Failed to create compatibility class link\n");
167124

168-
list_add(&parent->next, &parent_list);
169-
mutex_unlock(&parent_list_lock);
170-
171125
dev_info(dev, "MDEV: Registered\n");
172126
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
173-
174127
return 0;
175-
176-
add_dev_err:
177-
mutex_unlock(&parent_list_lock);
178-
if (parent)
179-
mdev_put_parent(parent);
180-
else
181-
put_device(dev);
182-
return ret;
183128
}
184-
EXPORT_SYMBOL(mdev_register_device);
129+
EXPORT_SYMBOL(mdev_register_parent);
185130

186131
/*
187-
* mdev_unregister_device : Unregister a parent device
188-
* @dev: device structure representing parent device.
189-
*
190-
* Remove device from list of registered parent devices. Give a chance to free
191-
* existing mediated devices for given device.
132+
* mdev_unregister_parent : Unregister a parent device
133+
* @parent: parent structure to unregister
192134
*/
193-
194-
void mdev_unregister_device(struct device *dev)
135+
void mdev_unregister_parent(struct mdev_parent *parent)
195136
{
196-
struct mdev_parent *parent;
197137
char *env_string = "MDEV_STATE=unregistered";
198138
char *envp[] = { env_string, NULL };
199139

200-
mutex_lock(&parent_list_lock);
201-
parent = __find_parent_device(dev);
202-
203-
if (!parent) {
204-
mutex_unlock(&parent_list_lock);
205-
return;
206-
}
207-
dev_info(dev, "MDEV: Unregistering\n");
208-
209-
list_del(&parent->next);
210-
mutex_unlock(&parent_list_lock);
140+
dev_info(parent->dev, "MDEV: Unregistering\n");
211141

212142
down_write(&parent->unreg_sem);
213-
214-
class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
215-
216-
device_for_each_child(dev, NULL, mdev_device_remove_cb);
217-
143+
class_compat_remove_link(mdev_bus_compat_class, parent->dev, NULL);
144+
device_for_each_child(parent->dev, NULL, mdev_device_remove_cb);
218145
parent_remove_sysfs_files(parent);
219146
up_write(&parent->unreg_sem);
220147

221-
mdev_put_parent(parent);
222-
223-
/* We still have the caller's reference to use for the uevent */
224-
kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
148+
kobject_uevent_env(&parent->dev->kobj, KOBJ_CHANGE, envp);
225149
}
226-
EXPORT_SYMBOL(mdev_unregister_device);
150+
EXPORT_SYMBOL(mdev_unregister_parent);
227151

228152
static void mdev_device_release(struct device *dev)
229153
{

drivers/vfio/mdev/mdev_private.h

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,6 @@
1313
int mdev_bus_register(void);
1414
void mdev_bus_unregister(void);
1515

16-
struct mdev_parent {
17-
struct device *dev;
18-
struct mdev_driver *mdev_driver;
19-
struct kref ref;
20-
struct list_head next;
21-
struct kset *mdev_types_kset;
22-
struct list_head type_list;
23-
/* Synchronize device creation/removal with parent unregistration */
24-
struct rw_semaphore unreg_sem;
25-
};
26-
2716
struct mdev_type {
2817
struct kobject kobj;
2918
struct kobject *devices_kobj;
@@ -48,16 +37,4 @@ void mdev_remove_sysfs_files(struct mdev_device *mdev);
4837
int mdev_device_create(struct mdev_type *kobj, const guid_t *uuid);
4938
int mdev_device_remove(struct mdev_device *dev);
5039

51-
void mdev_release_parent(struct kref *kref);
52-
53-
static inline void mdev_get_parent(struct mdev_parent *parent)
54-
{
55-
kref_get(&parent->ref);
56-
}
57-
58-
static inline void mdev_put_parent(struct mdev_parent *parent)
59-
{
60-
kref_put(&parent->ref, mdev_release_parent);
61-
}
62-
6340
#endif /* MDEV_PRIVATE_H */

0 commit comments

Comments
 (0)