History

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.

Christoph Hellwig committed 4 years ago

Commit da44c341 parent 89345d517 files · +165 −326Browse files

Unified · Split

17 files
  1. Documentation/driver-api/vfio-mediated-device.rst +1 −1
  2. drivers/gpu/drm/i915/gvt/gvt.h +2 −1
  3. drivers/gpu/drm/i915/gvt/kvmgt.c +14 −88
  4. drivers/gpu/drm/i915/gvt/vgpu.c +12 −1
  5. drivers/s390/cio/vfio_ccw_drv.c +4 −2
  6. drivers/s390/cio/vfio_ccw_ops.c +2 −12
  7. drivers/s390/cio/vfio_ccw_private.h +2 −0
  8. drivers/s390/crypto/vfio_ap_ops.c +6 −13
  9. drivers/s390/crypto/vfio_ap_private.h +2 −0
  10. drivers/vfio/mdev/mdev_core.c +6 −25
  11. drivers/vfio/mdev/mdev_driver.c +2 −3
  12. drivers/vfio/mdev/mdev_private.h +0 −8
  13. drivers/vfio/mdev/mdev_sysfs.c +22 −69
  14. include/linux/mdev.h +18 −8
  15. samples/vfio-mdev/mbochs.c +23 −34
  16. samples/vfio-mdev/mdpy.c +19 −31
  17. samples/vfio-mdev/mtty.c +30 −30
