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.
Unified · Split
| @@ -103,7 +103,7 @@ structure to represent a mediated device's driver:: · 102 unmodified lines | ||
| 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 | |
| @@ -310,8 +310,8 @@ struct intel_vgpu_config { · 309 unmodified lines | ||
| 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,6 +339,7 @@ struct intel_gvt { · 21 unmodified lines | ||
| 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; |
| @@ -117,17 +117,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 116 unmodified lines | ||
| 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, |
| @@ -139,12 +132,8 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 5 unmodified lines | ||
| 139 | 132 | static ssize_t description_show(struct mdev_type *mtype, |
| 140 | 133 | struct mdev_type_attribute *attr, char *buf) |
| 141 | 134 | { |
| 142 | − struct intel_vgpu_type *type; | |
| 143 | − struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt; | |
| 144 | − | |
| 145 | − type = &gvt->types[mtype_get_type_group_id(mtype)]; | |
| 146 | − if (!type) | |
| 147 | − return 0; | |
| 135 | + struct intel_vgpu_type *type = | |
| 136 | + container_of(mtype, struct intel_vgpu_type, type); | |
| 148 | 137 | |
| 149 | 138 | return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" |
| 150 | 139 | "fence: %d\nresolution: %s\n" |
| @@ -158,14 +147,7 @@ static ssize_t description_show(struct mdev_type *mtype, · 7 unmodified lines | ||
| 158 | 147 | static ssize_t name_show(struct mdev_type *mtype, |
| 159 | 148 | struct mdev_type_attribute *attr, char *buf) |
| 160 | 149 | { |
| 161 | − struct intel_vgpu_type *type; | |
| 162 | − struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt; | |
| 163 | − | |
| 164 | − type = &gvt->types[mtype_get_type_group_id(mtype)]; | |
| 165 | − if (!type) | |
| 166 | − return 0; | |
| 167 | − | |
| 168 | − return sprintf(buf, "%s\n", type->name); | |
| 150 | + return sprintf(buf, "%s\n", mtype->sysfs_name); | |
| 169 | 151 | } |
| 170 | 152 | |
| 171 | 153 | static MDEV_TYPE_ATTR_RO(available_instances); |
| @@ -173,7 +155,7 @@ static MDEV_TYPE_ATTR_RO(device_api); · 1 unmodified line | ||
| 173 | 155 | static MDEV_TYPE_ATTR_RO(description); |
| 174 | 156 | static MDEV_TYPE_ATTR_RO(name); |
| 175 | 157 | |
| 176 | −static struct attribute *gvt_type_attrs[] = { | |
| 158 | +static const struct attribute *gvt_type_attrs[] = { | |
| 177 | 159 | &mdev_type_attr_available_instances.attr, |
| 178 | 160 | &mdev_type_attr_device_api.attr, |
| 179 | 161 | &mdev_type_attr_description.attr, |
| @@ -181,51 +163,6 @@ static struct attribute *gvt_type_attrs[] = { · 1 unmodified line | ||
| 181 | 163 | NULL, |
| 182 | 164 | }; |
| 183 | 165 | |
| 184 | −static struct attribute_group *gvt_vgpu_type_groups[] = { | |
| 185 | − [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, | |
| 186 | −}; | |
| 187 | − | |
| 188 | −static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt) | |
| 189 | −{ | |
| 190 | − int i, j; | |
| 191 | − struct intel_vgpu_type *type; | |
| 192 | − struct attribute_group *group; | |
| 193 | − | |
| 194 | − for (i = 0; i < gvt->num_types; i++) { | |
| 195 | − type = &gvt->types[i]; | |
| 196 | − | |
| 197 | − group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL); | |
| 198 | − if (!group) | |
| 199 | − goto unwind; | |
| 200 | − | |
| 201 | − group->name = type->name; | |
| 202 | − group->attrs = gvt_type_attrs; | |
| 203 | − gvt_vgpu_type_groups[i] = group; | |
| 204 | − } | |
| 205 | − | |
| 206 | − return 0; | |
| 207 | − | |
| 208 | −unwind: | |
| 209 | − for (j = 0; j < i; j++) { | |
| 210 | − group = gvt_vgpu_type_groups[j]; | |
| 211 | − kfree(group); | |
| 212 | − } | |
| 213 | − | |
| 214 | − return -ENOMEM; | |
| 215 | −} | |
| 216 | − | |
| 217 | −static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt) | |
| 218 | −{ | |
| 219 | − int i; | |
| 220 | − struct attribute_group *group; | |
| 221 | − | |
| 222 | − for (i = 0; i < gvt->num_types; i++) { | |
| 223 | − group = gvt_vgpu_type_groups[i]; | |
| 224 | − gvt_vgpu_type_groups[i] = NULL; | |
| 225 | − kfree(group); | |
| 226 | − } | |
| 227 | −} | |
| 228 | − | |
| 229 | 166 | static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn, |
| 230 | 167 | unsigned long size) |
| 231 | 168 | { |
| @@ -1547,16 +1484,11 @@ static const struct attribute_group *intel_vgpu_groups[] = { · 1315 unmodified lines | ||
| 1547 | 1484 | static int intel_vgpu_init_dev(struct vfio_device *vfio_dev) |
| 1548 | 1485 | { |
| 1549 | 1486 | struct mdev_device *mdev = to_mdev_device(vfio_dev->dev); |
| 1550 | − struct device *pdev = mdev_parent_dev(mdev); | |
| 1551 | − struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt; | |
| 1552 | − struct intel_vgpu_type *type; | |
| 1553 | 1487 | struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); |
| 1488 | + struct intel_vgpu_type *type = | |
| 1489 | + container_of(mdev->type, struct intel_vgpu_type, type); | |
| 1554 | 1490 | |
| 1555 | − type = &gvt->types[mdev_get_type_group_id(mdev)]; | |
| 1556 | − if (!type) | |
| 1557 | − return -EINVAL; | |
| 1558 | − | |
| 1559 | − vgpu->gvt = gvt; | |
| 1491 | + vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt; | |
| 1560 | 1492 | return intel_gvt_create_vgpu(vgpu, type->conf); |
| 1561 | 1493 | } |
| 1562 | 1494 | |
| @@ -1625,7 +1557,7 @@ static struct mdev_driver intel_vgpu_mdev_driver = { · 62 unmodified lines | ||
| 1625 | 1557 | }, |
| 1626 | 1558 | .probe = intel_vgpu_probe, |
| 1627 | 1559 | .remove = intel_vgpu_remove, |
| 1628 | − .supported_type_groups = gvt_vgpu_type_groups, | |
| 1560 | + .types_attrs = gvt_type_attrs, | |
| 1629 | 1561 | }; |
| 1630 | 1562 | |
| 1631 | 1563 | int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn) |
| @@ -1924,7 +1856,6 @@ static void intel_gvt_clean_device(struct drm_i915_private *i915) · 292 unmodified lines | ||
| 1924 | 1856 | return; |
| 1925 | 1857 | |
| 1926 | 1858 | mdev_unregister_parent(&gvt->parent); |
| 1927 | − intel_gvt_cleanup_vgpu_type_groups(gvt); | |
| 1928 | 1859 | intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); |
| 1929 | 1860 | intel_gvt_clean_vgpu_types(gvt); |
| 1930 | 1861 | |
| @@ -2024,20 +1955,15 @@ static int intel_gvt_init_device(struct drm_i915_private *i915) · 93 unmodified lines | ||
| 2024 | 1955 | |
| 2025 | 1956 | intel_gvt_debugfs_init(gvt); |
| 2026 | 1957 | |
| 2027 | − ret = intel_gvt_init_vgpu_type_groups(gvt); | |
| 2028 | − if (ret) | |
| 2029 | − goto out_destroy_idle_vgpu; | |
| 2030 | − | |
| 2031 | 1958 | ret = mdev_register_parent(&gvt->parent, i915->drm.dev, |
| 2032 | − &intel_vgpu_mdev_driver); | |
| 1959 | + &intel_vgpu_mdev_driver, | |
| 1960 | + gvt->mdev_types, gvt->num_types); | |
| 2033 | 1961 | if (ret) |
| 2034 | − goto out_cleanup_vgpu_type_groups; | |
| 1962 | + goto out_destroy_idle_vgpu; | |
| 2035 | 1963 | |
| 2036 | 1964 | gvt_dbg_core("gvt device initialization is done\n"); |
| 2037 | 1965 | return 0; |
| 2038 | 1966 | |
| 2039 | −out_cleanup_vgpu_type_groups: | |
| 2040 | − intel_gvt_cleanup_vgpu_type_groups(gvt); | |
| 2041 | 1967 | out_destroy_idle_vgpu: |
| 2042 | 1968 | intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); |
| 2043 | 1969 | intel_gvt_debugfs_clean(gvt); |
| @@ -113,13 +113,18 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) · 112 unmodified lines | ||
| 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); |
| @@ -131,11 +136,16 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) · 5 unmodified lines | ||
| 131 | 136 | i, gvt->types[i].name, gvt->types[i].avail_instance, |
| 132 | 137 | conf->low_mm, conf->high_mm, conf->fence, |
| 133 | 138 | conf->weight, vgpu_edid_str(conf->edid)); |
| 139 | + | |
| 140 | + gvt->mdev_types[i] = &gvt->types[i].type; | |
| 141 | + gvt->mdev_types[i]->sysfs_name = gvt->types[i].name; | |
| 134 | 142 | } |
| 135 | 143 | |
| 136 | 144 | gvt->num_types = i; |
| 137 | 145 | return 0; |
| 138 | 146 | |
| 147 | +out_free_mdev_types: | |
| 148 | + kfree(gvt->mdev_types); | |
| 139 | 149 | out_free_types: |
| 140 | 150 | kfree(gvt->types); |
| 141 | 151 | return -EINVAL; |
| @@ -143,6 +153,7 @@ out_free_types: · 1 unmodified line | ||
| 143 | 153 | |
| 144 | 154 | void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt) |
| 145 | 155 | { |
| 156 | + kfree(gvt->mdev_types); | |
| 146 | 157 | kfree(gvt->types); |
| 147 | 158 | } |
| 148 | 159 | |
| @@ -202,7 +202,6 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private) · 201 unmodified lines | ||
| 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; |
| @@ -221,8 +220,11 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) · 12 unmodified lines | ||
| 221 | 220 | |
| 222 | 221 | dev_set_drvdata(&sch->dev, private); |
| 223 | 222 | |
| 223 | + private->mdev_type.sysfs_name = "io"; | |
| 224 | + private->mdev_types[0] = &private->mdev_type; | |
| 224 | 225 | ret = mdev_register_parent(&private->parent, &sch->dev, |
| 225 | − &vfio_ccw_mdev_driver); | |
| 226 | + &vfio_ccw_mdev_driver, | |
| 227 | + private->mdev_types, 1); | |
| 226 | 228 | if (ret) |
| 227 | 229 | goto out_free; |
| 228 | 230 | |
| @@ -69,23 +69,13 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 68 unmodified lines | ||
| 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 | 76 | NULL, |
| 77 | 77 | }; |
| 78 | 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 | − NULL, | |
| 87 | −}; | |
| 88 | − | |
| 89 | 79 | static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev) |
| 90 | 80 | { |
| 91 | 81 | struct vfio_ccw_private *private = |
| @@ -646,5 +636,5 @@ struct mdev_driver vfio_ccw_mdev_driver = { · 554 unmodified lines | ||
| 646 | 636 | }, |
| 647 | 637 | .probe = vfio_ccw_mdev_probe, |
| 648 | 638 | .remove = vfio_ccw_mdev_remove, |
| 649 | − .supported_type_groups = mdev_type_groups, | |
| 639 | + .types_attrs = mdev_types_attrs, | |
| 650 | 640 | }; |
| @@ -120,6 +120,8 @@ struct vfio_ccw_private { · 119 unmodified lines | ||
| 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); |
| @@ -816,23 +816,13 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 815 unmodified lines | ||
| 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 | 823 | NULL, |
| 824 | 824 | }; |
| 825 | 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 | − NULL, | |
| 834 | −}; | |
| 835 | − | |
| 836 | 826 | #define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \ |
| 837 | 827 | "already assigned to %s" |
| 838 | 828 | |
| @@ -1817,7 +1807,7 @@ static struct mdev_driver vfio_ap_matrix_driver = { · 978 unmodified lines | ||
| 1817 | 1807 | }, |
| 1818 | 1808 | .probe = vfio_ap_mdev_probe, |
| 1819 | 1809 | .remove = vfio_ap_mdev_remove, |
| 1820 | − .supported_type_groups = vfio_ap_mdev_type_groups, | |
| 1810 | + .types_attrs = vfio_ap_mdev_type_attrs, | |
| 1821 | 1811 | }; |
| 1822 | 1812 | |
| 1823 | 1813 | int vfio_ap_mdev_register(void) |
| @@ -1830,8 +1820,11 @@ int vfio_ap_mdev_register(void) · 6 unmodified lines | ||
| 1830 | 1820 | if (ret) |
| 1831 | 1821 | return ret; |
| 1832 | 1822 | |
| 1823 | + matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT; | |
| 1824 | + matrix_dev->mdev_types[0] = &matrix_dev->mdev_type; | |
| 1833 | 1825 | ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device, |
| 1834 | − &vfio_ap_matrix_driver); | |
| 1826 | + &vfio_ap_matrix_driver, | |
| 1827 | + matrix_dev->mdev_types, 1); | |
| 1835 | 1828 | if (ret) |
| 1836 | 1829 | goto err_driver; |
| 1837 | 1830 | return 0; |
| @@ -53,6 +53,8 @@ struct ap_matrix_dev { · 52 unmodified lines | ||
| 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; |
| @@ -29,26 +29,6 @@ struct device *mdev_parent_dev(struct mdev_device *mdev) · 28 unmodified lines | ||
| 29 | 29 | } |
| 30 | 30 | EXPORT_SYMBOL(mdev_parent_dev); |
| 31 | 31 | |
| 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 | 32 | /* |
| 53 | 33 | * Used in mdev_type_attribute sysfs functions to return the parent struct |
| 54 | 34 | * device |
| @@ -85,6 +65,8 @@ static int mdev_device_remove_cb(struct device *dev, void *data) · 30 unmodified lines | ||
| 85 | 65 | * @parent: parent structure registered |
| 86 | 66 | * @dev: device structure representing parent device. |
| 87 | 67 | * @mdev_driver: Device driver to bind to the newly created mdev |
| 68 | + * @types: Array of supported mdev types | |
| 69 | + * @nr_types: Number of entries in @types | |
| 88 | 70 | * |
| 89 | 71 | * Registers the @parent stucture as a parent for mdev types and thus mdev |
| 90 | 72 | * devices. The caller needs to hold a reference on @dev that must not be |
| @@ -93,20 +75,19 @@ static int mdev_device_remove_cb(struct device *dev, void *data) · 2 unmodified lines | ||
| 93 | 75 | * Returns a negative value on error, otherwise 0. |
| 94 | 76 | */ |
| 95 | 77 | int mdev_register_parent(struct mdev_parent *parent, struct device *dev, |
| 96 | − struct mdev_driver *mdev_driver) | |
| 78 | + struct mdev_driver *mdev_driver, struct mdev_type **types, | |
| 79 | + unsigned int nr_types) | |
| 97 | 80 | { |
| 98 | 81 | char *env_string = "MDEV_STATE=registered"; |
| 99 | 82 | char *envp[] = { env_string, NULL }; |
| 100 | 83 | int ret; |
| 101 | 84 | |
| 102 | − /* check for mandatory ops */ | |
| 103 | − if (!mdev_driver->supported_type_groups) | |
| 104 | − return -EINVAL; | |
| 105 | − | |
| 106 | 85 | memset(parent, 0, sizeof(*parent)); |
| 107 | 86 | init_rwsem(&parent->unreg_sem); |
| 108 | 87 | parent->dev = dev; |
| 109 | 88 | parent->mdev_driver = mdev_driver; |
| 89 | + parent->types = types; | |
| 90 | + parent->nr_types = nr_types; | |
| 110 | 91 | |
| 111 | 92 | if (!mdev_bus_compat_class) { |
| 112 | 93 | mdev_bus_compat_class = class_compat_register("mdev_bus"); |
| @@ -56,10 +56,9 @@ EXPORT_SYMBOL_GPL(mdev_bus_type); · 55 unmodified lines | ||
| 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); |
| @@ -13,14 +13,6 @@ · 12 unmodified lines | ||
| 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) \ |
| @@ -82,7 +82,6 @@ static void mdev_type_release(struct kobject *kobj) · 81 unmodified lines | ||
| 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 = { |
| @@ -90,35 +89,21 @@ static struct kobj_type mdev_type_ktype = { · 1 unmodified line | ||
| 90 | 89 | .release = mdev_type_release, |
| 91 | 90 | }; |
| 92 | 91 | |
| 93 | −static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent, | |
| 94 | − unsigned int type_group_id) | |
| 92 | +static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type) | |
| 95 | 93 | { |
| 96 | − struct mdev_type *type; | |
| 97 | − struct attribute_group *group = | |
| 98 | − parent->mdev_driver->supported_type_groups[type_group_id]; | |
| 99 | 94 | int ret; |
| 100 | 95 | |
| 101 | − if (!group->name) { | |
| 102 | − pr_err("%s: Type name empty!\n", __func__); | |
| 103 | − return ERR_PTR(-EINVAL); | |
| 104 | − } | |
| 105 | − | |
| 106 | − type = kzalloc(sizeof(*type), GFP_KERNEL); | |
| 107 | − if (!type) | |
| 108 | − return ERR_PTR(-ENOMEM); | |
| 109 | − | |
| 110 | 96 | type->kobj.kset = parent->mdev_types_kset; |
| 111 | 97 | type->parent = parent; |
| 112 | 98 | /* Pairs with the put in mdev_type_release() */ |
| 113 | 99 | get_device(parent->dev); |
| 114 | − type->type_group_id = type_group_id; | |
| 115 | 100 | |
| 116 | 101 | ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL, |
| 117 | 102 | "%s-%s", dev_driver_string(parent->dev), |
| 118 | − group->name); | |
| 103 | + type->sysfs_name); | |
| 119 | 104 | if (ret) { |
| 120 | 105 | kobject_put(&type->kobj); |
| 121 | − return ERR_PTR(ret); | |
| 106 | + return ret; | |
| 122 | 107 | } |
| 123 | 108 | |
| 124 | 109 | ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr); |
| @@ -131,13 +116,10 @@ static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent, · 6 unmodified lines | ||
| 131 | 116 | goto attr_devices_failed; |
| 132 | 117 | } |
| 133 | 118 | |
| 134 | − ret = sysfs_create_files(&type->kobj, | |
| 135 | − (const struct attribute **)group->attrs); | |
| 136 | − if (ret) { | |
| 137 | − ret = -ENOMEM; | |
| 119 | + ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs); | |
| 120 | + if (ret) | |
| 138 | 121 | goto attrs_failed; |
| 139 | − } | |
| 140 | − return type; | |
| 122 | + return 0; | |
| 141 | 123 | |
| 142 | 124 | attrs_failed: |
| 143 | 125 | kobject_put(type->devices_kobj); |
| @@ -146,78 +128,49 @@ attr_devices_failed: · 2 unmodified lines | ||
| 146 | 128 | attr_create_failed: |
| 147 | 129 | kobject_del(&type->kobj); |
| 148 | 130 | kobject_put(&type->kobj); |
| 149 | − return ERR_PTR(ret); | |
| 131 | + return ret; | |
| 150 | 132 | } |
| 151 | 133 | |
| 152 | −static void remove_mdev_supported_type(struct mdev_type *type) | |
| 134 | +static void mdev_type_remove(struct mdev_type *type) | |
| 153 | 135 | { |
| 154 | − struct attribute_group *group = | |
| 155 | − type->parent->mdev_driver->supported_type_groups[type->type_group_id]; | |
| 136 | + sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs); | |
| 156 | 137 | |
| 157 | − sysfs_remove_files(&type->kobj, | |
| 158 | − (const struct attribute **)group->attrs); | |
| 159 | 138 | kobject_put(type->devices_kobj); |
| 160 | 139 | sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr); |
| 161 | 140 | kobject_del(&type->kobj); |
| 162 | 141 | kobject_put(&type->kobj); |
| 163 | 142 | } |
| 164 | 143 | |
| 165 | −static int add_mdev_supported_type_groups(struct mdev_parent *parent) | |
| 166 | −{ | |
| 167 | − int i; | |
| 168 | − | |
| 169 | − for (i = 0; parent->mdev_driver->supported_type_groups[i]; i++) { | |
| 170 | − struct mdev_type *type; | |
| 171 | − | |
| 172 | − type = add_mdev_supported_type(parent, i); | |
| 173 | − if (IS_ERR(type)) { | |
| 174 | − struct mdev_type *ltype, *tmp; | |
| 175 | − | |
| 176 | − list_for_each_entry_safe(ltype, tmp, &parent->type_list, | |
| 177 | − next) { | |
| 178 | − list_del(<ype->next); | |
| 179 | − remove_mdev_supported_type(ltype); | |
| 180 | − } | |
| 181 | − return PTR_ERR(type); | |
| 182 | − } | |
| 183 | − list_add(&type->next, &parent->type_list); | |
| 184 | − } | |
| 185 | − return 0; | |
| 186 | −} | |
| 187 | − | |
| 188 | 144 | /* mdev sysfs functions */ |
| 189 | 145 | void parent_remove_sysfs_files(struct mdev_parent *parent) |
| 190 | 146 | { |
| 191 | − struct mdev_type *type, *tmp; | |
| 192 | − | |
| 193 | − list_for_each_entry_safe(type, tmp, &parent->type_list, next) { | |
| 194 | − list_del(&type->next); | |
| 195 | − remove_mdev_supported_type(type); | |
| 196 | − } | |
| 147 | + int i; | |
| 197 | 148 | |
| 149 | + for (i = 0; i < parent->nr_types; i++) | |
| 150 | + mdev_type_remove(parent->types[i]); | |
| 198 | 151 | kset_unregister(parent->mdev_types_kset); |
| 199 | 152 | } |
| 200 | 153 | |
| 201 | 154 | int parent_create_sysfs_files(struct mdev_parent *parent) |
| 202 | 155 | { |
| 203 | − int ret; | |
| 156 | + int ret, i; | |
| 204 | 157 | |
| 205 | 158 | parent->mdev_types_kset = kset_create_and_add("mdev_supported_types", |
| 206 | 159 | NULL, &parent->dev->kobj); |
| 207 | − | |
| 208 | 160 | if (!parent->mdev_types_kset) |
| 209 | 161 | return -ENOMEM; |
| 210 | 162 | |
| 211 | − INIT_LIST_HEAD(&parent->type_list); | |
| 212 | − | |
| 213 | − ret = add_mdev_supported_type_groups(parent); | |
| 214 | − if (ret) | |
| 215 | − goto create_err; | |
| 163 | + for (i = 0; i < parent->nr_types; i++) { | |
| 164 | + ret = mdev_type_add(parent, parent->types[i]); | |
| 165 | + if (ret) | |
| 166 | + goto out_err; | |
| 167 | + } | |
| 216 | 168 | return 0; |
| 217 | 169 | |
| 218 | −create_err: | |
| 219 | − kset_unregister(parent->mdev_types_kset); | |
| 220 | − return ret; | |
| 170 | +out_err: | |
| 171 | + while (--i >= 0) | |
| 172 | + mdev_type_remove(parent->types[i]); | |
| 173 | + return 0; | |
| 221 | 174 | } |
| 222 | 175 | |
| 223 | 176 | static ssize_t remove_store(struct device *dev, struct device_attribute *attr, |
| @@ -23,14 +23,27 @@ struct mdev_device { · 22 unmodified lines | ||
| 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) |
| @@ -38,8 +51,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev) · 1 unmodified line | ||
| 38 | 51 | return container_of(dev, struct mdev_device, dev); |
| 39 | 52 | } |
| 40 | 53 | |
| 41 | −unsigned int mdev_get_type_group_id(struct mdev_device *mdev); | |
| 42 | −unsigned int mtype_get_type_group_id(struct mdev_type *mtype); | |
| 43 | 54 | struct device *mtype_get_parent_dev(struct mdev_type *mtype); |
| 44 | 55 | |
| 45 | 56 | /* interface for exporting mdev supported type attributes */ |
| @@ -66,22 +77,21 @@ struct mdev_type_attribute mdev_type_attr_##_name = \ · 20 unmodified lines | ||
| 66 | 77 | * struct mdev_driver - Mediated device driver |
| 67 | 78 | * @probe: called when new device created |
| 68 | 79 | * @remove: called when device removed |
| 69 | − * @supported_type_groups: Attributes to define supported types. It is mandatory | |
| 70 | − * to provide supported types. | |
| 80 | + * @types_attrs: attributes to the type kobjects. | |
| 71 | 81 | * @driver: device driver structure |
| 72 | − * | |
| 73 | 82 | **/ |
| 74 | 83 | struct mdev_driver { |
| 75 | 84 | int (*probe)(struct mdev_device *dev); |
| 76 | 85 | void (*remove)(struct mdev_device *dev); |
| 77 | − struct attribute_group **supported_type_groups; | |
| 86 | + const struct attribute * const *types_attrs; | |
| 78 | 87 | struct device_driver driver; |
| 79 | 88 | }; |
| 80 | 89 | |
| 81 | 90 | extern struct bus_type mdev_bus_type; |
| 82 | 91 | |
| 83 | 92 | int mdev_register_parent(struct mdev_parent *parent, struct device *dev, |
| 84 | − struct mdev_driver *mdev_driver); | |
| 93 | + struct mdev_driver *mdev_driver, struct mdev_type **types, | |
| 94 | + unsigned int nr_types); | |
| 85 | 95 | void mdev_unregister_parent(struct mdev_parent *parent); |
| 86 | 96 | |
| 87 | 97 | int mdev_register_driver(struct mdev_driver *drv); |
| @@ -99,23 +99,27 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices"); · 98 unmodified lines | ||
| 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, |
| @@ -123,6 +127,11 @@ static const struct mbochs_type { · 1 unmodified line | ||
| 123 | 127 | }, |
| 124 | 128 | }; |
| 125 | 129 | |
| 130 | +static struct mdev_type *mbochs_mdev_types[] = { | |
| 131 | + &mbochs_types[0].type, | |
| 132 | + &mbochs_types[1].type, | |
| 133 | + &mbochs_types[2].type, | |
| 134 | +}; | |
| 126 | 135 | |
| 127 | 136 | static dev_t mbochs_devt; |
| 128 | 137 | static struct class *mbochs_class; |
| @@ -510,8 +519,8 @@ static int mbochs_init_dev(struct vfio_device *vdev) · 381 unmodified lines | ||
| 510 | 519 | struct mdev_state *mdev_state = |
| 511 | 520 | container_of(vdev, struct mdev_state, vdev); |
| 512 | 521 | struct mdev_device *mdev = to_mdev_device(vdev->dev); |
| 513 | − const struct mbochs_type *type = | |
| 514 | − &mbochs_types[mdev_get_type_group_id(mdev)]; | |
| 522 | + struct mbochs_type *type = | |
| 523 | + container_of(mdev->type, struct mbochs_type, type); | |
| 515 | 524 | int avail_mbytes = atomic_read(&mbochs_avail_mbytes); |
| 516 | 525 | int ret = -ENOMEM; |
| 517 | 526 | |
| @@ -1345,8 +1354,8 @@ static const struct attribute_group *mdev_dev_groups[] = { · 827 unmodified lines | ||
| 1345 | 1354 | static ssize_t name_show(struct mdev_type *mtype, |
| 1346 | 1355 | struct mdev_type_attribute *attr, char *buf) |
| 1347 | 1356 | { |
| 1348 | − const struct mbochs_type *type = | |
| 1349 | − &mbochs_types[mtype_get_type_group_id(mtype)]; | |
| 1357 | + struct mbochs_type *type = | |
| 1358 | + container_of(mtype, struct mbochs_type, type); | |
| 1350 | 1359 | |
| 1351 | 1360 | return sprintf(buf, "%s\n", type->name); |
| 1352 | 1361 | } |
| @@ -1355,8 +1364,8 @@ static MDEV_TYPE_ATTR_RO(name); · 2 unmodified lines | ||
| 1355 | 1364 | static ssize_t description_show(struct mdev_type *mtype, |
| 1356 | 1365 | struct mdev_type_attribute *attr, char *buf) |
| 1357 | 1366 | { |
| 1358 | − const struct mbochs_type *type = | |
| 1359 | − &mbochs_types[mtype_get_type_group_id(mtype)]; | |
| 1367 | + struct mbochs_type *type = | |
| 1368 | + container_of(mtype, struct mbochs_type, type); | |
| 1360 | 1369 | |
| 1361 | 1370 | return sprintf(buf, "virtual display, %d MB video memory\n", |
| 1362 | 1371 | type ? type->mbytes : 0); |
| @@ -1367,8 +1376,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 4 unmodified lines | ||
| 1367 | 1376 | struct mdev_type_attribute *attr, |
| 1368 | 1377 | char *buf) |
| 1369 | 1378 | { |
| 1370 | − const struct mbochs_type *type = | |
| 1371 | − &mbochs_types[mtype_get_type_group_id(mtype)]; | |
| 1379 | + struct mbochs_type *type = | |
| 1380 | + container_of(mtype, struct mbochs_type, type); | |
| 1372 | 1381 | int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes; |
| 1373 | 1382 | |
| 1374 | 1383 | return sprintf(buf, "%d\n", count); |
| @@ -1382,7 +1391,7 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 7 unmodified lines | ||
| 1382 | 1391 | } |
| 1383 | 1392 | static MDEV_TYPE_ATTR_RO(device_api); |
| 1384 | 1393 | |
| 1385 | −static struct attribute *mdev_types_attrs[] = { | |
| 1394 | +static const struct attribute *mdev_types_attrs[] = { | |
| 1386 | 1395 | &mdev_type_attr_name.attr, |
| 1387 | 1396 | &mdev_type_attr_description.attr, |
| 1388 | 1397 | &mdev_type_attr_device_api.attr, |
| @@ -1390,28 +1399,6 @@ static struct attribute *mdev_types_attrs[] = { · 1 unmodified line | ||
| 1390 | 1399 | NULL, |
| 1391 | 1400 | }; |
| 1392 | 1401 | |
| 1393 | −static struct attribute_group mdev_type_group1 = { | |
| 1394 | − .name = MBOCHS_TYPE_1, | |
| 1395 | − .attrs = mdev_types_attrs, | |
| 1396 | −}; | |
| 1397 | − | |
| 1398 | −static struct attribute_group mdev_type_group2 = { | |
| 1399 | − .name = MBOCHS_TYPE_2, | |
| 1400 | − .attrs = mdev_types_attrs, | |
| 1401 | −}; | |
| 1402 | − | |
| 1403 | −static struct attribute_group mdev_type_group3 = { | |
| 1404 | − .name = MBOCHS_TYPE_3, | |
| 1405 | − .attrs = mdev_types_attrs, | |
| 1406 | −}; | |
| 1407 | − | |
| 1408 | −static struct attribute_group *mdev_type_groups[] = { | |
| 1409 | − &mdev_type_group1, | |
| 1410 | − &mdev_type_group2, | |
| 1411 | − &mdev_type_group3, | |
| 1412 | − NULL, | |
| 1413 | −}; | |
| 1414 | − | |
| 1415 | 1402 | static const struct vfio_device_ops mbochs_dev_ops = { |
| 1416 | 1403 | .close_device = mbochs_close_device, |
| 1417 | 1404 | .init = mbochs_init_dev, |
| @@ -1431,7 +1418,7 @@ static struct mdev_driver mbochs_driver = { · 13 unmodified lines | ||
| 1431 | 1418 | }, |
| 1432 | 1419 | .probe = mbochs_probe, |
| 1433 | 1420 | .remove = mbochs_remove, |
| 1434 | − .supported_type_groups = mdev_type_groups, | |
| 1421 | + .types_attrs = mdev_types_attrs, | |
| 1435 | 1422 | }; |
| 1436 | 1423 | |
| 1437 | 1424 | static const struct file_operations vd_fops = { |
| @@ -1476,7 +1463,9 @@ static int __init mbochs_dev_init(void) · 38 unmodified lines | ||
| 1476 | 1463 | if (ret) |
| 1477 | 1464 | goto err_class; |
| 1478 | 1465 | |
| 1479 | − ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver); | |
| 1466 | + ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver, | |
| 1467 | + mbochs_mdev_types, | |
| 1468 | + ARRAY_SIZE(mbochs_mdev_types)); | |
| 1480 | 1469 | if (ret) |
| 1481 | 1470 | goto err_device; |
| 1482 | 1471 | |
| @@ -51,7 +51,8 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices"); · 50 unmodified lines | ||
| 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; |
| @@ -59,18 +60,21 @@ static const struct mdpy_type { · 1 unmodified line | ||
| 59 | 60 | u32 height; |
| 60 | 61 | } mdpy_types[] = { |
| 61 | 62 | { |
| 63 | + .type.sysfs_name = MDPY_TYPE_1, | |
| 62 | 64 | .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1, |
| 63 | 65 | .format = DRM_FORMAT_XRGB8888, |
| 64 | 66 | .bytepp = 4, |
| 65 | 67 | .width = 640, |
| 66 | 68 | .height = 480, |
| 67 | 69 | }, { |
| 70 | + .type.sysfs_name = MDPY_TYPE_2, | |
| 68 | 71 | .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2, |
| 69 | 72 | .format = DRM_FORMAT_XRGB8888, |
| 70 | 73 | .bytepp = 4, |
| 71 | 74 | .width = 1024, |
| 72 | 75 | .height = 768, |
| 73 | 76 | }, { |
| 77 | + .type.sysfs_name = MDPY_TYPE_3, | |
| 74 | 78 | .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3, |
| 75 | 79 | .format = DRM_FORMAT_XRGB8888, |
| 76 | 80 | .bytepp = 4, |
| @@ -79,6 +83,12 @@ static const struct mdpy_type { · 2 unmodified lines | ||
| 79 | 83 | }, |
| 80 | 84 | }; |
| 81 | 85 | |
| 86 | +static struct mdev_type *mdpy_mdev_types[] = { | |
| 87 | + &mdpy_types[0].type, | |
| 88 | + &mdpy_types[1].type, | |
| 89 | + &mdpy_types[2].type, | |
| 90 | +}; | |
| 91 | + | |
| 82 | 92 | static dev_t mdpy_devt; |
| 83 | 93 | static struct class *mdpy_class; |
| 84 | 94 | static struct cdev mdpy_cdev; |
| @@ -222,7 +232,7 @@ static int mdpy_init_dev(struct vfio_device *vdev) · 137 unmodified lines | ||
| 222 | 232 | container_of(vdev, struct mdev_state, vdev); |
| 223 | 233 | struct mdev_device *mdev = to_mdev_device(vdev->dev); |
| 224 | 234 | const struct mdpy_type *type = |
| 225 | − &mdpy_types[mdev_get_type_group_id(mdev)]; | |
| 235 | + container_of(mdev->type, struct mdpy_type, type); | |
| 226 | 236 | u32 fbsize; |
| 227 | 237 | int ret = -ENOMEM; |
| 228 | 238 | |
| @@ -655,8 +665,7 @@ static const struct attribute_group *mdev_dev_groups[] = { · 426 unmodified lines | ||
| 655 | 665 | static ssize_t name_show(struct mdev_type *mtype, |
| 656 | 666 | struct mdev_type_attribute *attr, char *buf) |
| 657 | 667 | { |
| 658 | − const struct mdpy_type *type = | |
| 659 | − &mdpy_types[mtype_get_type_group_id(mtype)]; | |
| 668 | + struct mdpy_type *type = container_of(mtype, struct mdpy_type, type); | |
| 660 | 669 | |
| 661 | 670 | return sprintf(buf, "%s\n", type->name); |
| 662 | 671 | } |
| @@ -665,8 +674,7 @@ static MDEV_TYPE_ATTR_RO(name); · 2 unmodified lines | ||
| 665 | 674 | static ssize_t description_show(struct mdev_type *mtype, |
| 666 | 675 | struct mdev_type_attribute *attr, char *buf) |
| 667 | 676 | { |
| 668 | − const struct mdpy_type *type = | |
| 669 | − &mdpy_types[mtype_get_type_group_id(mtype)]; | |
| 677 | + struct mdpy_type *type = container_of(mtype, struct mdpy_type, type); | |
| 670 | 678 | |
| 671 | 679 | return sprintf(buf, "virtual display, %dx%d framebuffer\n", |
| 672 | 680 | type->width, type->height); |
| @@ -688,7 +696,7 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 15 unmodified lines | ||
| 688 | 696 | } |
| 689 | 697 | static MDEV_TYPE_ATTR_RO(device_api); |
| 690 | 698 | |
| 691 | −static struct attribute *mdev_types_attrs[] = { | |
| 699 | +static const struct attribute *mdev_types_attrs[] = { | |
| 692 | 700 | &mdev_type_attr_name.attr, |
| 693 | 701 | &mdev_type_attr_description.attr, |
| 694 | 702 | &mdev_type_attr_device_api.attr, |
| @@ -696,28 +704,6 @@ static struct attribute *mdev_types_attrs[] = { · 1 unmodified line | ||
| 696 | 704 | NULL, |
| 697 | 705 | }; |
| 698 | 706 | |
| 699 | −static struct attribute_group mdev_type_group1 = { | |
| 700 | − .name = MDPY_TYPE_1, | |
| 701 | − .attrs = mdev_types_attrs, | |
| 702 | −}; | |
| 703 | − | |
| 704 | −static struct attribute_group mdev_type_group2 = { | |
| 705 | − .name = MDPY_TYPE_2, | |
| 706 | − .attrs = mdev_types_attrs, | |
| 707 | −}; | |
| 708 | − | |
| 709 | −static struct attribute_group mdev_type_group3 = { | |
| 710 | − .name = MDPY_TYPE_3, | |
| 711 | − .attrs = mdev_types_attrs, | |
| 712 | −}; | |
| 713 | − | |
| 714 | −static struct attribute_group *mdev_type_groups[] = { | |
| 715 | − &mdev_type_group1, | |
| 716 | − &mdev_type_group2, | |
| 717 | − &mdev_type_group3, | |
| 718 | − NULL, | |
| 719 | −}; | |
| 720 | − | |
| 721 | 707 | static const struct vfio_device_ops mdpy_dev_ops = { |
| 722 | 708 | .init = mdpy_init_dev, |
| 723 | 709 | .release = mdpy_release_dev, |
| @@ -736,7 +722,7 @@ static struct mdev_driver mdpy_driver = { · 12 unmodified lines | ||
| 736 | 722 | }, |
| 737 | 723 | .probe = mdpy_probe, |
| 738 | 724 | .remove = mdpy_remove, |
| 739 | − .supported_type_groups = mdev_type_groups, | |
| 725 | + .types_attrs = mdev_types_attrs, | |
| 740 | 726 | }; |
| 741 | 727 | |
| 742 | 728 | static const struct file_operations vd_fops = { |
| @@ -779,7 +765,9 @@ static int __init mdpy_dev_init(void) · 36 unmodified lines | ||
| 779 | 765 | if (ret) |
| 780 | 766 | goto err_class; |
| 781 | 767 | |
| 782 | − ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver); | |
| 768 | + ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver, | |
| 769 | + mdpy_mdev_types, | |
| 770 | + ARRAY_SIZE(mdpy_mdev_types)); | |
| 783 | 771 | if (ret) |
| 784 | 772 | goto err_device; |
| 785 | 773 | |
| @@ -143,6 +143,20 @@ struct mdev_state { · 142 unmodified lines | ||
| 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 = { |
| @@ -707,17 +721,19 @@ static int mtty_init_dev(struct vfio_device *vdev) · 558 unmodified lines | ||
| 707 | 721 | struct mdev_state *mdev_state = |
| 708 | 722 | container_of(vdev, struct mdev_state, vdev); |
| 709 | 723 | struct mdev_device *mdev = to_mdev_device(vdev->dev); |
| 710 | − int nr_ports = mdev_get_type_group_id(mdev) + 1; | |
| 724 | + struct mtty_type *type = | |
| 725 | + container_of(mdev->type, struct mtty_type, type); | |
| 711 | 726 | int avail_ports = atomic_read(&mdev_avail_ports); |
| 712 | 727 | int ret; |
| 713 | 728 | |
| 714 | 729 | do { |
| 715 | − if (avail_ports < nr_ports) | |
| 730 | + if (avail_ports < type->nr_ports) | |
| 716 | 731 | return -ENOSPC; |
| 717 | 732 | } while (!atomic_try_cmpxchg(&mdev_avail_ports, |
| 718 | − &avail_ports, avail_ports - nr_ports)); | |
| 733 | + &avail_ports, | |
| 734 | + avail_ports - type->nr_ports)); | |
| 719 | 735 | |
| 720 | − mdev_state->nr_ports = nr_ports; | |
| 736 | + mdev_state->nr_ports = type->nr_ports; | |
| 721 | 737 | mdev_state->irq_index = -1; |
| 722 | 738 | mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE; |
| 723 | 739 | mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE; |
| @@ -735,7 +751,7 @@ static int mtty_init_dev(struct vfio_device *vdev) · 11 unmodified lines | ||
| 735 | 751 | return 0; |
| 736 | 752 | |
| 737 | 753 | err_nr_ports: |
| 738 | − atomic_add(nr_ports, &mdev_avail_ports); | |
| 754 | + atomic_add(type->nr_ports, &mdev_avail_ports); | |
| 739 | 755 | return ret; |
| 740 | 756 | } |
| 741 | 757 | |
| @@ -1242,11 +1258,9 @@ static const struct attribute_group *mdev_dev_groups[] = { · 500 unmodified lines | ||
| 1242 | 1258 | static ssize_t name_show(struct mdev_type *mtype, |
| 1243 | 1259 | struct mdev_type_attribute *attr, char *buf) |
| 1244 | 1260 | { |
| 1245 | − static const char *name_str[2] = { "Single port serial", | |
| 1246 | − "Dual port serial" }; | |
| 1261 | + struct mtty_type *type = container_of(mtype, struct mtty_type, type); | |
| 1247 | 1262 | |
| 1248 | − return sysfs_emit(buf, "%s\n", | |
| 1249 | − name_str[mtype_get_type_group_id(mtype)]); | |
| 1263 | + return sysfs_emit(buf, "%s\n", type->name); | |
| 1250 | 1264 | } |
| 1251 | 1265 | |
| 1252 | 1266 | static MDEV_TYPE_ATTR_RO(name); |
| @@ -1255,9 +1269,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 2 unmodified lines | ||
| 1255 | 1269 | struct mdev_type_attribute *attr, |
| 1256 | 1270 | char *buf) |
| 1257 | 1271 | { |
| 1258 | − unsigned int ports = mtype_get_type_group_id(mtype) + 1; | |
| 1272 | + struct mtty_type *type = container_of(mtype, struct mtty_type, type); | |
| 1259 | 1273 | |
| 1260 | − return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / ports); | |
| 1274 | + return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / | |
| 1275 | + type->nr_ports); | |
| 1261 | 1276 | } |
| 1262 | 1277 | |
| 1263 | 1278 | static MDEV_TYPE_ATTR_RO(available_instances); |
| @@ -1270,29 +1285,13 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 6 unmodified lines | ||
| 1270 | 1285 | |
| 1271 | 1286 | static MDEV_TYPE_ATTR_RO(device_api); |
| 1272 | 1287 | |
| 1273 | −static struct attribute *mdev_types_attrs[] = { | |
| 1288 | +static const struct attribute *mdev_types_attrs[] = { | |
| 1274 | 1289 | &mdev_type_attr_name.attr, |
| 1275 | 1290 | &mdev_type_attr_device_api.attr, |
| 1276 | 1291 | &mdev_type_attr_available_instances.attr, |
| 1277 | 1292 | NULL, |
| 1278 | 1293 | }; |
| 1279 | 1294 | |
| 1280 | −static struct attribute_group mdev_type_group1 = { | |
| 1281 | − .name = "1", | |
| 1282 | − .attrs = mdev_types_attrs, | |
| 1283 | −}; | |
| 1284 | − | |
| 1285 | −static struct attribute_group mdev_type_group2 = { | |
| 1286 | − .name = "2", | |
| 1287 | − .attrs = mdev_types_attrs, | |
| 1288 | −}; | |
| 1289 | − | |
| 1290 | −static struct attribute_group *mdev_type_groups[] = { | |
| 1291 | − &mdev_type_group1, | |
| 1292 | − &mdev_type_group2, | |
| 1293 | − NULL, | |
| 1294 | −}; | |
| 1295 | − | |
| 1296 | 1295 | static const struct vfio_device_ops mtty_dev_ops = { |
| 1297 | 1296 | .name = "vfio-mtty", |
| 1298 | 1297 | .init = mtty_init_dev, |
| @@ -1311,7 +1310,7 @@ static struct mdev_driver mtty_driver = { · 12 unmodified lines | ||
| 1311 | 1310 | }, |
| 1312 | 1311 | .probe = mtty_probe, |
| 1313 | 1312 | .remove = mtty_remove, |
| 1314 | − .supported_type_groups = mdev_type_groups, | |
| 1313 | + .types_attrs = mdev_types_attrs, | |
| 1315 | 1314 | }; |
| 1316 | 1315 | |
| 1317 | 1316 | static void mtty_device_release(struct device *dev) |
| @@ -1363,7 +1362,8 @@ static int __init mtty_dev_init(void) · 45 unmodified lines | ||
| 1363 | 1362 | goto err_class; |
| 1364 | 1363 | |
| 1365 | 1364 | ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev, |
| 1366 | − &mtty_driver); | |
| 1365 | + &mtty_driver, mtty_mdev_types, | |
| 1366 | + ARRAY_SIZE(mtty_mdev_types)); | |
| 1367 | 1367 | if (ret) |
| 1368 | 1368 | goto err_device; |
| 1369 | 1369 | return 0; |