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

vfio/mdev: simplify mdev_type handling

Instead of abusing struct attribute_group to control initialization of
struct mdev_type, just define the actual attributes in the mdev_driver,
allocate the mdev_type structures in the caller and pass them to
mdev_register_parent.

This allows the caller to use container_of to get at the containing
structure and thus significantly simplify the code.

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-6-hch@lst.de
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Christoph Hellwig and committed by
Alex Williamson
da44c340 89345d51

+165 -326
+1 -1
Documentation/driver-api/vfio-mediated-device.rst
··· 103 103 struct mdev_driver { 104 104 int (*probe) (struct mdev_device *dev); 105 105 void (*remove) (struct mdev_device *dev); 106 - struct attribute_group **supported_type_groups; 106 + const struct attribute * const *types_attrs; 107 107 struct device_driver driver; 108 108 }; 109 109
+2 -1
drivers/gpu/drm/i915/gvt/gvt.h
··· 310 310 const char *name; 311 311 }; 312 312 313 - #define NR_MAX_INTEL_VGPU_TYPES 20 314 313 struct intel_vgpu_type { 314 + struct mdev_type type; 315 315 char name[16]; 316 316 const struct intel_vgpu_config *conf; 317 317 unsigned int avail_instance; ··· 339 339 struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES]; 340 340 DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); 341 341 struct mdev_parent parent; 342 + struct mdev_type **mdev_types; 342 343 struct intel_vgpu_type *types; 343 344 unsigned int num_types; 344 345 struct intel_vgpu *idle_vgpu;
+14 -88
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 117 117 struct mdev_type_attribute *attr, 118 118 char *buf) 119 119 { 120 - struct intel_vgpu_type *type; 121 - unsigned int num = 0; 122 - struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt; 120 + struct intel_vgpu_type *type = 121 + container_of(mtype, struct intel_vgpu_type, type); 123 122 124 - type = &gvt->types[mtype_get_type_group_id(mtype)]; 125 - if (!type) 126 - num = 0; 127 - else 128 - num = type->avail_instance; 129 - 130 - return sprintf(buf, "%u\n", num); 123 + return sprintf(buf, "%u\n", type->avail_instance); 131 124 } 132 125 133 126 static ssize_t device_api_show(struct mdev_type *mtype, ··· 132 139 static ssize_t description_show(struct mdev_type *mtype, 133 140 struct mdev_type_attribute *attr, char *buf) 134 141 { 135 - struct intel_vgpu_type *type; 136 - struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt; 137 - 138 - type = &gvt->types[mtype_get_type_group_id(mtype)]; 139 - if (!type) 140 - return 0; 142 + struct intel_vgpu_type *type = 143 + container_of(mtype, struct intel_vgpu_type, type); 141 144 142 145 return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" 143 146 "fence: %d\nresolution: %s\n" ··· 147 158 static ssize_t name_show(struct mdev_type *mtype, 148 159 struct mdev_type_attribute *attr, char *buf) 149 160 { 150 - struct intel_vgpu_type *type; 151 - struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt; 152 - 153 - type = &gvt->types[mtype_get_type_group_id(mtype)]; 154 - if (!type) 155 - return 0; 156 - 157 - return sprintf(buf, "%s\n", type->name); 161 + return sprintf(buf, "%s\n", mtype->sysfs_name); 158 162 } 159 163 160 164 static MDEV_TYPE_ATTR_RO(available_instances); ··· 155 173 static MDEV_TYPE_ATTR_RO(description); 156 174 static MDEV_TYPE_ATTR_RO(name); 157 175 158 - static struct attribute *gvt_type_attrs[] = { 176 + static const struct attribute *gvt_type_attrs[] = { 159 177 &mdev_type_attr_available_instances.attr, 160 178 &mdev_type_attr_device_api.attr, 161 179 &mdev_type_attr_description.attr, 162 180 &mdev_type_attr_name.attr, 163 181 NULL, 164 182 }; 165 - 166 - static struct attribute_group *gvt_vgpu_type_groups[] = { 167 - [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, 168 - }; 169 - 170 - static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt) 171 - { 172 - int i, j; 173 - struct intel_vgpu_type *type; 174 - struct attribute_group *group; 175 - 176 - for (i = 0; i < gvt->num_types; i++) { 177 - type = &gvt->types[i]; 178 - 179 - group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); 180 - if (!group) 181 - goto unwind; 182 - 183 - group->name = type->name; 184 - group->attrs = gvt_type_attrs; 185 - gvt_vgpu_type_groups[i] = group; 186 - } 187 - 188 - return 0; 189 - 190 - unwind: 191 - for (j = 0; j < i; j++) { 192 - group = gvt_vgpu_type_groups[j]; 193 - kfree(group); 194 - } 195 - 196 - return -ENOMEM; 197 - } 198 - 199 - static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt) 200 - { 201 - int i; 202 - struct attribute_group *group; 203 - 204 - for (i = 0; i < gvt->num_types; i++) { 205 - group = gvt_vgpu_type_groups[i]; 206 - gvt_vgpu_type_groups[i] = NULL; 207 - kfree(group); 208 - } 209 - } 210 183 211 184 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, 212 185 unsigned long size) ··· 1484 1547 static int intel_vgpu_init_dev(struct vfio_device *vfio_dev) 1485 1548 { 1486 1549 struct mdev_device *mdev = to_mdev_device(vfio_dev->dev); 1487 - struct device *pdev = mdev_parent_dev(mdev); 1488 - struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt; 1489 - struct intel_vgpu_type *type; 1490 1550 struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); 1551 + struct intel_vgpu_type *type = 1552 + container_of(mdev->type, struct intel_vgpu_type, type); 1491 1553 1492 - type = &gvt->types[mdev_get_type_group_id(mdev)]; 1493 - if (!type) 1494 - return -EINVAL; 1495 - 1496 - vgpu->gvt = gvt; 1554 + vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt; 1497 1555 return intel_gvt_create_vgpu(vgpu, type->conf); 1498 1556 } 1499 1557 ··· 1557 1625 }, 1558 1626 .probe = intel_vgpu_probe, 1559 1627 .remove = intel_vgpu_remove, 1560 - .supported_type_groups = gvt_vgpu_type_groups, 1628 + .types_attrs = gvt_type_attrs, 1561 1629 }; 1562 1630 1563 1631 int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn) ··· 1856 1924 return; 1857 1925 1858 1926 mdev_unregister_parent(&gvt->parent); 1859 - intel_gvt_cleanup_vgpu_type_groups(gvt); 1860 1927 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); 1861 1928 intel_gvt_clean_vgpu_types(gvt); 1862 1929 ··· 1955 2024 1956 2025 intel_gvt_debugfs_init(gvt); 1957 2026 1958 - ret = intel_gvt_init_vgpu_type_groups(gvt); 2027 + ret = mdev_register_parent(&gvt->parent, i915->drm.dev, 2028 + &intel_vgpu_mdev_driver, 2029 + gvt->mdev_types, gvt->num_types); 1959 2030 if (ret) 1960 2031 goto out_destroy_idle_vgpu; 1961 - 1962 - ret = mdev_register_parent(&gvt->parent, i915->drm.dev, 1963 - &intel_vgpu_mdev_driver); 1964 - if (ret) 1965 - goto out_cleanup_vgpu_type_groups; 1966 2032 1967 2033 gvt_dbg_core("gvt device initialization is done\n"); 1968 2034 return 0; 1969 2035 1970 - out_cleanup_vgpu_type_groups: 1971 - intel_gvt_cleanup_vgpu_type_groups(gvt); 1972 2036 out_destroy_idle_vgpu: 1973 2037 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); 1974 2038 intel_gvt_debugfs_clean(gvt);
+12 -1
drivers/gpu/drm/i915/gvt/vgpu.c
··· 113 113 if (!gvt->types) 114 114 return -ENOMEM; 115 115 116 + gvt->mdev_types = kcalloc(num_types, sizeof(*gvt->mdev_types), 117 + GFP_KERNEL); 118 + if (!gvt->mdev_types) 119 + goto out_free_types; 120 + 116 121 for (i = 0; i < num_types; ++i) { 117 122 const struct intel_vgpu_config *conf = &intel_vgpu_configs[i]; 118 123 119 124 if (low_avail / conf->low_mm == 0) 120 125 break; 121 126 if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT) 122 - goto out_free_types; 127 + goto out_free_mdev_types; 123 128 124 129 sprintf(gvt->types[i].name, "GVTg_V%u_%s", 125 130 GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name); ··· 136 131 i, gvt->types[i].name, gvt->types[i].avail_instance, 137 132 conf->low_mm, conf->high_mm, conf->fence, 138 133 conf->weight, vgpu_edid_str(conf->edid)); 134 + 135 + gvt->mdev_types[i] = &gvt->types[i].type; 136 + gvt->mdev_types[i]->sysfs_name = gvt->types[i].name; 139 137 } 140 138 141 139 gvt->num_types = i; 142 140 return 0; 143 141 142 + out_free_mdev_types: 143 + kfree(gvt->mdev_types); 144 144 out_free_types: 145 145 kfree(gvt->types); 146 146 return -EINVAL; ··· 153 143 154 144 void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt) 155 145 { 146 + kfree(gvt->mdev_types); 156 147 kfree(gvt->types); 157 148 } 158 149
+4 -2
drivers/s390/cio/vfio_ccw_drv.c
··· 202 202 mutex_destroy(&private->io_mutex); 203 203 kfree(private); 204 204 } 205 - 206 205 static int vfio_ccw_sch_probe(struct subchannel *sch) 207 206 { 208 207 struct pmcw *pmcw = &sch->schib.pmcw; ··· 220 221 221 222 dev_set_drvdata(&sch->dev, private); 222 223 224 + private->mdev_type.sysfs_name = "io"; 225 + private->mdev_types[0] = &private->mdev_type; 223 226 ret = mdev_register_parent(&private->parent, &sch->dev, 224 - &vfio_ccw_mdev_driver); 227 + &vfio_ccw_mdev_driver, 228 + private->mdev_types, 1); 225 229 if (ret) 226 230 goto out_free; 227 231
+2 -12
drivers/s390/cio/vfio_ccw_ops.c
··· 69 69 } 70 70 static MDEV_TYPE_ATTR_RO(available_instances); 71 71 72 - static struct attribute *mdev_types_attrs[] = { 72 + static const struct attribute *mdev_types_attrs[] = { 73 73 &mdev_type_attr_name.attr, 74 74 &mdev_type_attr_device_api.attr, 75 75 &mdev_type_attr_available_instances.attr, 76 - NULL, 77 - }; 78 - 79 - static struct attribute_group mdev_type_group = { 80 - .name = "io", 81 - .attrs = mdev_types_attrs, 82 - }; 83 - 84 - static struct attribute_group *mdev_type_groups[] = { 85 - &mdev_type_group, 86 76 NULL, 87 77 }; 88 78 ··· 636 646 }, 637 647 .probe = vfio_ccw_mdev_probe, 638 648 .remove = vfio_ccw_mdev_remove, 639 - .supported_type_groups = mdev_type_groups, 649 + .types_attrs = mdev_types_attrs, 640 650 };
+2
drivers/s390/cio/vfio_ccw_private.h
··· 120 120 struct completion release_comp; 121 121 122 122 struct mdev_parent parent; 123 + struct mdev_type mdev_type; 124 + struct mdev_type *mdev_types[1]; 123 125 } __aligned(8); 124 126 125 127 int vfio_ccw_sch_quiesce(struct subchannel *sch);
+6 -13
drivers/s390/crypto/vfio_ap_ops.c
··· 816 816 817 817 static MDEV_TYPE_ATTR_RO(device_api); 818 818 819 - static struct attribute *vfio_ap_mdev_type_attrs[] = { 819 + static const struct attribute *vfio_ap_mdev_type_attrs[] = { 820 820 &mdev_type_attr_name.attr, 821 821 &mdev_type_attr_device_api.attr, 822 822 &mdev_type_attr_available_instances.attr, 823 - NULL, 824 - }; 825 - 826 - static struct attribute_group vfio_ap_mdev_hwvirt_type_group = { 827 - .name = VFIO_AP_MDEV_TYPE_HWVIRT, 828 - .attrs = vfio_ap_mdev_type_attrs, 829 - }; 830 - 831 - static struct attribute_group *vfio_ap_mdev_type_groups[] = { 832 - &vfio_ap_mdev_hwvirt_type_group, 833 823 NULL, 834 824 }; 835 825 ··· 1807 1817 }, 1808 1818 .probe = vfio_ap_mdev_probe, 1809 1819 .remove = vfio_ap_mdev_remove, 1810 - .supported_type_groups = vfio_ap_mdev_type_groups, 1820 + .types_attrs = vfio_ap_mdev_type_attrs, 1811 1821 }; 1812 1822 1813 1823 int vfio_ap_mdev_register(void) ··· 1820 1830 if (ret) 1821 1831 return ret; 1822 1832 1833 + matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT; 1834 + matrix_dev->mdev_types[0] = &matrix_dev->mdev_type; 1823 1835 ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device, 1824 - &vfio_ap_matrix_driver); 1836 + &vfio_ap_matrix_driver, 1837 + matrix_dev->mdev_types, 1); 1825 1838 if (ret) 1826 1839 goto err_driver; 1827 1840 return 0;
+2
drivers/s390/crypto/vfio_ap_private.h
··· 53 53 struct ap_driver *vfio_ap_drv; 54 54 struct mutex guests_lock; /* serializes access to each KVM guest */ 55 55 struct mdev_parent parent; 56 + struct mdev_type mdev_type; 57 + struct mdev_type *mdev_types[]; 56 58 }; 57 59 58 60 extern struct ap_matrix_dev *matrix_dev;
+6 -25
drivers/vfio/mdev/mdev_core.c
··· 30 30 EXPORT_SYMBOL(mdev_parent_dev); 31 31 32 32 /* 33 - * Return the index in supported_type_groups that this mdev_device was created 34 - * from. 35 - */ 36 - unsigned int mdev_get_type_group_id(struct mdev_device *mdev) 37 - { 38 - return mdev->type->type_group_id; 39 - } 40 - EXPORT_SYMBOL(mdev_get_type_group_id); 41 - 42 - /* 43 - * Used in mdev_type_attribute sysfs functions to return the index in the 44 - * supported_type_groups that the sysfs is called from. 45 - */ 46 - unsigned int mtype_get_type_group_id(struct mdev_type *mtype) 47 - { 48 - return mtype->type_group_id; 49 - } 50 - EXPORT_SYMBOL(mtype_get_type_group_id); 51 - 52 - /* 53 33 * Used in mdev_type_attribute sysfs functions to return the parent struct 54 34 * device 55 35 */ ··· 65 85 * @parent: parent structure registered 66 86 * @dev: device structure representing parent device. 67 87 * @mdev_driver: Device driver to bind to the newly created mdev 88 + * @types: Array of supported mdev types 89 + * @nr_types: Number of entries in @types 68 90 * 69 91 * Registers the @parent stucture as a parent for mdev types and thus mdev 70 92 * devices. The caller needs to hold a reference on @dev that must not be ··· 75 93 * Returns a negative value on error, otherwise 0. 76 94 */ 77 95 int mdev_register_parent(struct mdev_parent *parent, struct device *dev, 78 - struct mdev_driver *mdev_driver) 96 + struct mdev_driver *mdev_driver, struct mdev_type **types, 97 + unsigned int nr_types) 79 98 { 80 99 char *env_string = "MDEV_STATE=registered"; 81 100 char *envp[] = { env_string, NULL }; 82 101 int ret; 83 102 84 - /* check for mandatory ops */ 85 - if (!mdev_driver->supported_type_groups) 86 - return -EINVAL; 87 - 88 103 memset(parent, 0, sizeof(*parent)); 89 104 init_rwsem(&parent->unreg_sem); 90 105 parent->dev = dev; 91 106 parent->mdev_driver = mdev_driver; 107 + parent->types = types; 108 + parent->nr_types = nr_types; 92 109 93 110 if (!mdev_bus_compat_class) { 94 111 mdev_bus_compat_class = class_compat_register("mdev_bus");
+2 -3
drivers/vfio/mdev/mdev_driver.c
··· 56 56 **/ 57 57 int mdev_register_driver(struct mdev_driver *drv) 58 58 { 59 - /* initialize common driver fields */ 59 + if (!drv->types_attrs) 60 + return -EINVAL; 60 61 drv->driver.bus = &mdev_bus_type; 61 - 62 - /* register with core */ 63 62 return driver_register(&drv->driver); 64 63 } 65 64 EXPORT_SYMBOL(mdev_register_driver);
-8
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_type { 17 - struct kobject kobj; 18 - struct kobject *devices_kobj; 19 - struct mdev_parent *parent; 20 - struct list_head next; 21 - unsigned int type_group_id; 22 - }; 23 - 24 16 extern const struct attribute_group *mdev_device_groups[]; 25 17 26 18 #define to_mdev_type_attr(_attr) \
+22 -69
drivers/vfio/mdev/mdev_sysfs.c
··· 82 82 pr_debug("Releasing group %s\n", kobj->name); 83 83 /* Pairs with the get in add_mdev_supported_type() */ 84 84 put_device(type->parent->dev); 85 - kfree(type); 86 85 } 87 86 88 87 static struct kobj_type mdev_type_ktype = { ··· 89 90 .release = mdev_type_release, 90 91 }; 91 92 92 - static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent, 93 - unsigned int type_group_id) 93 + static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type) 94 94 { 95 - struct mdev_type *type; 96 - struct attribute_group *group = 97 - parent->mdev_driver->supported_type_groups[type_group_id]; 98 95 int ret; 99 - 100 - if (!group->name) { 101 - pr_err("%s: Type name empty!\n", __func__); 102 - return ERR_PTR(-EINVAL); 103 - } 104 - 105 - type = kzalloc(sizeof(*type), GFP_KERNEL); 106 - if (!type) 107 - return ERR_PTR(-ENOMEM); 108 96 109 97 type->kobj.kset = parent->mdev_types_kset; 110 98 type->parent = parent; 111 99 /* Pairs with the put in mdev_type_release() */ 112 100 get_device(parent->dev); 113 - type->type_group_id = type_group_id; 114 101 115 102 ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL, 116 103 "%s-%s", dev_driver_string(parent->dev), 117 - group->name); 104 + type->sysfs_name); 118 105 if (ret) { 119 106 kobject_put(&type->kobj); 120 - return ERR_PTR(ret); 107 + return ret; 121 108 } 122 109 123 110 ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr); ··· 116 131 goto attr_devices_failed; 117 132 } 118 133 119 - ret = sysfs_create_files(&type->kobj, 120 - (const struct attribute **)group->attrs); 121 - if (ret) { 122 - ret = -ENOMEM; 134 + ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs); 135 + if (ret) 123 136 goto attrs_failed; 124 - } 125 - return type; 137 + return 0; 126 138 127 139 attrs_failed: 128 140 kobject_put(type->devices_kobj); ··· 128 146 attr_create_failed: 129 147 kobject_del(&type->kobj); 130 148 kobject_put(&type->kobj); 131 - return ERR_PTR(ret); 149 + return ret; 132 150 } 133 151 134 - static void remove_mdev_supported_type(struct mdev_type *type) 152 + static void mdev_type_remove(struct mdev_type *type) 135 153 { 136 - struct attribute_group *group = 137 - type->parent->mdev_driver->supported_type_groups[type->type_group_id]; 154 + sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs); 138 155 139 - sysfs_remove_files(&type->kobj, 140 - (const struct attribute **)group->attrs); 141 156 kobject_put(type->devices_kobj); 142 157 sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr); 143 158 kobject_del(&type->kobj); 144 159 kobject_put(&type->kobj); 145 160 } 146 161 147 - static int add_mdev_supported_type_groups(struct mdev_parent *parent) 148 - { 149 - int i; 150 - 151 - for (i = 0; parent->mdev_driver->supported_type_groups[i]; i++) { 152 - struct mdev_type *type; 153 - 154 - type = add_mdev_supported_type(parent, i); 155 - if (IS_ERR(type)) { 156 - struct mdev_type *ltype, *tmp; 157 - 158 - list_for_each_entry_safe(ltype, tmp, &parent->type_list, 159 - next) { 160 - list_del(&ltype->next); 161 - remove_mdev_supported_type(ltype); 162 - } 163 - return PTR_ERR(type); 164 - } 165 - list_add(&type->next, &parent->type_list); 166 - } 167 - return 0; 168 - } 169 - 170 162 /* mdev sysfs functions */ 171 163 void parent_remove_sysfs_files(struct mdev_parent *parent) 172 164 { 173 - struct mdev_type *type, *tmp; 165 + int i; 174 166 175 - list_for_each_entry_safe(type, tmp, &parent->type_list, next) { 176 - list_del(&type->next); 177 - remove_mdev_supported_type(type); 178 - } 179 - 167 + for (i = 0; i < parent->nr_types; i++) 168 + mdev_type_remove(parent->types[i]); 180 169 kset_unregister(parent->mdev_types_kset); 181 170 } 182 171 183 172 int parent_create_sysfs_files(struct mdev_parent *parent) 184 173 { 185 - int ret; 174 + int ret, i; 186 175 187 176 parent->mdev_types_kset = kset_create_and_add("mdev_supported_types", 188 177 NULL, &parent->dev->kobj); 189 - 190 178 if (!parent->mdev_types_kset) 191 179 return -ENOMEM; 192 180 193 - INIT_LIST_HEAD(&parent->type_list); 194 - 195 - ret = add_mdev_supported_type_groups(parent); 196 - if (ret) 197 - goto create_err; 181 + for (i = 0; i < parent->nr_types; i++) { 182 + ret = mdev_type_add(parent, parent->types[i]); 183 + if (ret) 184 + goto out_err; 185 + } 198 186 return 0; 199 187 200 - create_err: 201 - kset_unregister(parent->mdev_types_kset); 202 - return ret; 188 + out_err: 189 + while (--i >= 0) 190 + mdev_type_remove(parent->types[i]); 191 + return 0; 203 192 } 204 193 205 194 static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
+18 -8
include/linux/mdev.h
··· 23 23 bool active; 24 24 }; 25 25 26 + struct mdev_type { 27 + /* set by the driver before calling mdev_register parent: */ 28 + const char *sysfs_name; 29 + 30 + /* set by the core, can be used drivers */ 31 + struct mdev_parent *parent; 32 + 33 + /* internal only */ 34 + struct kobject kobj; 35 + struct kobject *devices_kobj; 36 + }; 37 + 26 38 /* embedded into the struct device that the mdev devices hang off */ 27 39 struct mdev_parent { 28 40 struct device *dev; 29 41 struct mdev_driver *mdev_driver; 30 42 struct kset *mdev_types_kset; 31 - struct list_head type_list; 32 43 /* Synchronize device creation/removal with parent unregistration */ 33 44 struct rw_semaphore unreg_sem; 45 + struct mdev_type **types; 46 + unsigned int nr_types; 34 47 }; 35 48 36 49 static inline struct mdev_device *to_mdev_device(struct device *dev) ··· 51 38 return container_of(dev, struct mdev_device, dev); 52 39 } 53 40 54 - unsigned int mdev_get_type_group_id(struct mdev_device *mdev); 55 - unsigned int mtype_get_type_group_id(struct mdev_type *mtype); 56 41 struct device *mtype_get_parent_dev(struct mdev_type *mtype); 57 42 58 43 /* interface for exporting mdev supported type attributes */ ··· 77 66 * struct mdev_driver - Mediated device driver 78 67 * @probe: called when new device created 79 68 * @remove: called when device removed 80 - * @supported_type_groups: Attributes to define supported types. It is mandatory 81 - * to provide supported types. 69 + * @types_attrs: attributes to the type kobjects. 82 70 * @driver: device driver structure 83 - * 84 71 **/ 85 72 struct mdev_driver { 86 73 int (*probe)(struct mdev_device *dev); 87 74 void (*remove)(struct mdev_device *dev); 88 - struct attribute_group **supported_type_groups; 75 + const struct attribute * const *types_attrs; 89 76 struct device_driver driver; 90 77 }; 91 78 92 79 extern struct bus_type mdev_bus_type; 93 80 94 81 int mdev_register_parent(struct mdev_parent *parent, struct device *dev, 95 - struct mdev_driver *mdev_driver); 82 + struct mdev_driver *mdev_driver, struct mdev_type **types, 83 + unsigned int nr_types); 96 84 void mdev_unregister_parent(struct mdev_parent *parent); 97 85 98 86 int mdev_register_driver(struct mdev_driver *drv);
+23 -34
samples/vfio-mdev/mbochs.c
··· 99 99 #define MBOCHS_TYPE_2 "medium" 100 100 #define MBOCHS_TYPE_3 "large" 101 101 102 - static const struct mbochs_type { 102 + static struct mbochs_type { 103 + struct mdev_type type; 103 104 const char *name; 104 105 u32 mbytes; 105 106 u32 max_x; 106 107 u32 max_y; 107 108 } mbochs_types[] = { 108 109 { 110 + .type.sysfs_name = MBOCHS_TYPE_1, 109 111 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1, 110 112 .mbytes = 4, 111 113 .max_x = 800, 112 114 .max_y = 600, 113 115 }, { 116 + .type.sysfs_name = MBOCHS_TYPE_2, 114 117 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2, 115 118 .mbytes = 16, 116 119 .max_x = 1920, 117 120 .max_y = 1440, 118 121 }, { 122 + .type.sysfs_name = MBOCHS_TYPE_3, 119 123 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3, 120 124 .mbytes = 64, 121 125 .max_x = 0, ··· 127 123 }, 128 124 }; 129 125 126 + static struct mdev_type *mbochs_mdev_types[] = { 127 + &mbochs_types[0].type, 128 + &mbochs_types[1].type, 129 + &mbochs_types[2].type, 130 + }; 130 131 131 132 static dev_t mbochs_devt; 132 133 static struct class *mbochs_class; ··· 519 510 struct mdev_state *mdev_state = 520 511 container_of(vdev, struct mdev_state, vdev); 521 512 struct mdev_device *mdev = to_mdev_device(vdev->dev); 522 - const struct mbochs_type *type = 523 - &mbochs_types[mdev_get_type_group_id(mdev)]; 513 + struct mbochs_type *type = 514 + container_of(mdev->type, struct mbochs_type, type); 524 515 int avail_mbytes = atomic_read(&mbochs_avail_mbytes); 525 516 int ret = -ENOMEM; 526 517 ··· 1354 1345 static ssize_t name_show(struct mdev_type *mtype, 1355 1346 struct mdev_type_attribute *attr, char *buf) 1356 1347 { 1357 - const struct mbochs_type *type = 1358 - &mbochs_types[mtype_get_type_group_id(mtype)]; 1348 + struct mbochs_type *type = 1349 + container_of(mtype, struct mbochs_type, type); 1359 1350 1360 1351 return sprintf(buf, "%s\n", type->name); 1361 1352 } ··· 1364 1355 static ssize_t description_show(struct mdev_type *mtype, 1365 1356 struct mdev_type_attribute *attr, char *buf) 1366 1357 { 1367 - const struct mbochs_type *type = 1368 - &mbochs_types[mtype_get_type_group_id(mtype)]; 1358 + struct mbochs_type *type = 1359 + container_of(mtype, struct mbochs_type, type); 1369 1360 1370 1361 return sprintf(buf, "virtual display, %d MB video memory\n", 1371 1362 type ? type->mbytes : 0); ··· 1376 1367 struct mdev_type_attribute *attr, 1377 1368 char *buf) 1378 1369 { 1379 - const struct mbochs_type *type = 1380 - &mbochs_types[mtype_get_type_group_id(mtype)]; 1370 + struct mbochs_type *type = 1371 + container_of(mtype, struct mbochs_type, type); 1381 1372 int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes; 1382 1373 1383 1374 return sprintf(buf, "%d\n", count); ··· 1391 1382 } 1392 1383 static MDEV_TYPE_ATTR_RO(device_api); 1393 1384 1394 - static struct attribute *mdev_types_attrs[] = { 1385 + static const struct attribute *mdev_types_attrs[] = { 1395 1386 &mdev_type_attr_name.attr, 1396 1387 &mdev_type_attr_description.attr, 1397 1388 &mdev_type_attr_device_api.attr, 1398 1389 &mdev_type_attr_available_instances.attr, 1399 - NULL, 1400 - }; 1401 - 1402 - static struct attribute_group mdev_type_group1 = { 1403 - .name = MBOCHS_TYPE_1, 1404 - .attrs = mdev_types_attrs, 1405 - }; 1406 - 1407 - static struct attribute_group mdev_type_group2 = { 1408 - .name = MBOCHS_TYPE_2, 1409 - .attrs = mdev_types_attrs, 1410 - }; 1411 - 1412 - static struct attribute_group mdev_type_group3 = { 1413 - .name = MBOCHS_TYPE_3, 1414 - .attrs = mdev_types_attrs, 1415 - }; 1416 - 1417 - static struct attribute_group *mdev_type_groups[] = { 1418 - &mdev_type_group1, 1419 - &mdev_type_group2, 1420 - &mdev_type_group3, 1421 1390 NULL, 1422 1391 }; 1423 1392 ··· 1418 1431 }, 1419 1432 .probe = mbochs_probe, 1420 1433 .remove = mbochs_remove, 1421 - .supported_type_groups = mdev_type_groups, 1434 + .types_attrs = mdev_types_attrs, 1422 1435 }; 1423 1436 1424 1437 static const struct file_operations vd_fops = { ··· 1463 1476 if (ret) 1464 1477 goto err_class; 1465 1478 1466 - ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver); 1479 + ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver, 1480 + mbochs_mdev_types, 1481 + ARRAY_SIZE(mbochs_mdev_types)); 1467 1482 if (ret) 1468 1483 goto err_device; 1469 1484
+19 -31
samples/vfio-mdev/mdpy.c
··· 51 51 #define MDPY_TYPE_2 "xga" 52 52 #define MDPY_TYPE_3 "hd" 53 53 54 - static const struct mdpy_type { 54 + static struct mdpy_type { 55 + struct mdev_type type; 55 56 const char *name; 56 57 u32 format; 57 58 u32 bytepp; ··· 60 59 u32 height; 61 60 } mdpy_types[] = { 62 61 { 62 + .type.sysfs_name = MDPY_TYPE_1, 63 63 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1, 64 64 .format = DRM_FORMAT_XRGB8888, 65 65 .bytepp = 4, 66 66 .width = 640, 67 67 .height = 480, 68 68 }, { 69 + .type.sysfs_name = MDPY_TYPE_2, 69 70 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2, 70 71 .format = DRM_FORMAT_XRGB8888, 71 72 .bytepp = 4, 72 73 .width = 1024, 73 74 .height = 768, 74 75 }, { 76 + .type.sysfs_name = MDPY_TYPE_3, 75 77 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3, 76 78 .format = DRM_FORMAT_XRGB8888, 77 79 .bytepp = 4, 78 80 .width = 1920, 79 81 .height = 1080, 80 82 }, 83 + }; 84 + 85 + static struct mdev_type *mdpy_mdev_types[] = { 86 + &mdpy_types[0].type, 87 + &mdpy_types[1].type, 88 + &mdpy_types[2].type, 81 89 }; 82 90 83 91 static dev_t mdpy_devt; ··· 232 222 container_of(vdev, struct mdev_state, vdev); 233 223 struct mdev_device *mdev = to_mdev_device(vdev->dev); 234 224 const struct mdpy_type *type = 235 - &mdpy_types[mdev_get_type_group_id(mdev)]; 225 + container_of(mdev->type, struct mdpy_type, type); 236 226 u32 fbsize; 237 227 int ret = -ENOMEM; 238 228 ··· 665 655 static ssize_t name_show(struct mdev_type *mtype, 666 656 struct mdev_type_attribute *attr, char *buf) 667 657 { 668 - const struct mdpy_type *type = 669 - &mdpy_types[mtype_get_type_group_id(mtype)]; 658 + struct mdpy_type *type = container_of(mtype, struct mdpy_type, type); 670 659 671 660 return sprintf(buf, "%s\n", type->name); 672 661 } ··· 674 665 static ssize_t description_show(struct mdev_type *mtype, 675 666 struct mdev_type_attribute *attr, char *buf) 676 667 { 677 - const struct mdpy_type *type = 678 - &mdpy_types[mtype_get_type_group_id(mtype)]; 668 + struct mdpy_type *type = container_of(mtype, struct mdpy_type, type); 679 669 680 670 return sprintf(buf, "virtual display, %dx%d framebuffer\n", 681 671 type->width, type->height); ··· 696 688 } 697 689 static MDEV_TYPE_ATTR_RO(device_api); 698 690 699 - static struct attribute *mdev_types_attrs[] = { 691 + static const struct attribute *mdev_types_attrs[] = { 700 692 &mdev_type_attr_name.attr, 701 693 &mdev_type_attr_description.attr, 702 694 &mdev_type_attr_device_api.attr, 703 695 &mdev_type_attr_available_instances.attr, 704 - NULL, 705 - }; 706 - 707 - static struct attribute_group mdev_type_group1 = { 708 - .name = MDPY_TYPE_1, 709 - .attrs = mdev_types_attrs, 710 - }; 711 - 712 - static struct attribute_group mdev_type_group2 = { 713 - .name = MDPY_TYPE_2, 714 - .attrs = mdev_types_attrs, 715 - }; 716 - 717 - static struct attribute_group mdev_type_group3 = { 718 - .name = MDPY_TYPE_3, 719 - .attrs = mdev_types_attrs, 720 - }; 721 - 722 - static struct attribute_group *mdev_type_groups[] = { 723 - &mdev_type_group1, 724 - &mdev_type_group2, 725 - &mdev_type_group3, 726 696 NULL, 727 697 }; 728 698 ··· 722 736 }, 723 737 .probe = mdpy_probe, 724 738 .remove = mdpy_remove, 725 - .supported_type_groups = mdev_type_groups, 739 + .types_attrs = mdev_types_attrs, 726 740 }; 727 741 728 742 static const struct file_operations vd_fops = { ··· 765 779 if (ret) 766 780 goto err_class; 767 781 768 - ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver); 782 + ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver, 783 + mdpy_mdev_types, 784 + ARRAY_SIZE(mdpy_mdev_types)); 769 785 if (ret) 770 786 goto err_device; 771 787
+30 -30
samples/vfio-mdev/mtty.c
··· 143 143 int nr_ports; 144 144 }; 145 145 146 + static struct mtty_type { 147 + struct mdev_type type; 148 + int nr_ports; 149 + const char *name; 150 + } mtty_types[2] = { 151 + { .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port serial" }, 152 + { .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port serial" }, 153 + }; 154 + 155 + static struct mdev_type *mtty_mdev_types[] = { 156 + &mtty_types[0].type, 157 + &mtty_types[1].type, 158 + }; 159 + 146 160 static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS); 147 161 148 162 static const struct file_operations vd_fops = { ··· 721 707 struct mdev_state *mdev_state = 722 708 container_of(vdev, struct mdev_state, vdev); 723 709 struct mdev_device *mdev = to_mdev_device(vdev->dev); 724 - int nr_ports = mdev_get_type_group_id(mdev) + 1; 710 + struct mtty_type *type = 711 + container_of(mdev->type, struct mtty_type, type); 725 712 int avail_ports = atomic_read(&mdev_avail_ports); 726 713 int ret; 727 714 728 715 do { 729 - if (avail_ports < nr_ports) 716 + if (avail_ports < type->nr_ports) 730 717 return -ENOSPC; 731 718 } while (!atomic_try_cmpxchg(&mdev_avail_ports, 732 - &avail_ports, avail_ports - nr_ports)); 719 + &avail_ports, 720 + avail_ports - type->nr_ports)); 733 721 734 - mdev_state->nr_ports = nr_ports; 722 + mdev_state->nr_ports = type->nr_ports; 735 723 mdev_state->irq_index = -1; 736 724 mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE; 737 725 mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE; ··· 751 735 return 0; 752 736 753 737 err_nr_ports: 754 - atomic_add(nr_ports, &mdev_avail_ports); 738 + atomic_add(type->nr_ports, &mdev_avail_ports); 755 739 return ret; 756 740 } 757 741 ··· 1258 1242 static ssize_t name_show(struct mdev_type *mtype, 1259 1243 struct mdev_type_attribute *attr, char *buf) 1260 1244 { 1261 - static const char *name_str[2] = { "Single port serial", 1262 - "Dual port serial" }; 1245 + struct mtty_type *type = container_of(mtype, struct mtty_type, type); 1263 1246 1264 - return sysfs_emit(buf, "%s\n", 1265 - name_str[mtype_get_type_group_id(mtype)]); 1247 + return sysfs_emit(buf, "%s\n", type->name); 1266 1248 } 1267 1249 1268 1250 static MDEV_TYPE_ATTR_RO(name); ··· 1269 1255 struct mdev_type_attribute *attr, 1270 1256 char *buf) 1271 1257 { 1272 - unsigned int ports = mtype_get_type_group_id(mtype) + 1; 1258 + struct mtty_type *type = container_of(mtype, struct mtty_type, type); 1273 1259 1274 - return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / ports); 1260 + return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / 1261 + type->nr_ports); 1275 1262 } 1276 1263 1277 1264 static MDEV_TYPE_ATTR_RO(available_instances); ··· 1285 1270 1286 1271 static MDEV_TYPE_ATTR_RO(device_api); 1287 1272 1288 - static struct attribute *mdev_types_attrs[] = { 1273 + static const struct attribute *mdev_types_attrs[] = { 1289 1274 &mdev_type_attr_name.attr, 1290 1275 &mdev_type_attr_device_api.attr, 1291 1276 &mdev_type_attr_available_instances.attr, 1292 - NULL, 1293 - }; 1294 - 1295 - static struct attribute_group mdev_type_group1 = { 1296 - .name = "1", 1297 - .attrs = mdev_types_attrs, 1298 - }; 1299 - 1300 - static struct attribute_group mdev_type_group2 = { 1301 - .name = "2", 1302 - .attrs = mdev_types_attrs, 1303 - }; 1304 - 1305 - static struct attribute_group *mdev_type_groups[] = { 1306 - &mdev_type_group1, 1307 - &mdev_type_group2, 1308 1277 NULL, 1309 1278 }; 1310 1279 ··· 1310 1311 }, 1311 1312 .probe = mtty_probe, 1312 1313 .remove = mtty_remove, 1313 - .supported_type_groups = mdev_type_groups, 1314 + .types_attrs = mdev_types_attrs, 1314 1315 }; 1315 1316 1316 1317 static void mtty_device_release(struct device *dev) ··· 1362 1363 goto err_class; 1363 1364 1364 1365 ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev, 1365 - &mtty_driver); 1366 + &mtty_driver, mtty_mdev_types, 1367 + ARRAY_SIZE(mtty_mdev_types)); 1366 1368 if (ret) 1367 1369 goto err_device; 1368 1370 return 0;