Documentation/driver-api/vfio-mediated-device.rst+1−1
@@ -103,7 +103,7 @@ structure to represent a mediated device's driver:: · 102 unmodified lines
103 struct mdev_driver {103 struct mdev_driver {
104 int (*probe) (struct mdev_device *dev);104 int (*probe) (struct mdev_device *dev);
105 void (*remove) (struct mdev_device *dev);105 void (*remove) (struct mdev_device *dev);
106 struct attribute_group **supported_type_groups;106 const struct attribute * const *types_attrs;
107 struct device_driver driver;107 struct device_driver driver;
108 };108 };
109 109
drivers/gpu/drm/i915/gvt/gvt.h+2−1
@@ -310,8 +310,8 @@ struct intel_vgpu_config { · 309 unmodified lines
310 const char *name;310 const char *name;
311};311};
312 312
313#define NR_MAX_INTEL_VGPU_TYPES 20
314struct intel_vgpu_type {313struct intel_vgpu_type {
314 struct mdev_type type;
315 char name[16];315 char name[16];
316 const struct intel_vgpu_config *conf;316 const struct intel_vgpu_config *conf;
317 unsigned int avail_instance;317 unsigned int avail_instance;
@@ -339,6 +339,7 @@ struct intel_gvt { · 21 unmodified lines
339 struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];339 struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
340 DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);340 DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
341 struct mdev_parent parent;341 struct mdev_parent parent;
342 struct mdev_type **mdev_types;
342 struct intel_vgpu_type *types;343 struct intel_vgpu_type *types;
343 unsigned int num_types;344 unsigned int num_types;
344 struct intel_vgpu *idle_vgpu;345 struct intel_vgpu *idle_vgpu;
drivers/gpu/drm/i915/gvt/kvmgt.c+14−88
@@ -117,17 +117,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 116 unmodified lines
117 struct mdev_type_attribute *attr,117 struct mdev_type_attribute *attr,
118 char *buf)118 char *buf)
119{119{
120 struct intel_vgpu_type *type;120 struct intel_vgpu_type *type =
121 unsigned int num = 0;121 container_of(mtype, struct intel_vgpu_type, type);
122 struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
123 122
124 type = &gvt->types[mtype_get_type_group_id(mtype)];123 return sprintf(buf, "%u\n", type->avail_instance);
125 if (!type)
126 num = 0;
127 else
128 num = type->avail_instance;
129
130 return sprintf(buf, "%u\n", num);
131}124}
132 125
133static ssize_t device_api_show(struct mdev_type *mtype,126static 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
139static ssize_t description_show(struct mdev_type *mtype,132static ssize_t description_show(struct mdev_type *mtype,
140 struct mdev_type_attribute *attr, char *buf)133 struct mdev_type_attribute *attr, char *buf)
141{134{
142 struct intel_vgpu_type *type;135 struct intel_vgpu_type *type =
143 struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;136 container_of(mtype, struct intel_vgpu_type, type);
144
145 type = &gvt->types[mtype_get_type_group_id(mtype)];
146 if (!type)
147 return 0;
148 137
149 return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"138 return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
150 "fence: %d\nresolution: %s\n"139 "fence: %d\nresolution: %s\n"
@@ -158,14 +147,7 @@ static ssize_t description_show(struct mdev_type *mtype, · 7 unmodified lines
158static ssize_t name_show(struct mdev_type *mtype,147static ssize_t name_show(struct mdev_type *mtype,
159 struct mdev_type_attribute *attr, char *buf)148 struct mdev_type_attribute *attr, char *buf)
160{149{
161 struct intel_vgpu_type *type;150 return sprintf(buf, "%s\n", mtype->sysfs_name);
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);
169}151}
170 152
171static MDEV_TYPE_ATTR_RO(available_instances);153static MDEV_TYPE_ATTR_RO(available_instances);
@@ -173,7 +155,7 @@ static MDEV_TYPE_ATTR_RO(device_api); · 1 unmodified line
173static MDEV_TYPE_ATTR_RO(description);155static MDEV_TYPE_ATTR_RO(description);
174static MDEV_TYPE_ATTR_RO(name);156static MDEV_TYPE_ATTR_RO(name);
175 157
176static struct attribute *gvt_type_attrs[] = {158static const struct attribute *gvt_type_attrs[] = {
177 &mdev_type_attr_available_instances.attr,159 &mdev_type_attr_available_instances.attr,
178 &mdev_type_attr_device_api.attr,160 &mdev_type_attr_device_api.attr,
179 &mdev_type_attr_description.attr,161 &mdev_type_attr_description.attr,
@@ -181,51 +163,6 @@ static struct attribute *gvt_type_attrs[] = { · 1 unmodified line
181 NULL,163 NULL,
182};164};
183 165
184static struct attribute_group *gvt_vgpu_type_groups[] = {
185 [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
186};
187
188static 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
208unwind:
209 for (j = 0; j < i; j++) {
210 group = gvt_vgpu_type_groups[j];
211 kfree(group);
212 }
213
214 return -ENOMEM;
215}
216
217static 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
229static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,166static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
230 unsigned long size)167 unsigned long size)
231{168{
@@ -1547,16 +1484,11 @@ static const struct attribute_group *intel_vgpu_groups[] = { · 1315 unmodified lines
1547static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)1484static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
1548{1485{
1549 struct mdev_device *mdev = to_mdev_device(vfio_dev->dev);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 struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);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)];1491 vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt;
1556 if (!type)
1557 return -EINVAL;
1558
1559 vgpu->gvt = gvt;
1560 return intel_gvt_create_vgpu(vgpu, type->conf);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 .probe = intel_vgpu_probe,1558 .probe = intel_vgpu_probe,
1627 .remove = intel_vgpu_remove,1559 .remove = intel_vgpu_remove,
1628 .supported_type_groups = gvt_vgpu_type_groups,1560 .types_attrs = gvt_type_attrs,
1629};1561};
1630 1562
1631int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn)1563int 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 return;1856 return;
1925 1857
1926 mdev_unregister_parent(&gvt->parent);1858 mdev_unregister_parent(&gvt->parent);
1927 intel_gvt_cleanup_vgpu_type_groups(gvt);
1928 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);1859 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
1929 intel_gvt_clean_vgpu_types(gvt);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 intel_gvt_debugfs_init(gvt);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 ret = mdev_register_parent(&gvt->parent, i915->drm.dev,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 if (ret)1961 if (ret)
2034 goto out_cleanup_vgpu_type_groups;1962 goto out_destroy_idle_vgpu;
2035 1963
2036 gvt_dbg_core("gvt device initialization is done\n");1964 gvt_dbg_core("gvt device initialization is done\n");
2037 return 0;1965 return 0;
2038 1966
2039out_cleanup_vgpu_type_groups:
2040 intel_gvt_cleanup_vgpu_type_groups(gvt);
2041out_destroy_idle_vgpu:1967out_destroy_idle_vgpu:
2042 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);1968 intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
2043 intel_gvt_debugfs_clean(gvt);1969 intel_gvt_debugfs_clean(gvt);
drivers/gpu/drm/i915/gvt/vgpu.c+12−1
@@ -113,13 +113,18 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) · 112 unmodified lines
113 if (!gvt->types)113 if (!gvt->types)
114 return -ENOMEM;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 for (i = 0; i < num_types; ++i) {121 for (i = 0; i < num_types; ++i) {
117 const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];122 const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];
118 123
119 if (low_avail / conf->low_mm == 0)124 if (low_avail / conf->low_mm == 0)
120 break;125 break;
121 if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)126 if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)
122 goto out_free_types;127 goto out_free_mdev_types;
123 128
124 sprintf(gvt->types[i].name, "GVTg_V%u_%s",129 sprintf(gvt->types[i].name, "GVTg_V%u_%s",
125 GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);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 i, gvt->types[i].name, gvt->types[i].avail_instance,136 i, gvt->types[i].name, gvt->types[i].avail_instance,
132 conf->low_mm, conf->high_mm, conf->fence,137 conf->low_mm, conf->high_mm, conf->fence,
133 conf->weight, vgpu_edid_str(conf->edid));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 gvt->num_types = i;144 gvt->num_types = i;
137 return 0;145 return 0;
138 146
147out_free_mdev_types:
148 kfree(gvt->mdev_types);
139out_free_types:149out_free_types:
140 kfree(gvt->types);150 kfree(gvt->types);
141 return -EINVAL;151 return -EINVAL;
@@ -143,6 +153,7 @@ out_free_types: · 1 unmodified line
143 153
144void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)154void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
145{155{
156 kfree(gvt->mdev_types);
146 kfree(gvt->types);157 kfree(gvt->types);
147}158}
148 159
drivers/s390/cio/vfio_ccw_drv.c+4−2
@@ -202,7 +202,6 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private) · 201 unmodified lines
202 mutex_destroy(&private->io_mutex);202 mutex_destroy(&private->io_mutex);
203 kfree(private);203 kfree(private);
204}204}
205
206static int vfio_ccw_sch_probe(struct subchannel *sch)205static int vfio_ccw_sch_probe(struct subchannel *sch)
207{206{
208 struct pmcw *pmcw = &sch->schib.pmcw;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 dev_set_drvdata(&sch->dev, private);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 ret = mdev_register_parent(&private->parent, &sch->dev,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 if (ret)228 if (ret)
227 goto out_free;229 goto out_free;
228 230
drivers/s390/cio/vfio_ccw_ops.c+2−12
@@ -69,23 +69,13 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 68 unmodified lines
69}69}
70static MDEV_TYPE_ATTR_RO(available_instances);70static MDEV_TYPE_ATTR_RO(available_instances);
71 71
72static struct attribute *mdev_types_attrs[] = {72static const struct attribute *mdev_types_attrs[] = {
73 &mdev_type_attr_name.attr,73 &mdev_type_attr_name.attr,
74 &mdev_type_attr_device_api.attr,74 &mdev_type_attr_device_api.attr,
75 &mdev_type_attr_available_instances.attr,75 &mdev_type_attr_available_instances.attr,
76 NULL,76 NULL,
77};77};
78 78
79static struct attribute_group mdev_type_group = {
80 .name = "io",
81 .attrs = mdev_types_attrs,
82};
83
84static struct attribute_group *mdev_type_groups[] = {
85 &mdev_type_group,
86 NULL,
87};
88
89static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)79static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
90{80{
91 struct vfio_ccw_private *private =81 struct vfio_ccw_private *private =
@@ -646,5 +636,5 @@ struct mdev_driver vfio_ccw_mdev_driver = { · 554 unmodified lines
646 },636 },
647 .probe = vfio_ccw_mdev_probe,637 .probe = vfio_ccw_mdev_probe,
648 .remove = vfio_ccw_mdev_remove,638 .remove = vfio_ccw_mdev_remove,
649 .supported_type_groups = mdev_type_groups,639 .types_attrs = mdev_types_attrs,
650};640};
drivers/s390/cio/vfio_ccw_private.h+2−0
@@ -120,6 +120,8 @@ struct vfio_ccw_private { · 119 unmodified lines
120 struct completion release_comp;120 struct completion release_comp;
121 121
122 struct mdev_parent parent;122 struct mdev_parent parent;
123 struct mdev_type mdev_type;
124 struct mdev_type *mdev_types[1];
123} __aligned(8);125} __aligned(8);
124 126
125int vfio_ccw_sch_quiesce(struct subchannel *sch);127int vfio_ccw_sch_quiesce(struct subchannel *sch);
drivers/s390/crypto/vfio_ap_ops.c+6−13
@@ -816,23 +816,13 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 815 unmodified lines
816 816
817static MDEV_TYPE_ATTR_RO(device_api);817static MDEV_TYPE_ATTR_RO(device_api);
818 818
819static struct attribute *vfio_ap_mdev_type_attrs[] = {819static const struct attribute *vfio_ap_mdev_type_attrs[] = {
820 &mdev_type_attr_name.attr,820 &mdev_type_attr_name.attr,
821 &mdev_type_attr_device_api.attr,821 &mdev_type_attr_device_api.attr,
822 &mdev_type_attr_available_instances.attr,822 &mdev_type_attr_available_instances.attr,
823 NULL,823 NULL,
824};824};
825 825
826static 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
831static struct attribute_group *vfio_ap_mdev_type_groups[] = {
832 &vfio_ap_mdev_hwvirt_type_group,
833 NULL,
834};
835
836#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \826#define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
837 "already assigned to %s"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 .probe = vfio_ap_mdev_probe,1808 .probe = vfio_ap_mdev_probe,
1819 .remove = vfio_ap_mdev_remove,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
1823int vfio_ap_mdev_register(void)1813int vfio_ap_mdev_register(void)
@@ -1830,8 +1820,11 @@ int vfio_ap_mdev_register(void) · 6 unmodified lines
1830 if (ret)1820 if (ret)
1831 return ret;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 ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,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 if (ret)1828 if (ret)
1836 goto err_driver;1829 goto err_driver;
1837 return 0;1830 return 0;
drivers/s390/crypto/vfio_ap_private.h+2−0
@@ -53,6 +53,8 @@ struct ap_matrix_dev { · 52 unmodified lines
53 struct ap_driver *vfio_ap_drv;53 struct ap_driver *vfio_ap_drv;
54 struct mutex guests_lock; /* serializes access to each KVM guest */54 struct mutex guests_lock; /* serializes access to each KVM guest */
55 struct mdev_parent parent;55 struct mdev_parent parent;
56 struct mdev_type mdev_type;
57 struct mdev_type *mdev_types[];
56};58};
57 59
58extern struct ap_matrix_dev *matrix_dev;60extern struct ap_matrix_dev *matrix_dev;
drivers/vfio/mdev/mdev_core.c+6−25
@@ -29,26 +29,6 @@ struct device *mdev_parent_dev(struct mdev_device *mdev) · 28 unmodified lines
29}29}
30EXPORT_SYMBOL(mdev_parent_dev);30EXPORT_SYMBOL(mdev_parent_dev);
31 31
32/*
33 * Return the index in supported_type_groups that this mdev_device was created
34 * from.
35 */
36unsigned int mdev_get_type_group_id(struct mdev_device *mdev)
37{
38 return mdev->type->type_group_id;
39}
40EXPORT_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 */
46unsigned int mtype_get_type_group_id(struct mdev_type *mtype)
47{
48 return mtype->type_group_id;
49}
50EXPORT_SYMBOL(mtype_get_type_group_id);
51
52/*32/*
53 * Used in mdev_type_attribute sysfs functions to return the parent struct33 * Used in mdev_type_attribute sysfs functions to return the parent struct
54 * device34 * device
@@ -85,6 +65,8 @@ static int mdev_device_remove_cb(struct device *dev, void *data) · 30 unmodified lines
85 * @parent: parent structure registered65 * @parent: parent structure registered
86 * @dev: device structure representing parent device.66 * @dev: device structure representing parent device.
87 * @mdev_driver: Device driver to bind to the newly created mdev67 * @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 * Registers the @parent stucture as a parent for mdev types and thus mdev71 * Registers the @parent stucture as a parent for mdev types and thus mdev
90 * devices. The caller needs to hold a reference on @dev that must not be72 * 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 * Returns a negative value on error, otherwise 0.75 * Returns a negative value on error, otherwise 0.
94 */76 */
95int mdev_register_parent(struct mdev_parent *parent, struct device *dev,77int 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 char *env_string = "MDEV_STATE=registered";81 char *env_string = "MDEV_STATE=registered";
99 char *envp[] = { env_string, NULL };82 char *envp[] = { env_string, NULL };
100 int ret;83 int ret;
101 84
102 /* check for mandatory ops */
103 if (!mdev_driver->supported_type_groups)
104 return -EINVAL;
105
106 memset(parent, 0, sizeof(*parent));85 memset(parent, 0, sizeof(*parent));
107 init_rwsem(&parent->unreg_sem);86 init_rwsem(&parent->unreg_sem);
108 parent->dev = dev;87 parent->dev = dev;
109 parent->mdev_driver = mdev_driver;88 parent->mdev_driver = mdev_driver;
89 parent->types = types;
90 parent->nr_types = nr_types;
110 91
111 if (!mdev_bus_compat_class) {92 if (!mdev_bus_compat_class) {
112 mdev_bus_compat_class = class_compat_register("mdev_bus");93 mdev_bus_compat_class = class_compat_register("mdev_bus");
drivers/vfio/mdev/mdev_driver.c+2−3
@@ -56,10 +56,9 @@ EXPORT_SYMBOL_GPL(mdev_bus_type); · 55 unmodified lines
56 **/56 **/
57int mdev_register_driver(struct mdev_driver *drv)57int mdev_register_driver(struct mdev_driver *drv)
58{58{
59 /* initialize common driver fields */59 if (!drv->types_attrs)
60 return -EINVAL;
60 drv->driver.bus = &mdev_bus_type;61 drv->driver.bus = &mdev_bus_type;
61
62 /* register with core */
63 return driver_register(&drv->driver);62 return driver_register(&drv->driver);
64}63}
65EXPORT_SYMBOL(mdev_register_driver);64EXPORT_SYMBOL(mdev_register_driver);
drivers/vfio/mdev/mdev_private.h+0−8
@@ -13,14 +13,6 @@ · 12 unmodified lines
13int mdev_bus_register(void);13int mdev_bus_register(void);
14void mdev_bus_unregister(void);14void mdev_bus_unregister(void);
15 15
16struct 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
24extern const struct attribute_group *mdev_device_groups[];16extern const struct attribute_group *mdev_device_groups[];
25 17
26#define to_mdev_type_attr(_attr) \18#define to_mdev_type_attr(_attr) \
drivers/vfio/mdev/mdev_sysfs.c+22−69
@@ -82,7 +82,6 @@ static void mdev_type_release(struct kobject *kobj) · 81 unmodified lines
82 pr_debug("Releasing group %s\n", kobj->name);82 pr_debug("Releasing group %s\n", kobj->name);
83 /* Pairs with the get in add_mdev_supported_type() */83 /* Pairs with the get in add_mdev_supported_type() */
84 put_device(type->parent->dev);84 put_device(type->parent->dev);
85 kfree(type);
86}85}
87 86
88static struct kobj_type mdev_type_ktype = {87static struct kobj_type mdev_type_ktype = {
@@ -90,35 +89,21 @@ static struct kobj_type mdev_type_ktype = { · 1 unmodified line
90 .release = mdev_type_release,89 .release = mdev_type_release,
91};90};
92 91
93static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,92static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
94 unsigned int type_group_id)
95{93{
96 struct mdev_type *type;
97 struct attribute_group *group =
98 parent->mdev_driver->supported_type_groups[type_group_id];
99 int ret;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 type->kobj.kset = parent->mdev_types_kset;96 type->kobj.kset = parent->mdev_types_kset;
111 type->parent = parent;97 type->parent = parent;
112 /* Pairs with the put in mdev_type_release() */98 /* Pairs with the put in mdev_type_release() */
113 get_device(parent->dev);99 get_device(parent->dev);
114 type->type_group_id = type_group_id;
115 100
116 ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,101 ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
117 "%s-%s", dev_driver_string(parent->dev),102 "%s-%s", dev_driver_string(parent->dev),
118 group->name);103 type->sysfs_name);
119 if (ret) {104 if (ret) {
120 kobject_put(&type->kobj);105 kobject_put(&type->kobj);
121 return ERR_PTR(ret);106 return ret;
122 }107 }
123 108
124 ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);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 goto attr_devices_failed;116 goto attr_devices_failed;
132 }117 }
133 118
134 ret = sysfs_create_files(&type->kobj,119 ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs);
135 (const struct attribute **)group->attrs);120 if (ret)
136 if (ret) {
137 ret = -ENOMEM;
138 goto attrs_failed;121 goto attrs_failed;
139 }122 return 0;
140 return type;
141 123
142attrs_failed:124attrs_failed:
143 kobject_put(type->devices_kobj);125 kobject_put(type->devices_kobj);
@@ -146,78 +128,49 @@ attr_devices_failed: · 2 unmodified lines
146attr_create_failed:128attr_create_failed:
147 kobject_del(&type->kobj);129 kobject_del(&type->kobj);
148 kobject_put(&type->kobj);130 kobject_put(&type->kobj);
149 return ERR_PTR(ret);131 return ret;
150}132}
151 133
152static void remove_mdev_supported_type(struct mdev_type *type)134static void mdev_type_remove(struct mdev_type *type)
153{135{
154 struct attribute_group *group =136 sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
155 type->parent->mdev_driver->supported_type_groups[type->type_group_id];
156 137
157 sysfs_remove_files(&type->kobj,
158 (const struct attribute **)group->attrs);
159 kobject_put(type->devices_kobj);138 kobject_put(type->devices_kobj);
160 sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);139 sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
161 kobject_del(&type->kobj);140 kobject_del(&type->kobj);
162 kobject_put(&type->kobj);141 kobject_put(&type->kobj);
163}142}
164 143
165static 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(&ltype->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/* mdev sysfs functions */144/* mdev sysfs functions */
189void parent_remove_sysfs_files(struct mdev_parent *parent)145void parent_remove_sysfs_files(struct mdev_parent *parent)
190{146{
191 struct mdev_type *type, *tmp;147 int i;
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 }
197 148
149 for (i = 0; i < parent->nr_types; i++)
150 mdev_type_remove(parent->types[i]);
198 kset_unregister(parent->mdev_types_kset);151 kset_unregister(parent->mdev_types_kset);
199}152}
200 153
201int parent_create_sysfs_files(struct mdev_parent *parent)154int parent_create_sysfs_files(struct mdev_parent *parent)
202{155{
203 int ret;156 int ret, i;
204 157
205 parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",158 parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
206 NULL, &parent->dev->kobj);159 NULL, &parent->dev->kobj);
207
208 if (!parent->mdev_types_kset)160 if (!parent->mdev_types_kset)
209 return -ENOMEM;161 return -ENOMEM;
210 162
211 INIT_LIST_HEAD(&parent->type_list);163 for (i = 0; i < parent->nr_types; i++) {
212 164 ret = mdev_type_add(parent, parent->types[i]);
213 ret = add_mdev_supported_type_groups(parent);165 if (ret)
214 if (ret)166 goto out_err;
215 goto create_err;167 }
216 return 0;168 return 0;
217 169
218create_err:170out_err:
219 kset_unregister(parent->mdev_types_kset);171 while (--i >= 0)
220 return ret;172 mdev_type_remove(parent->types[i]);
173 return 0;
221}174}
222 175
223static ssize_t remove_store(struct device *dev, struct device_attribute *attr,176static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
include/linux/mdev.h+18−8
@@ -23,14 +23,27 @@ struct mdev_device { · 22 unmodified lines
23 bool active;23 bool active;
24};24};
25 25
26struct 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/* embedded into the struct device that the mdev devices hang off */38/* embedded into the struct device that the mdev devices hang off */
27struct mdev_parent {39struct mdev_parent {
28 struct device *dev;40 struct device *dev;
29 struct mdev_driver *mdev_driver;41 struct mdev_driver *mdev_driver;
30 struct kset *mdev_types_kset;42 struct kset *mdev_types_kset;
31 struct list_head type_list;
32 /* Synchronize device creation/removal with parent unregistration */43 /* Synchronize device creation/removal with parent unregistration */
33 struct rw_semaphore unreg_sem;44 struct rw_semaphore unreg_sem;
45 struct mdev_type **types;
46 unsigned int nr_types;
34};47};
35 48
36static inline struct mdev_device *to_mdev_device(struct device *dev)49static 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 return container_of(dev, struct mdev_device, dev);51 return container_of(dev, struct mdev_device, dev);
39}52}
40 53
41unsigned int mdev_get_type_group_id(struct mdev_device *mdev);
42unsigned int mtype_get_type_group_id(struct mdev_type *mtype);
43struct device *mtype_get_parent_dev(struct mdev_type *mtype);54struct device *mtype_get_parent_dev(struct mdev_type *mtype);
44 55
45/* interface for exporting mdev supported type attributes */56/* interface for exporting mdev supported type attributes */
@@ -66,22 +77,21 @@ struct mdev_type_attribute mdev_type_attr_##_name = \ · 20 unmodified lines
66 * struct mdev_driver - Mediated device driver77 * struct mdev_driver - Mediated device driver
67 * @probe: called when new device created78 * @probe: called when new device created
68 * @remove: called when device removed79 * @remove: called when device removed
69 * @supported_type_groups: Attributes to define supported types. It is mandatory80 * @types_attrs: attributes to the type kobjects.
70 * to provide supported types.
71 * @driver: device driver structure81 * @driver: device driver structure
72 *
73 **/82 **/
74struct mdev_driver {83struct mdev_driver {
75 int (*probe)(struct mdev_device *dev);84 int (*probe)(struct mdev_device *dev);
76 void (*remove)(struct mdev_device *dev);85 void (*remove)(struct mdev_device *dev);
77 struct attribute_group **supported_type_groups;86 const struct attribute * const *types_attrs;
78 struct device_driver driver;87 struct device_driver driver;
79};88};
80 89
81extern struct bus_type mdev_bus_type;90extern struct bus_type mdev_bus_type;
82 91
83int mdev_register_parent(struct mdev_parent *parent, struct device *dev,92int 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);
85void mdev_unregister_parent(struct mdev_parent *parent);95void mdev_unregister_parent(struct mdev_parent *parent);
86 96
87int mdev_register_driver(struct mdev_driver *drv);97int mdev_register_driver(struct mdev_driver *drv);
samples/vfio-mdev/mbochs.c+23−34
@@ -99,23 +99,27 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices"); · 98 unmodified lines
99#define MBOCHS_TYPE_2 "medium"99#define MBOCHS_TYPE_2 "medium"
100#define MBOCHS_TYPE_3 "large"100#define MBOCHS_TYPE_3 "large"
101 101
102static const struct mbochs_type {102static struct mbochs_type {
103 struct mdev_type type;
103 const char *name;104 const char *name;
104 u32 mbytes;105 u32 mbytes;
105 u32 max_x;106 u32 max_x;
106 u32 max_y;107 u32 max_y;
107} mbochs_types[] = {108} mbochs_types[] = {
108 {109 {
110 .type.sysfs_name = MBOCHS_TYPE_1,
109 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,111 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
110 .mbytes = 4,112 .mbytes = 4,
111 .max_x = 800,113 .max_x = 800,
112 .max_y = 600,114 .max_y = 600,
113 }, {115 }, {
116 .type.sysfs_name = MBOCHS_TYPE_2,
114 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,117 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
115 .mbytes = 16,118 .mbytes = 16,
116 .max_x = 1920,119 .max_x = 1920,
117 .max_y = 1440,120 .max_y = 1440,
118 }, {121 }, {
122 .type.sysfs_name = MBOCHS_TYPE_3,
119 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,123 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
120 .mbytes = 64,124 .mbytes = 64,
121 .max_x = 0,125 .max_x = 0,
@@ -123,6 +127,11 @@ static const struct mbochs_type { · 1 unmodified line
123 },127 },
124};128};
125 129
130static struct mdev_type *mbochs_mdev_types[] = {
131 &mbochs_types[0].type,
132 &mbochs_types[1].type,
133 &mbochs_types[2].type,
134};
126 135
127static dev_t mbochs_devt;136static dev_t mbochs_devt;
128static struct class *mbochs_class;137static struct class *mbochs_class;
@@ -510,8 +519,8 @@ static int mbochs_init_dev(struct vfio_device *vdev) · 381 unmodified lines
510 struct mdev_state *mdev_state =519 struct mdev_state *mdev_state =
511 container_of(vdev, struct mdev_state, vdev);520 container_of(vdev, struct mdev_state, vdev);
512 struct mdev_device *mdev = to_mdev_device(vdev->dev);521 struct mdev_device *mdev = to_mdev_device(vdev->dev);
513 const struct mbochs_type *type =522 struct mbochs_type *type =
514 &mbochs_types[mdev_get_type_group_id(mdev)];523 container_of(mdev->type, struct mbochs_type, type);
515 int avail_mbytes = atomic_read(&mbochs_avail_mbytes);524 int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
516 int ret = -ENOMEM;525 int ret = -ENOMEM;
517 526
@@ -1345,8 +1354,8 @@ static const struct attribute_group *mdev_dev_groups[] = { · 827 unmodified lines
1345static ssize_t name_show(struct mdev_type *mtype,1354static ssize_t name_show(struct mdev_type *mtype,
1346 struct mdev_type_attribute *attr, char *buf)1355 struct mdev_type_attribute *attr, char *buf)
1347{1356{
1348 const struct mbochs_type *type =1357 struct mbochs_type *type =
1349 &mbochs_types[mtype_get_type_group_id(mtype)];1358 container_of(mtype, struct mbochs_type, type);
1350 1359
1351 return sprintf(buf, "%s\n", type->name);1360 return sprintf(buf, "%s\n", type->name);
1352}1361}
@@ -1355,8 +1364,8 @@ static MDEV_TYPE_ATTR_RO(name); · 2 unmodified lines
1355static ssize_t description_show(struct mdev_type *mtype,1364static ssize_t description_show(struct mdev_type *mtype,
1356 struct mdev_type_attribute *attr, char *buf)1365 struct mdev_type_attribute *attr, char *buf)
1357{1366{
1358 const struct mbochs_type *type =1367 struct mbochs_type *type =
1359 &mbochs_types[mtype_get_type_group_id(mtype)];1368 container_of(mtype, struct mbochs_type, type);
1360 1369
1361 return sprintf(buf, "virtual display, %d MB video memory\n",1370 return sprintf(buf, "virtual display, %d MB video memory\n",
1362 type ? type->mbytes : 0);1371 type ? type->mbytes : 0);
@@ -1367,8 +1376,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 4 unmodified lines
1367 struct mdev_type_attribute *attr,1376 struct mdev_type_attribute *attr,
1368 char *buf)1377 char *buf)
1369{1378{
1370 const struct mbochs_type *type =1379 struct mbochs_type *type =
1371 &mbochs_types[mtype_get_type_group_id(mtype)];1380 container_of(mtype, struct mbochs_type, type);
1372 int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;1381 int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
1373 1382
1374 return sprintf(buf, "%d\n", count);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}
1383static MDEV_TYPE_ATTR_RO(device_api);1392static MDEV_TYPE_ATTR_RO(device_api);
1384 1393
1385static struct attribute *mdev_types_attrs[] = {1394static const struct attribute *mdev_types_attrs[] = {
1386 &mdev_type_attr_name.attr,1395 &mdev_type_attr_name.attr,
1387 &mdev_type_attr_description.attr,1396 &mdev_type_attr_description.attr,
1388 &mdev_type_attr_device_api.attr,1397 &mdev_type_attr_device_api.attr,
@@ -1390,28 +1399,6 @@ static struct attribute *mdev_types_attrs[] = { · 1 unmodified line
1390 NULL,1399 NULL,
1391};1400};
1392 1401
1393static struct attribute_group mdev_type_group1 = {
1394 .name = MBOCHS_TYPE_1,
1395 .attrs = mdev_types_attrs,
1396};
1397
1398static struct attribute_group mdev_type_group2 = {
1399 .name = MBOCHS_TYPE_2,
1400 .attrs = mdev_types_attrs,
1401};
1402
1403static struct attribute_group mdev_type_group3 = {
1404 .name = MBOCHS_TYPE_3,
1405 .attrs = mdev_types_attrs,
1406};
1407
1408static struct attribute_group *mdev_type_groups[] = {
1409 &mdev_type_group1,
1410 &mdev_type_group2,
1411 &mdev_type_group3,
1412 NULL,
1413};
1414
1415static const struct vfio_device_ops mbochs_dev_ops = {1402static const struct vfio_device_ops mbochs_dev_ops = {
1416 .close_device = mbochs_close_device,1403 .close_device = mbochs_close_device,
1417 .init = mbochs_init_dev,1404 .init = mbochs_init_dev,
@@ -1431,7 +1418,7 @@ static struct mdev_driver mbochs_driver = { · 13 unmodified lines
1431 },1418 },
1432 .probe = mbochs_probe,1419 .probe = mbochs_probe,
1433 .remove = mbochs_remove,1420 .remove = mbochs_remove,
1434 .supported_type_groups = mdev_type_groups,1421 .types_attrs = mdev_types_attrs,
1435};1422};
1436 1423
1437static const struct file_operations vd_fops = {1424static const struct file_operations vd_fops = {
@@ -1476,7 +1463,9 @@ static int __init mbochs_dev_init(void) · 38 unmodified lines
1476 if (ret)1463 if (ret)
1477 goto err_class;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 if (ret)1469 if (ret)
1481 goto err_device;1470 goto err_device;
1482 1471
samples/vfio-mdev/mdpy.c+19−31
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices"); · 50 unmodified lines
51#define MDPY_TYPE_2 "xga"51#define MDPY_TYPE_2 "xga"
52#define MDPY_TYPE_3 "hd"52#define MDPY_TYPE_3 "hd"
53 53
54static const struct mdpy_type {54static struct mdpy_type {
55 struct mdev_type type;
55 const char *name;56 const char *name;
56 u32 format;57 u32 format;
57 u32 bytepp;58 u32 bytepp;
@@ -59,18 +60,21 @@ static const struct mdpy_type { · 1 unmodified line
59 u32 height;60 u32 height;
60} mdpy_types[] = {61} mdpy_types[] = {
61 {62 {
63 .type.sysfs_name = MDPY_TYPE_1,
62 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1,64 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
63 .format = DRM_FORMAT_XRGB8888,65 .format = DRM_FORMAT_XRGB8888,
64 .bytepp = 4,66 .bytepp = 4,
65 .width = 640,67 .width = 640,
66 .height = 480,68 .height = 480,
67 }, {69 }, {
70 .type.sysfs_name = MDPY_TYPE_2,
68 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2,71 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
69 .format = DRM_FORMAT_XRGB8888,72 .format = DRM_FORMAT_XRGB8888,
70 .bytepp = 4,73 .bytepp = 4,
71 .width = 1024,74 .width = 1024,
72 .height = 768,75 .height = 768,
73 }, {76 }, {
77 .type.sysfs_name = MDPY_TYPE_3,
74 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3,78 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
75 .format = DRM_FORMAT_XRGB8888,79 .format = DRM_FORMAT_XRGB8888,
76 .bytepp = 4,80 .bytepp = 4,
@@ -79,6 +83,12 @@ static const struct mdpy_type { · 2 unmodified lines
79 },83 },
80};84};
81 85
86static struct mdev_type *mdpy_mdev_types[] = {
87 &mdpy_types[0].type,
88 &mdpy_types[1].type,
89 &mdpy_types[2].type,
90};
91
82static dev_t mdpy_devt;92static dev_t mdpy_devt;
83static struct class *mdpy_class;93static struct class *mdpy_class;
84static struct cdev mdpy_cdev;94static struct cdev mdpy_cdev;
@@ -222,7 +232,7 @@ static int mdpy_init_dev(struct vfio_device *vdev) · 137 unmodified lines
222 container_of(vdev, struct mdev_state, vdev);232 container_of(vdev, struct mdev_state, vdev);
223 struct mdev_device *mdev = to_mdev_device(vdev->dev);233 struct mdev_device *mdev = to_mdev_device(vdev->dev);
224 const struct mdpy_type *type =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 u32 fbsize;236 u32 fbsize;
227 int ret = -ENOMEM;237 int ret = -ENOMEM;
228 238
@@ -655,8 +665,7 @@ static const struct attribute_group *mdev_dev_groups[] = { · 426 unmodified lines
655static ssize_t name_show(struct mdev_type *mtype,665static ssize_t name_show(struct mdev_type *mtype,
656 struct mdev_type_attribute *attr, char *buf)666 struct mdev_type_attribute *attr, char *buf)
657{667{
658 const struct mdpy_type *type =668 struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
659 &mdpy_types[mtype_get_type_group_id(mtype)];
660 669
661 return sprintf(buf, "%s\n", type->name);670 return sprintf(buf, "%s\n", type->name);
662}671}
@@ -665,8 +674,7 @@ static MDEV_TYPE_ATTR_RO(name); · 2 unmodified lines
665static ssize_t description_show(struct mdev_type *mtype,674static ssize_t description_show(struct mdev_type *mtype,
666 struct mdev_type_attribute *attr, char *buf)675 struct mdev_type_attribute *attr, char *buf)
667{676{
668 const struct mdpy_type *type =677 struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
669 &mdpy_types[mtype_get_type_group_id(mtype)];
670 678
671 return sprintf(buf, "virtual display, %dx%d framebuffer\n",679 return sprintf(buf, "virtual display, %dx%d framebuffer\n",
672 type->width, type->height);680 type->width, type->height);
@@ -688,7 +696,7 @@ static ssize_t device_api_show(struct mdev_type *mtype, · 15 unmodified lines
688}696}
689static MDEV_TYPE_ATTR_RO(device_api);697static MDEV_TYPE_ATTR_RO(device_api);
690 698
691static struct attribute *mdev_types_attrs[] = {699static const struct attribute *mdev_types_attrs[] = {
692 &mdev_type_attr_name.attr,700 &mdev_type_attr_name.attr,
693 &mdev_type_attr_description.attr,701 &mdev_type_attr_description.attr,
694 &mdev_type_attr_device_api.attr,702 &mdev_type_attr_device_api.attr,
@@ -696,28 +704,6 @@ static struct attribute *mdev_types_attrs[] = { · 1 unmodified line
696 NULL,704 NULL,
697};705};
698 706
699static struct attribute_group mdev_type_group1 = {
700 .name = MDPY_TYPE_1,
701 .attrs = mdev_types_attrs,
702};
703
704static struct attribute_group mdev_type_group2 = {
705 .name = MDPY_TYPE_2,
706 .attrs = mdev_types_attrs,
707};
708
709static struct attribute_group mdev_type_group3 = {
710 .name = MDPY_TYPE_3,
711 .attrs = mdev_types_attrs,
712};
713
714static struct attribute_group *mdev_type_groups[] = {
715 &mdev_type_group1,
716 &mdev_type_group2,
717 &mdev_type_group3,
718 NULL,
719};
720
721static const struct vfio_device_ops mdpy_dev_ops = {707static const struct vfio_device_ops mdpy_dev_ops = {
722 .init = mdpy_init_dev,708 .init = mdpy_init_dev,
723 .release = mdpy_release_dev,709 .release = mdpy_release_dev,
@@ -736,7 +722,7 @@ static struct mdev_driver mdpy_driver = { · 12 unmodified lines
736 },722 },
737 .probe = mdpy_probe,723 .probe = mdpy_probe,
738 .remove = mdpy_remove,724 .remove = mdpy_remove,
739 .supported_type_groups = mdev_type_groups,725 .types_attrs = mdev_types_attrs,
740};726};
741 727
742static const struct file_operations vd_fops = {728static const struct file_operations vd_fops = {
@@ -779,7 +765,9 @@ static int __init mdpy_dev_init(void) · 36 unmodified lines
779 if (ret)765 if (ret)
780 goto err_class;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 if (ret)771 if (ret)
784 goto err_device;772 goto err_device;
785 773
samples/vfio-mdev/mtty.c+30−30
@@ -143,6 +143,20 @@ struct mdev_state { · 142 unmodified lines
143 int nr_ports;143 int nr_ports;
144};144};
145 145
146static 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
155static struct mdev_type *mtty_mdev_types[] = {
156 &mtty_types[0].type,
157 &mtty_types[1].type,
158};
159
146static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS);160static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS);
147 161
148static const struct file_operations vd_fops = {162static const struct file_operations vd_fops = {
@@ -707,17 +721,19 @@ static int mtty_init_dev(struct vfio_device *vdev) · 558 unmodified lines
707 struct mdev_state *mdev_state =721 struct mdev_state *mdev_state =
708 container_of(vdev, struct mdev_state, vdev);722 container_of(vdev, struct mdev_state, vdev);
709 struct mdev_device *mdev = to_mdev_device(vdev->dev);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 int avail_ports = atomic_read(&mdev_avail_ports);726 int avail_ports = atomic_read(&mdev_avail_ports);
712 int ret;727 int ret;
713 728
714 do {729 do {
715 if (avail_ports < nr_ports)730 if (avail_ports < type->nr_ports)
716 return -ENOSPC;731 return -ENOSPC;
717 } while (!atomic_try_cmpxchg(&mdev_avail_ports,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 mdev_state->irq_index = -1;737 mdev_state->irq_index = -1;
722 mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;738 mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
723 mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE;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 return 0;751 return 0;
736 752
737err_nr_ports:753err_nr_ports:
738 atomic_add(nr_ports, &mdev_avail_ports);754 atomic_add(type->nr_ports, &mdev_avail_ports);
739 return ret;755 return ret;
740}756}
741 757
@@ -1242,11 +1258,9 @@ static const struct attribute_group *mdev_dev_groups[] = { · 500 unmodified lines
1242static ssize_t name_show(struct mdev_type *mtype,1258static ssize_t name_show(struct mdev_type *mtype,
1243 struct mdev_type_attribute *attr, char *buf)1259 struct mdev_type_attribute *attr, char *buf)
1244{1260{
1245 static const char *name_str[2] = { "Single port serial",1261 struct mtty_type *type = container_of(mtype, struct mtty_type, type);
1246 "Dual port serial" };
1247 1262
1248 return sysfs_emit(buf, "%s\n",1263 return sysfs_emit(buf, "%s\n", type->name);
1249 name_str[mtype_get_type_group_id(mtype)]);
1250}1264}
1251 1265
1252static MDEV_TYPE_ATTR_RO(name);1266static MDEV_TYPE_ATTR_RO(name);
@@ -1255,9 +1269,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype, · 2 unmodified lines
1255 struct mdev_type_attribute *attr,1269 struct mdev_type_attribute *attr,
1256 char *buf)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
1263static MDEV_TYPE_ATTR_RO(available_instances);1278static 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
1271static MDEV_TYPE_ATTR_RO(device_api);1286static MDEV_TYPE_ATTR_RO(device_api);
1272 1287
1273static struct attribute *mdev_types_attrs[] = {1288static const struct attribute *mdev_types_attrs[] = {
1274 &mdev_type_attr_name.attr,1289 &mdev_type_attr_name.attr,
1275 &mdev_type_attr_device_api.attr,1290 &mdev_type_attr_device_api.attr,
1276 &mdev_type_attr_available_instances.attr,1291 &mdev_type_attr_available_instances.attr,
1277 NULL,1292 NULL,
1278};1293};
1279 1294
1280static struct attribute_group mdev_type_group1 = {
1281 .name = "1",
1282 .attrs = mdev_types_attrs,
1283};
1284
1285static struct attribute_group mdev_type_group2 = {
1286 .name = "2",
1287 .attrs = mdev_types_attrs,
1288};
1289
1290static struct attribute_group *mdev_type_groups[] = {
1291 &mdev_type_group1,
1292 &mdev_type_group2,
1293 NULL,
1294};
1295
1296static const struct vfio_device_ops mtty_dev_ops = {1295static const struct vfio_device_ops mtty_dev_ops = {
1297 .name = "vfio-mtty",1296 .name = "vfio-mtty",
1298 .init = mtty_init_dev,1297 .init = mtty_init_dev,
@@ -1311,7 +1310,7 @@ static struct mdev_driver mtty_driver = { · 12 unmodified lines
1311 },1310 },
1312 .probe = mtty_probe,1311 .probe = mtty_probe,
1313 .remove = mtty_remove,1312 .remove = mtty_remove,
1314 .supported_type_groups = mdev_type_groups,1313 .types_attrs = mdev_types_attrs,
1315};1314};
1316 1315
1317static void mtty_device_release(struct device *dev)1316static void mtty_device_release(struct device *dev)
@@ -1363,7 +1362,8 @@ static int __init mtty_dev_init(void) · 45 unmodified lines
1363 goto err_class;1362 goto err_class;
1364 1363
1365 ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,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 if (ret)1367 if (ret)
1368 goto err_device;1368 goto err_device;
1369 return 0;1369 return 0;