Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/r/20220923092652.100656-5-hch@lst.de
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Christoph Hellwig and committed by
Alex Williamson
89345d51 bdef2b78

+71 -146
+6 -6
Documentation/driver-api/vfio-mediated-device.rst
··· 58 58 | MDEV CORE | 59 59 | MODULE | 60 60 | mdev.ko | 61 - | +-----------+ | mdev_register_device() +--------------+ 61 + | +-----------+ | mdev_register_parent() +--------------+ 62 62 | | | +<------------------------+ | 63 63 | | | | | nvidia.ko |<-> physical 64 64 | | | +------------------------>+ | device 65 65 | | | | callbacks +--------------+ 66 66 | | Physical | | 67 - | | device | | mdev_register_device() +--------------+ 67 + | | device | | mdev_register_parent() +--------------+ 68 68 | | interface | |<------------------------+ | 69 69 | | | | | i915.ko |<-> physical 70 70 | | | +------------------------>+ | device 71 71 | | | | callbacks +--------------+ 72 72 | | | | 73 - | | | | mdev_register_device() +--------------+ 73 + | | | | mdev_register_parent() +--------------+ 74 74 | | | +<------------------------+ | 75 75 | | | | | ccw_device.ko|<-> physical 76 76 | | | +------------------------>+ | device ··· 125 125 When a driver wants to add the GUID creation sysfs to an existing device it has 126 126 probe'd to then it should call:: 127 127 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); 130 130 131 131 This will provide the 'mdev_supported_types/XX/create' files which can then be 132 132 used to trigger the creation of a mdev_device. The created mdev_device will be ··· 134 134 135 135 When the driver needs to remove itself it calls:: 136 136 137 - void mdev_unregister_device(struct device *dev); 137 + void mdev_unregister_parent(struct mdev_parent *parent); 138 138 139 139 Which will unbind and destroy all the created mdevs and remove the sysfs files. 140 140
+1 -1
Documentation/s390/vfio-ap.rst
··· 297 297 | MDEV CORE | 298 298 | MODULE | 299 299 | mdev.ko | 300 - | +---------+ | mdev_register_device() +--------------+ 300 + | +---------+ | mdev_register_parent() +--------------+ 301 301 | |Physical | +<-----------------------+ | 302 302 | | device | | | vfio_ap.ko |<-> matrix 303 303 | |interface| +----------------------->+ | device
+1 -1
Documentation/s390/vfio-ccw.rst
··· 156 156 | MDEV CORE | 157 157 | MODULE | 158 158 | mdev.ko | 159 - | +---------+ | mdev_register_device() +--------------+ 159 + | +---------+ | mdev_register_parent() +--------------+ 160 160 | |Physical | +<-----------------------+ | 161 161 | | device | | | vfio_ccw.ko |<-> subchannel 162 162 | |interface| +----------------------->+ | device
+2
drivers/gpu/drm/i915/gvt/gvt.h
··· 36 36 #include <uapi/linux/pci_regs.h> 37 37 #include <linux/kvm_host.h> 38 38 #include <linux/vfio.h> 39 + #include <linux/mdev.h> 39 40 40 41 #include "i915_drv.h" 41 42 #include "intel_gvt.h" ··· 338 337 struct intel_gvt_workload_scheduler scheduler; 339 338 struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES]; 340 339 DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); 340 + struct mdev_parent parent; 341 341 struct intel_vgpu_type *types; 342 342 unsigned int num_types; 343 343 struct intel_vgpu *idle_vgpu;
+3 -2
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 1923 1923 if (drm_WARN_ON(&i915->drm, !gvt)) 1924 1924 return; 1925 1925 1926 - mdev_unregister_device(i915->drm.dev); 1926 + mdev_unregister_parent(&gvt->parent); 1927 1927 intel_gvt_cleanup_vgpu_type_groups(gvt); 1928 1928 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); 1929 1929 intel_gvt_clean_vgpu_types(gvt); ··· 2028 2028 if (ret) 2029 2029 goto out_destroy_idle_vgpu; 2030 2030 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); 2032 2033 if (ret) 2033 2034 goto out_cleanup_vgpu_type_groups; 2034 2035
+3 -2
drivers/s390/cio/vfio_ccw_drv.c
··· 221 221 222 222 dev_set_drvdata(&sch->dev, private); 223 223 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); 225 226 if (ret) 226 227 goto out_free; 227 228 ··· 241 240 { 242 241 struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); 243 242 244 - mdev_unregister_device(&sch->dev); 243 + mdev_unregister_parent(&private->parent); 245 244 246 245 dev_set_drvdata(&sch->dev, NULL); 247 246
-1
drivers/s390/cio/vfio_ccw_ops.c
··· 11 11 */ 12 12 13 13 #include <linux/vfio.h> 14 - #include <linux/mdev.h> 15 14 #include <linux/nospec.h> 16 15 #include <linux/slab.h> 17 16
+4
drivers/s390/cio/vfio_ccw_private.h
··· 18 18 #include <linux/workqueue.h> 19 19 #include <linux/vfio_ccw.h> 20 20 #include <linux/vfio.h> 21 + #include <linux/mdev.h> 21 22 #include <asm/crw.h> 22 23 #include <asm/debug.h> 23 24 ··· 90 89 * @io_work: work for deferral process of I/O handling 91 90 * @crw_work: work for deferral process of CRW handling 92 91 * @release_comp: synchronization helper for vfio device release 92 + * @parent: parent data structures for mdevs created 93 93 */ 94 94 struct vfio_ccw_private { 95 95 struct vfio_device vdev; ··· 118 116 struct work_struct crw_work; 119 117 120 118 struct completion release_comp; 119 + 120 + struct mdev_parent parent; 121 121 } __aligned(8); 122 122 123 123 int vfio_ccw_sch_quiesce(struct subchannel *sch);
+3 -2
drivers/s390/crypto/vfio_ap_ops.c
··· 1830 1830 if (ret) 1831 1831 return ret; 1832 1832 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); 1834 1835 if (ret) 1835 1836 goto err_driver; 1836 1837 return 0; ··· 1843 1842 1844 1843 void vfio_ap_mdev_unregister(void) 1845 1844 { 1846 - mdev_unregister_device(&matrix_dev->device); 1845 + mdev_unregister_parent(&matrix_dev->parent); 1847 1846 mdev_unregister_driver(&vfio_ap_matrix_driver); 1848 1847 } 1849 1848
+1
drivers/s390/crypto/vfio_ap_private.h
··· 52 52 struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */ 53 53 struct ap_driver *vfio_ap_drv; 54 54 struct mutex guests_lock; /* serializes access to each KVM guest */ 55 + struct mdev_parent parent; 55 56 }; 56 57 57 58 extern struct ap_matrix_dev *matrix_dev;
+22 -98
drivers/vfio/mdev/mdev_core.c
··· 18 18 #define DRIVER_AUTHOR "NVIDIA Corporation" 19 19 #define DRIVER_DESC "Mediated device Core Driver" 20 20 21 - static LIST_HEAD(parent_list); 22 - static DEFINE_MUTEX(parent_list_lock); 23 21 static struct class_compat *mdev_bus_compat_class; 24 22 25 23 static LIST_HEAD(mdev_list); ··· 59 61 } 60 62 EXPORT_SYMBOL(mtype_get_parent_dev); 61 63 62 - /* Should be called holding parent_list_lock */ 63 - static struct mdev_parent *__find_parent_device(struct device *dev) 64 - { 65 - struct mdev_parent *parent; 66 - 67 - list_for_each_entry(parent, &parent_list, next) { 68 - if (parent->dev == dev) 69 - return parent; 70 - } 71 - return NULL; 72 - } 73 - 74 - void mdev_release_parent(struct kref *kref) 75 - { 76 - struct mdev_parent *parent = container_of(kref, struct mdev_parent, 77 - ref); 78 - struct device *dev = parent->dev; 79 - 80 - kfree(parent); 81 - put_device(dev); 82 - } 83 - 84 64 /* Caller must hold parent unreg_sem read or write lock */ 85 65 static void mdev_device_remove_common(struct mdev_device *mdev) 86 66 { ··· 81 105 } 82 106 83 107 /* 84 - * mdev_register_device : Register a device 108 + * mdev_register_parent: Register a device as parent for mdevs 109 + * @parent: parent structure registered 85 110 * @dev: device structure representing parent device. 86 111 * @mdev_driver: Device driver to bind to the newly created mdev 87 112 * 88 - * Add device to list of registered parent devices. 113 + * Registers the @parent stucture as a parent for mdev types and thus mdev 114 + * devices. The caller needs to hold a reference on @dev that must not be 115 + * released until after the call to mdev_unregister_parent(). 116 + * 89 117 * Returns a negative value on error, otherwise 0. 90 118 */ 91 - int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver) 119 + int mdev_register_parent(struct mdev_parent *parent, struct device *dev, 120 + struct mdev_driver *mdev_driver) 92 121 { 93 - int ret; 94 - struct mdev_parent *parent; 95 122 char *env_string = "MDEV_STATE=registered"; 96 123 char *envp[] = { env_string, NULL }; 124 + int ret; 97 125 98 126 /* check for mandatory ops */ 99 127 if (!mdev_driver->supported_type_groups) 100 128 return -EINVAL; 101 129 102 - dev = get_device(dev); 103 - if (!dev) 104 - return -EINVAL; 105 - 106 - mutex_lock(&parent_list_lock); 107 - 108 - /* Check for duplicate */ 109 - parent = __find_parent_device(dev); 110 - if (parent) { 111 - parent = NULL; 112 - ret = -EEXIST; 113 - goto add_dev_err; 114 - } 115 - 116 - parent = kzalloc(sizeof(*parent), GFP_KERNEL); 117 - if (!parent) { 118 - ret = -ENOMEM; 119 - goto add_dev_err; 120 - } 121 - 122 - kref_init(&parent->ref); 130 + memset(parent, 0, sizeof(*parent)); 123 131 init_rwsem(&parent->unreg_sem); 124 - 125 132 parent->dev = dev; 126 133 parent->mdev_driver = mdev_driver; 127 134 128 135 if (!mdev_bus_compat_class) { 129 136 mdev_bus_compat_class = class_compat_register("mdev_bus"); 130 - if (!mdev_bus_compat_class) { 131 - ret = -ENOMEM; 132 - goto add_dev_err; 133 - } 137 + if (!mdev_bus_compat_class) 138 + return -ENOMEM; 134 139 } 135 140 136 141 ret = parent_create_sysfs_files(parent); 137 142 if (ret) 138 - goto add_dev_err; 143 + return ret; 139 144 140 145 ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL); 141 146 if (ret) 142 147 dev_warn(dev, "Failed to create compatibility class link\n"); 143 148 144 - list_add(&parent->next, &parent_list); 145 - mutex_unlock(&parent_list_lock); 146 - 147 149 dev_info(dev, "MDEV: Registered\n"); 148 150 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 149 - 150 151 return 0; 151 - 152 - add_dev_err: 153 - mutex_unlock(&parent_list_lock); 154 - if (parent) 155 - mdev_put_parent(parent); 156 - else 157 - put_device(dev); 158 - return ret; 159 152 } 160 - EXPORT_SYMBOL(mdev_register_device); 153 + EXPORT_SYMBOL(mdev_register_parent); 161 154 162 155 /* 163 - * mdev_unregister_device : Unregister a parent device 164 - * @dev: device structure representing parent device. 165 - * 166 - * Remove device from list of registered parent devices. Give a chance to free 167 - * existing mediated devices for given device. 156 + * mdev_unregister_parent : Unregister a parent device 157 + * @parent: parent structure to unregister 168 158 */ 169 - 170 - void mdev_unregister_device(struct device *dev) 159 + void mdev_unregister_parent(struct mdev_parent *parent) 171 160 { 172 - struct mdev_parent *parent; 173 161 char *env_string = "MDEV_STATE=unregistered"; 174 162 char *envp[] = { env_string, NULL }; 175 163 176 - mutex_lock(&parent_list_lock); 177 - parent = __find_parent_device(dev); 178 - 179 - if (!parent) { 180 - mutex_unlock(&parent_list_lock); 181 - return; 182 - } 183 - dev_info(dev, "MDEV: Unregistering\n"); 184 - 185 - list_del(&parent->next); 186 - mutex_unlock(&parent_list_lock); 164 + dev_info(parent->dev, "MDEV: Unregistering\n"); 187 165 188 166 down_write(&parent->unreg_sem); 189 - 190 - class_compat_remove_link(mdev_bus_compat_class, dev, NULL); 191 - 192 - device_for_each_child(dev, NULL, mdev_device_remove_cb); 193 - 167 + class_compat_remove_link(mdev_bus_compat_class, parent->dev, NULL); 168 + device_for_each_child(parent->dev, NULL, mdev_device_remove_cb); 194 169 parent_remove_sysfs_files(parent); 195 170 up_write(&parent->unreg_sem); 196 171 197 - mdev_put_parent(parent); 198 - 199 - /* We still have the caller's reference to use for the uevent */ 200 - kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 172 + kobject_uevent_env(&parent->dev->kobj, KOBJ_CHANGE, envp); 201 173 } 202 - EXPORT_SYMBOL(mdev_unregister_device); 174 + EXPORT_SYMBOL(mdev_unregister_parent); 203 175 204 176 static void mdev_device_release(struct device *dev) 205 177 {
-23
drivers/vfio/mdev/mdev_private.h
··· 13 13 int mdev_bus_register(void); 14 14 void mdev_bus_unregister(void); 15 15 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 - 27 16 struct mdev_type { 28 17 struct kobject kobj; 29 18 struct kobject *devices_kobj; ··· 36 47 37 48 int mdev_device_create(struct mdev_type *kobj, const guid_t *uuid); 38 49 int mdev_device_remove(struct mdev_device *dev); 39 - 40 - void mdev_release_parent(struct kref *kref); 41 - 42 - static inline void mdev_get_parent(struct mdev_parent *parent) 43 - { 44 - kref_get(&parent->ref); 45 - } 46 - 47 - static inline void mdev_put_parent(struct mdev_parent *parent) 48 - { 49 - kref_put(&parent->ref, mdev_release_parent); 50 - } 51 50 52 51 #endif /* MDEV_PRIVATE_H */
+2 -2
drivers/vfio/mdev/mdev_sysfs.c
··· 81 81 82 82 pr_debug("Releasing group %s\n", kobj->name); 83 83 /* Pairs with the get in add_mdev_supported_type() */ 84 - mdev_put_parent(type->parent); 84 + put_device(type->parent->dev); 85 85 kfree(type); 86 86 } 87 87 ··· 110 110 type->kobj.kset = parent->mdev_types_kset; 111 111 type->parent = parent; 112 112 /* Pairs with the put in mdev_type_release() */ 113 - mdev_get_parent(parent); 113 + get_device(parent->dev); 114 114 type->type_group_id = type_group_id; 115 115 116 116 ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
+13 -2
include/linux/mdev.h
··· 23 23 bool active; 24 24 }; 25 25 26 + /* embedded into the struct device that the mdev devices hang off */ 27 + struct mdev_parent { 28 + struct device *dev; 29 + struct mdev_driver *mdev_driver; 30 + struct kset *mdev_types_kset; 31 + struct list_head type_list; 32 + /* Synchronize device creation/removal with parent unregistration */ 33 + struct rw_semaphore unreg_sem; 34 + }; 35 + 26 36 static inline struct mdev_device *to_mdev_device(struct device *dev) 27 37 { 28 38 return container_of(dev, struct mdev_device, dev); ··· 80 70 81 71 extern struct bus_type mdev_bus_type; 82 72 83 - int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver); 84 - void mdev_unregister_device(struct device *dev); 73 + int mdev_register_parent(struct mdev_parent *parent, struct device *dev, 74 + struct mdev_driver *mdev_driver); 75 + void mdev_unregister_parent(struct mdev_parent *parent); 85 76 86 77 int mdev_register_driver(struct mdev_driver *drv); 87 78 void mdev_unregister_driver(struct mdev_driver *drv);
+3 -2
samples/vfio-mdev/mbochs.c
··· 128 128 static struct class *mbochs_class; 129 129 static struct cdev mbochs_cdev; 130 130 static struct device mbochs_dev; 131 + static struct mdev_parent mbochs_parent; 131 132 static atomic_t mbochs_avail_mbytes; 132 133 static const struct vfio_device_ops mbochs_dev_ops; 133 134 ··· 1476 1475 if (ret) 1477 1476 goto err_class; 1478 1477 1479 - ret = mdev_register_device(&mbochs_dev, &mbochs_driver); 1478 + ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver); 1480 1479 if (ret) 1481 1480 goto err_device; 1482 1481 ··· 1497 1496 static void __exit mbochs_dev_exit(void) 1498 1497 { 1499 1498 mbochs_dev.bus = NULL; 1500 - mdev_unregister_device(&mbochs_dev); 1499 + mdev_unregister_parent(&mbochs_parent); 1501 1500 1502 1501 device_unregister(&mbochs_dev); 1503 1502 mdev_unregister_driver(&mbochs_driver);
+3 -2
samples/vfio-mdev/mdpy.c
··· 83 83 static struct class *mdpy_class; 84 84 static struct cdev mdpy_cdev; 85 85 static struct device mdpy_dev; 86 + static struct mdev_parent mdpy_parent; 86 87 static u32 mdpy_count; 87 88 static const struct vfio_device_ops mdpy_dev_ops; 88 89 ··· 779 778 if (ret) 780 779 goto err_class; 781 780 782 - ret = mdev_register_device(&mdpy_dev, &mdpy_driver); 781 + ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver); 783 782 if (ret) 784 783 goto err_device; 785 784 ··· 800 799 static void __exit mdpy_dev_exit(void) 801 800 { 802 801 mdpy_dev.bus = NULL; 803 - mdev_unregister_device(&mdpy_dev); 802 + mdev_unregister_parent(&mdpy_parent); 804 803 805 804 device_unregister(&mdpy_dev); 806 805 mdev_unregister_driver(&mdpy_driver);
+4 -2
samples/vfio-mdev/mtty.c
··· 72 72 struct cdev vd_cdev; 73 73 struct idr vd_idr; 74 74 struct device dev; 75 + struct mdev_parent parent; 75 76 } mtty_dev; 76 77 77 78 struct mdev_region_info { ··· 1362 1361 if (ret) 1363 1362 goto err_class; 1364 1363 1365 - ret = mdev_register_device(&mtty_dev.dev, &mtty_driver); 1364 + ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev, 1365 + &mtty_driver); 1366 1366 if (ret) 1367 1367 goto err_device; 1368 1368 return 0; ··· 1383 1381 static void __exit mtty_dev_exit(void) 1384 1382 { 1385 1383 mtty_dev.dev.bus = NULL; 1386 - mdev_unregister_device(&mtty_dev.dev); 1384 + mdev_unregister_parent(&mtty_dev.parent); 1387 1385 1388 1386 device_unregister(&mtty_dev.dev); 1389 1387 idr_destroy(&mtty_dev.vd_idr);