vfio/mdev: simplify mdev_type handling
authorChristoph Hellwig <hch@lst.de>
Fri, 23 Sep 2022 09:26:43 +0000 (11:26 +0200)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 4 Oct 2022 18:06:58 +0000 (12:06 -0600)
Instead of abusing struct attribute_group to control initialization of
struct mdev_type, just define the actual attributes in the mdev_driver,
allocate the mdev_type structures in the caller and pass them to
mdev_register_parent.

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

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/r/20220923092652.100656-6-hch@lst.de
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
17 files changed:
Documentation/driver-api/vfio-mediated-device.rst
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/cio/vfio_ccw_ops.c
drivers/s390/cio/vfio_ccw_private.h
drivers/s390/crypto/vfio_ap_ops.c
drivers/s390/crypto/vfio_ap_private.h
drivers/vfio/mdev/mdev_core.c
drivers/vfio/mdev/mdev_driver.c
drivers/vfio/mdev/mdev_private.h
drivers/vfio/mdev/mdev_sysfs.c
include/linux/mdev.h
samples/vfio-mdev/mbochs.c
samples/vfio-mdev/mdpy.c
samples/vfio-mdev/mtty.c

index cd1667608ab5d06e120f9765f5787a3c6b6d0a2f..ff7342d2e332d396d2ed02825a6f5025bedf2b2c 100644 (file)
@@ -103,7 +103,7 @@ structure to represent a mediated device's driver::
      struct mdev_driver {
             int  (*probe)  (struct mdev_device *dev);
             void (*remove) (struct mdev_device *dev);
-            struct attribute_group **supported_type_groups;
+            const struct attribute * const *types_attrs;
             struct device_driver    driver;
      };
 
index fa4a56b50c828cb895cf84dd23d46ba17d434e6f..db182066d56c9e5f9c5b3ba2d935ecf98e25794f 100644 (file)
@@ -310,8 +310,8 @@ struct intel_vgpu_config {
        const char *name;
 };
 
-#define NR_MAX_INTEL_VGPU_TYPES 20
 struct intel_vgpu_type {
+       struct mdev_type type;
        char name[16];
        const struct intel_vgpu_config *conf;
        unsigned int avail_instance;
@@ -339,6 +339,7 @@ struct intel_gvt {
        struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
        DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
        struct mdev_parent parent;
+       struct mdev_type **mdev_types;
        struct intel_vgpu_type *types;
        unsigned int num_types;
        struct intel_vgpu *idle_vgpu;
index d7afe3f5f75b3be866e3d52248261ed1650098cf..12b0b330616850bf90fb759bb327a79e5181d248 100644 (file)
@@ -117,17 +117,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
                                        struct mdev_type_attribute *attr,
                                        char *buf)
 {
-       struct intel_vgpu_type *type;
-       unsigned int num = 0;
-       struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
+       struct intel_vgpu_type *type =
+               container_of(mtype, struct intel_vgpu_type, type);
 
-       type = &gvt->types[mtype_get_type_group_id(mtype)];
-       if (!type)
-               num = 0;
-       else
-               num = type->avail_instance;
-
-       return sprintf(buf, "%u\n", num);
+       return sprintf(buf, "%u\n", type->avail_instance);
 }
 
 static ssize_t device_api_show(struct mdev_type *mtype,
@@ -139,12 +132,8 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 static ssize_t description_show(struct mdev_type *mtype,
                                struct mdev_type_attribute *attr, char *buf)
 {
-       struct intel_vgpu_type *type;
-       struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-       type = &gvt->types[mtype_get_type_group_id(mtype)];
-       if (!type)
-               return 0;
+       struct intel_vgpu_type *type =
+               container_of(mtype, struct intel_vgpu_type, type);
 
        return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
                       "fence: %d\nresolution: %s\n"
@@ -158,14 +147,7 @@ static ssize_t description_show(struct mdev_type *mtype,
 static ssize_t name_show(struct mdev_type *mtype,
                         struct mdev_type_attribute *attr, char *buf)
 {
-       struct intel_vgpu_type *type;
-       struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-       type = &gvt->types[mtype_get_type_group_id(mtype)];
-       if (!type)
-               return 0;
-
-       return sprintf(buf, "%s\n", type->name);
+       return sprintf(buf, "%s\n", mtype->sysfs_name);
 }
 
 static MDEV_TYPE_ATTR_RO(available_instances);
@@ -173,7 +155,7 @@ static MDEV_TYPE_ATTR_RO(device_api);
 static MDEV_TYPE_ATTR_RO(description);
 static MDEV_TYPE_ATTR_RO(name);
 
-static struct attribute *gvt_type_attrs[] = {
+static const struct attribute *gvt_type_attrs[] = {
        &mdev_type_attr_available_instances.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_description.attr,
@@ -181,51 +163,6 @@ static struct attribute *gvt_type_attrs[] = {
        NULL,
 };
 
-static struct attribute_group *gvt_vgpu_type_groups[] = {
-       [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
-};
-
-static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
-{
-       int i, j;
-       struct intel_vgpu_type *type;
-       struct attribute_group *group;
-
-       for (i = 0; i < gvt->num_types; i++) {
-               type = &gvt->types[i];
-
-               group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
-               if (!group)
-                       goto unwind;
-
-               group->name = type->name;
-               group->attrs = gvt_type_attrs;
-               gvt_vgpu_type_groups[i] = group;
-       }
-
-       return 0;
-
-unwind:
-       for (j = 0; j < i; j++) {
-               group = gvt_vgpu_type_groups[j];
-               kfree(group);
-       }
-
-       return -ENOMEM;
-}
-
-static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
-{
-       int i;
-       struct attribute_group *group;
-
-       for (i = 0; i < gvt->num_types; i++) {
-               group = gvt_vgpu_type_groups[i];
-               gvt_vgpu_type_groups[i] = NULL;
-               kfree(group);
-       }
-}
-
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
                unsigned long size)
 {
@@ -1547,16 +1484,11 @@ static const struct attribute_group *intel_vgpu_groups[] = {
 static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
 {
        struct mdev_device *mdev = to_mdev_device(vfio_dev->dev);
-       struct device *pdev = mdev_parent_dev(mdev);
-       struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
-       struct intel_vgpu_type *type;
        struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
+       struct intel_vgpu_type *type =
+               container_of(mdev->type, struct intel_vgpu_type, type);
 
-       type = &gvt->types[mdev_get_type_group_id(mdev)];
-       if (!type)
-               return -EINVAL;
-
-       vgpu->gvt = gvt;
+       vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt;
        return intel_gvt_create_vgpu(vgpu, type->conf);
 }
 
@@ -1625,7 +1557,7 @@ static struct mdev_driver intel_vgpu_mdev_driver = {
        },
        .probe          = intel_vgpu_probe,
        .remove         = intel_vgpu_remove,
-       .supported_type_groups  = gvt_vgpu_type_groups,
+       .types_attrs    = gvt_type_attrs,
 };
 
 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)
                return;
 
        mdev_unregister_parent(&gvt->parent);
-       intel_gvt_cleanup_vgpu_type_groups(gvt);
        intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
        intel_gvt_clean_vgpu_types(gvt);
 
@@ -2024,20 +1955,15 @@ static int intel_gvt_init_device(struct drm_i915_private *i915)
 
        intel_gvt_debugfs_init(gvt);
 
-       ret = intel_gvt_init_vgpu_type_groups(gvt);
-       if (ret)
-               goto out_destroy_idle_vgpu;
-
        ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
-                                  &intel_vgpu_mdev_driver);
+                                  &intel_vgpu_mdev_driver,
+                                  gvt->mdev_types, gvt->num_types);
        if (ret)
-               goto out_cleanup_vgpu_type_groups;
+               goto out_destroy_idle_vgpu;
 
        gvt_dbg_core("gvt device initialization is done\n");
        return 0;
 
-out_cleanup_vgpu_type_groups:
-       intel_gvt_cleanup_vgpu_type_groups(gvt);
 out_destroy_idle_vgpu:
        intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
        intel_gvt_debugfs_clean(gvt);
index b0d5dafd013f4a034c272ad9a5c62bda1ec43ca8..92aaa77feceee8b74c4657f77ebbfde9b99686ec 100644 (file)
@@ -113,13 +113,18 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
        if (!gvt->types)
                return -ENOMEM;
 
+       gvt->mdev_types = kcalloc(num_types, sizeof(*gvt->mdev_types),
+                            GFP_KERNEL);
+       if (!gvt->mdev_types)
+               goto out_free_types;
+
        for (i = 0; i < num_types; ++i) {
                const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];
 
                if (low_avail / conf->low_mm == 0)
                        break;
                if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)
-                       goto out_free_types;
+                       goto out_free_mdev_types;
 
                sprintf(gvt->types[i].name, "GVTg_V%u_%s",
                        GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
@@ -131,11 +136,16 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
                             i, gvt->types[i].name, gvt->types[i].avail_instance,
                             conf->low_mm, conf->high_mm, conf->fence,
                             conf->weight, vgpu_edid_str(conf->edid));
+
+               gvt->mdev_types[i] = &gvt->types[i].type;
+               gvt->mdev_types[i]->sysfs_name = gvt->types[i].name;
        }
 
        gvt->num_types = i;
        return 0;
 
+out_free_mdev_types:
+       kfree(gvt->mdev_types);
 out_free_types:
        kfree(gvt->types);
        return -EINVAL;
@@ -143,6 +153,7 @@ out_free_types:
 
 void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
 {
+       kfree(gvt->mdev_types);
        kfree(gvt->types);
 }
 
index 7d105915bd149211498a54a0e803a0b567276b04..25a5de08b3902c02d1a6777eb968618718f3adca 100644 (file)
@@ -202,7 +202,6 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private)
        mutex_destroy(&private->io_mutex);
        kfree(private);
 }
-
 static int vfio_ccw_sch_probe(struct subchannel *sch)
 {
        struct pmcw *pmcw = &sch->schib.pmcw;
@@ -221,8 +220,11 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 
        dev_set_drvdata(&sch->dev, private);
 
+       private->mdev_type.sysfs_name = "io";
+       private->mdev_types[0] = &private->mdev_type;
        ret = mdev_register_parent(&private->parent, &sch->dev,
-                                  &vfio_ccw_mdev_driver);
+                                  &vfio_ccw_mdev_driver,
+                                  private->mdev_types, 1);
        if (ret)
                goto out_free;
 
index 9a0e0c5ffb1a535aa13d6ed2430a223cb8d671b9..c37e712a4b0699054b2c61b4619218a594e0f310 100644 (file)
@@ -69,23 +69,13 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
        &mdev_type_attr_name.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_available_instances.attr,
        NULL,
 };
 
-static struct attribute_group mdev_type_group = {
-       .name  = "io",
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-       &mdev_type_group,
-       NULL,
-};
-
 static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
 {
        struct vfio_ccw_private *private =
@@ -646,5 +636,5 @@ struct mdev_driver vfio_ccw_mdev_driver = {
        },
        .probe = vfio_ccw_mdev_probe,
        .remove = vfio_ccw_mdev_remove,
-       .supported_type_groups  = mdev_type_groups,
+       .types_attrs = mdev_types_attrs,
 };
index 1a4bfb1b5a808d8354430e3b217e30f1097819e4..52caa721ec06c511352771c99822bd10f1f527b4 100644 (file)
@@ -120,6 +120,8 @@ struct vfio_ccw_private {
        struct completion       release_comp;
 
        struct mdev_parent      parent;
+       struct mdev_type        mdev_type;
+       struct mdev_type        *mdev_types[1];
 } __aligned(8);
 
 int vfio_ccw_sch_quiesce(struct subchannel *sch);
index 724d09a74a8f1d45a11a9836aed85e08fd7caf17..24d131c502ca3149eccb87ec5d3d6c879d4235e2 100644 (file)
@@ -816,23 +816,13 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *vfio_ap_mdev_type_attrs[] = {
+static const struct attribute *vfio_ap_mdev_type_attrs[] = {
        &mdev_type_attr_name.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_available_instances.attr,
        NULL,
 };
 
-static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
-       .name = VFIO_AP_MDEV_TYPE_HWVIRT,
-       .attrs = vfio_ap_mdev_type_attrs,
-};
-
-static struct attribute_group *vfio_ap_mdev_type_groups[] = {
-       &vfio_ap_mdev_hwvirt_type_group,
-       NULL,
-};
-
 #define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
                         "already assigned to %s"
 
@@ -1817,7 +1807,7 @@ static struct mdev_driver vfio_ap_matrix_driver = {
        },
        .probe = vfio_ap_mdev_probe,
        .remove = vfio_ap_mdev_remove,
-       .supported_type_groups = vfio_ap_mdev_type_groups,
+       .types_attrs = vfio_ap_mdev_type_attrs,
 };
 
 int vfio_ap_mdev_register(void)
@@ -1830,8 +1820,11 @@ int vfio_ap_mdev_register(void)
        if (ret)
                return ret;
 
+       matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT;
+       matrix_dev->mdev_types[0] = &matrix_dev->mdev_type;
        ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,
-                                  &vfio_ap_matrix_driver);
+                                  &vfio_ap_matrix_driver,
+                                  matrix_dev->mdev_types, 1);
        if (ret)
                goto err_driver;
        return 0;
index 35165730f51749061a7b240c32685b264caaef1d..441dc8dda380bbb021e80ae90bac2a98fca4b86f 100644 (file)
@@ -53,6 +53,8 @@ struct ap_matrix_dev {
        struct ap_driver  *vfio_ap_drv;
        struct mutex guests_lock; /* serializes access to each KVM guest */
        struct mdev_parent parent;
+       struct mdev_type mdev_type;
+       struct mdev_type *mdev_types[];
 };
 
 extern struct ap_matrix_dev *matrix_dev;
index fa05ac3396950e769e4090d9053f1cc52b76c83b..2d95a497fd3b230da21880c5aabcc3ae22aab6be 100644 (file)
@@ -29,26 +29,6 @@ struct device *mdev_parent_dev(struct mdev_device *mdev)
 }
 EXPORT_SYMBOL(mdev_parent_dev);
 
-/*
- * Return the index in supported_type_groups that this mdev_device was created
- * from.
- */
-unsigned int mdev_get_type_group_id(struct mdev_device *mdev)
-{
-       return mdev->type->type_group_id;
-}
-EXPORT_SYMBOL(mdev_get_type_group_id);
-
-/*
- * Used in mdev_type_attribute sysfs functions to return the index in the
- * supported_type_groups that the sysfs is called from.
- */
-unsigned int mtype_get_type_group_id(struct mdev_type *mtype)
-{
-       return mtype->type_group_id;
-}
-EXPORT_SYMBOL(mtype_get_type_group_id);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
@@ -85,6 +65,8 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
  * @parent: parent structure registered
  * @dev: device structure representing parent device.
  * @mdev_driver: Device driver to bind to the newly created mdev
+ * @types: Array of supported mdev types
+ * @nr_types: Number of entries in @types
  *
  * Registers the @parent stucture as a parent for mdev types and thus mdev
  * 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)
  * Returns a negative value on error, otherwise 0.
  */
 int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
-               struct mdev_driver *mdev_driver)
+               struct mdev_driver *mdev_driver, struct mdev_type **types,
+               unsigned int nr_types)
 {
        char *env_string = "MDEV_STATE=registered";
        char *envp[] = { env_string, NULL };
        int ret;
 
-       /* check for mandatory ops */
-       if (!mdev_driver->supported_type_groups)
-               return -EINVAL;
-
        memset(parent, 0, sizeof(*parent));
        init_rwsem(&parent->unreg_sem);
        parent->dev = dev;
        parent->mdev_driver = mdev_driver;
+       parent->types = types;
+       parent->nr_types = nr_types;
 
        if (!mdev_bus_compat_class) {
                mdev_bus_compat_class = class_compat_register("mdev_bus");
index 7bd4bb9850e81a9f51b648fc6a5243154e7121bf..1da1ecf76a0d52915da4248fadd5a315df0c7565 100644 (file)
@@ -56,10 +56,9 @@ EXPORT_SYMBOL_GPL(mdev_bus_type);
  **/
 int mdev_register_driver(struct mdev_driver *drv)
 {
-       /* initialize common driver fields */
+       if (!drv->types_attrs)
+               return -EINVAL;
        drv->driver.bus = &mdev_bus_type;
-
-       /* register with core */
        return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(mdev_register_driver);
index 297f911fdc8902c1045983f31bc6e1c7cb62e245..ba1b2dbddc0bc22ff6415574a1559bba134f8c30 100644 (file)
 int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
-struct mdev_type {
-       struct kobject kobj;
-       struct kobject *devices_kobj;
-       struct mdev_parent *parent;
-       struct list_head next;
-       unsigned int type_group_id;
-};
-
 extern const struct attribute_group *mdev_device_groups[];
 
 #define to_mdev_type_attr(_attr)       \
index b71ffc5594870029a4cb61febe5f5b6c54f2c3dc..38b4c2466ec43d5c45578cb93099fe715fe7aba8 100644 (file)
@@ -82,7 +82,6 @@ static void mdev_type_release(struct kobject *kobj)
        pr_debug("Releasing group %s\n", kobj->name);
        /* Pairs with the get in add_mdev_supported_type() */
        put_device(type->parent->dev);
-       kfree(type);
 }
 
 static struct kobj_type mdev_type_ktype = {
@@ -90,35 +89,21 @@ static struct kobj_type mdev_type_ktype = {
        .release = mdev_type_release,
 };
 
-static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
-                                                unsigned int type_group_id)
+static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 {
-       struct mdev_type *type;
-       struct attribute_group *group =
-               parent->mdev_driver->supported_type_groups[type_group_id];
        int ret;
 
-       if (!group->name) {
-               pr_err("%s: Type name empty!\n", __func__);
-               return ERR_PTR(-EINVAL);
-       }
-
-       type = kzalloc(sizeof(*type), GFP_KERNEL);
-       if (!type)
-               return ERR_PTR(-ENOMEM);
-
        type->kobj.kset = parent->mdev_types_kset;
        type->parent = parent;
        /* Pairs with the put in mdev_type_release() */
        get_device(parent->dev);
-       type->type_group_id = type_group_id;
 
        ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
                                   "%s-%s", dev_driver_string(parent->dev),
-                                  group->name);
+                                  type->sysfs_name);
        if (ret) {
                kobject_put(&type->kobj);
-               return ERR_PTR(ret);
+               return ret;
        }
 
        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,
                goto attr_devices_failed;
        }
 
-       ret = sysfs_create_files(&type->kobj,
-                                (const struct attribute **)group->attrs);
-       if (ret) {
-               ret = -ENOMEM;
+       ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs);
+       if (ret)
                goto attrs_failed;
-       }
-       return type;
+       return 0;
 
 attrs_failed:
        kobject_put(type->devices_kobj);
@@ -146,78 +128,49 @@ attr_devices_failed:
 attr_create_failed:
        kobject_del(&type->kobj);
        kobject_put(&type->kobj);
-       return ERR_PTR(ret);
+       return ret;
 }
 
-static void remove_mdev_supported_type(struct mdev_type *type)
+static void mdev_type_remove(struct mdev_type *type)
 {
-       struct attribute_group *group =
-               type->parent->mdev_driver->supported_type_groups[type->type_group_id];
+       sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
 
-       sysfs_remove_files(&type->kobj,
-                          (const struct attribute **)group->attrs);
        kobject_put(type->devices_kobj);
        sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
        kobject_del(&type->kobj);
        kobject_put(&type->kobj);
 }
 
-static int add_mdev_supported_type_groups(struct mdev_parent *parent)
-{
-       int i;
-
-       for (i = 0; parent->mdev_driver->supported_type_groups[i]; i++) {
-               struct mdev_type *type;
-
-               type = add_mdev_supported_type(parent, i);
-               if (IS_ERR(type)) {
-                       struct mdev_type *ltype, *tmp;
-
-                       list_for_each_entry_safe(ltype, tmp, &parent->type_list,
-                                                 next) {
-                               list_del(&ltype->next);
-                               remove_mdev_supported_type(ltype);
-                       }
-                       return PTR_ERR(type);
-               }
-               list_add(&type->next, &parent->type_list);
-       }
-       return 0;
-}
-
 /* mdev sysfs functions */
 void parent_remove_sysfs_files(struct mdev_parent *parent)
 {
-       struct mdev_type *type, *tmp;
-
-       list_for_each_entry_safe(type, tmp, &parent->type_list, next) {
-               list_del(&type->next);
-               remove_mdev_supported_type(type);
-       }
+       int i;
 
+       for (i = 0; i < parent->nr_types; i++)
+               mdev_type_remove(parent->types[i]);
        kset_unregister(parent->mdev_types_kset);
 }
 
 int parent_create_sysfs_files(struct mdev_parent *parent)
 {
-       int ret;
+       int ret, i;
 
        parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
                                               NULL, &parent->dev->kobj);
-
        if (!parent->mdev_types_kset)
                return -ENOMEM;
 
-       INIT_LIST_HEAD(&parent->type_list);
-
-       ret = add_mdev_supported_type_groups(parent);
-       if (ret)
-               goto create_err;
+       for (i = 0; i < parent->nr_types; i++) {
+               ret = mdev_type_add(parent, parent->types[i]);
+               if (ret)
+                       goto out_err;
+       }
        return 0;
 
-create_err:
-       kset_unregister(parent->mdev_types_kset);
-       return ret;
+out_err:
+       while (--i >= 0)
+               mdev_type_remove(parent->types[i]);
+       return 0;
 }
 
 static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
index 262512c2a8ffcd39c28c13c6432ebf01b5504e3b..19bc93c10e8c773aec71306516f5026b89ca0313 100644 (file)
@@ -23,14 +23,27 @@ struct mdev_device {
        bool active;
 };
 
+struct mdev_type {
+       /* set by the driver before calling mdev_register parent: */
+       const char *sysfs_name;
+
+       /* set by the core, can be used drivers */
+       struct mdev_parent *parent;
+
+       /* internal only */
+       struct kobject kobj;
+       struct kobject *devices_kobj;
+};
+
 /* embedded into the struct device that the mdev devices hang off */
 struct mdev_parent {
        struct device *dev;
        struct mdev_driver *mdev_driver;
        struct kset *mdev_types_kset;
-       struct list_head type_list;
        /* Synchronize device creation/removal with parent unregistration */
        struct rw_semaphore unreg_sem;
+       struct mdev_type **types;
+       unsigned int nr_types;
 };
 
 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)
        return container_of(dev, struct mdev_device, dev);
 }
 
-unsigned int mdev_get_type_group_id(struct mdev_device *mdev);
-unsigned int mtype_get_type_group_id(struct mdev_type *mtype);
 struct device *mtype_get_parent_dev(struct mdev_type *mtype);
 
 /* interface for exporting mdev supported type attributes */
@@ -66,22 +77,21 @@ struct mdev_type_attribute mdev_type_attr_##_name =         \
  * struct mdev_driver - Mediated device driver
  * @probe: called when new device created
  * @remove: called when device removed
- * @supported_type_groups: Attributes to define supported types. It is mandatory
- *                     to provide supported types.
+ * @types_attrs: attributes to the type kobjects.
  * @driver: device driver structure
- *
  **/
 struct mdev_driver {
        int (*probe)(struct mdev_device *dev);
        void (*remove)(struct mdev_device *dev);
-       struct attribute_group **supported_type_groups;
+       const struct attribute * const *types_attrs;
        struct device_driver driver;
 };
 
 extern struct bus_type mdev_bus_type;
 
 int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
-               struct mdev_driver *mdev_driver);
+               struct mdev_driver *mdev_driver, struct mdev_type **types,
+               unsigned int nr_types);
 void mdev_unregister_parent(struct mdev_parent *parent);
 
 int mdev_register_driver(struct mdev_driver *drv);
index 2c4791abbc3d30de000fa1533d330debed29d79c..4d0839cb51943d4cdec728f038d2f8162965251f 100644 (file)
@@ -99,23 +99,27 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
 #define MBOCHS_TYPE_2 "medium"
 #define MBOCHS_TYPE_3 "large"
 
-static const struct mbochs_type {
+static struct mbochs_type {
+       struct mdev_type type;
        const char *name;
        u32 mbytes;
        u32 max_x;
        u32 max_y;
 } mbochs_types[] = {
        {
+               .type.sysfs_name        = MBOCHS_TYPE_1,
                .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
                .mbytes = 4,
                .max_x  = 800,
                .max_y  = 600,
        }, {
+               .type.sysfs_name        = MBOCHS_TYPE_2,
                .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
                .mbytes = 16,
                .max_x  = 1920,
                .max_y  = 1440,
        }, {
+               .type.sysfs_name        = MBOCHS_TYPE_3,
                .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
                .mbytes = 64,
                .max_x  = 0,
@@ -123,6 +127,11 @@ static const struct mbochs_type {
        },
 };
 
+static struct mdev_type *mbochs_mdev_types[] = {
+       &mbochs_types[0].type,
+       &mbochs_types[1].type,
+       &mbochs_types[2].type,
+};
 
 static dev_t           mbochs_devt;
 static struct class    *mbochs_class;
@@ -510,8 +519,8 @@ static int mbochs_init_dev(struct vfio_device *vdev)
        struct mdev_state *mdev_state =
                container_of(vdev, struct mdev_state, vdev);
        struct mdev_device *mdev = to_mdev_device(vdev->dev);
-       const struct mbochs_type *type =
-               &mbochs_types[mdev_get_type_group_id(mdev)];
+       struct mbochs_type *type =
+               container_of(mdev->type, struct mbochs_type, type);
        int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
        int ret = -ENOMEM;
 
@@ -1345,8 +1354,8 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
                         struct mdev_type_attribute *attr, char *buf)
 {
-       const struct mbochs_type *type =
-               &mbochs_types[mtype_get_type_group_id(mtype)];
+       struct mbochs_type *type =
+               container_of(mtype, struct mbochs_type, type);
 
        return sprintf(buf, "%s\n", type->name);
 }
@@ -1355,8 +1364,8 @@ static MDEV_TYPE_ATTR_RO(name);
 static ssize_t description_show(struct mdev_type *mtype,
                                struct mdev_type_attribute *attr, char *buf)
 {
-       const struct mbochs_type *type =
-               &mbochs_types[mtype_get_type_group_id(mtype)];
+       struct mbochs_type *type =
+               container_of(mtype, struct mbochs_type, type);
 
        return sprintf(buf, "virtual display, %d MB video memory\n",
                       type ? type->mbytes  : 0);
@@ -1367,8 +1376,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
                                        struct mdev_type_attribute *attr,
                                        char *buf)
 {
-       const struct mbochs_type *type =
-               &mbochs_types[mtype_get_type_group_id(mtype)];
+       struct mbochs_type *type =
+               container_of(mtype, struct mbochs_type, type);
        int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
 
        return sprintf(buf, "%d\n", count);
@@ -1382,7 +1391,7 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
        &mdev_type_attr_name.attr,
        &mdev_type_attr_description.attr,
        &mdev_type_attr_device_api.attr,
@@ -1390,28 +1399,6 @@ static struct attribute *mdev_types_attrs[] = {
        NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-       .name  = MBOCHS_TYPE_1,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-       .name  = MBOCHS_TYPE_2,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group3 = {
-       .name  = MBOCHS_TYPE_3,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-       &mdev_type_group1,
-       &mdev_type_group2,
-       &mdev_type_group3,
-       NULL,
-};
-
 static const struct vfio_device_ops mbochs_dev_ops = {
        .close_device = mbochs_close_device,
        .init = mbochs_init_dev,
@@ -1431,7 +1418,7 @@ static struct mdev_driver mbochs_driver = {
        },
        .probe = mbochs_probe,
        .remove = mbochs_remove,
-       .supported_type_groups = mdev_type_groups,
+       .types_attrs = mdev_types_attrs,
 };
 
 static const struct file_operations vd_fops = {
@@ -1476,7 +1463,9 @@ static int __init mbochs_dev_init(void)
        if (ret)
                goto err_class;
 
-       ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver);
+       ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver,
+                                  mbochs_mdev_types,
+                                  ARRAY_SIZE(mbochs_mdev_types));
        if (ret)
                goto err_device;
 
index 01f345430b9757202745c5025876b0e1e5959479..4a341f4849e73a07df114083bc8884d2890e23cb 100644 (file)
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
 #define MDPY_TYPE_2 "xga"
 #define MDPY_TYPE_3 "hd"
 
-static const struct mdpy_type {
+static struct mdpy_type {
+       struct mdev_type type;
        const char *name;
        u32 format;
        u32 bytepp;
@@ -59,18 +60,21 @@ static const struct mdpy_type {
        u32 height;
 } mdpy_types[] = {
        {
+               .type.sysfs_name        = MDPY_TYPE_1,
                .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
                .format = DRM_FORMAT_XRGB8888,
                .bytepp = 4,
                .width  = 640,
                .height = 480,
        }, {
+               .type.sysfs_name        = MDPY_TYPE_2,
                .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
                .format = DRM_FORMAT_XRGB8888,
                .bytepp = 4,
                .width  = 1024,
                .height = 768,
        }, {
+               .type.sysfs_name        = MDPY_TYPE_3,
                .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
                .format = DRM_FORMAT_XRGB8888,
                .bytepp = 4,
@@ -79,6 +83,12 @@ static const struct mdpy_type {
        },
 };
 
+static struct mdev_type *mdpy_mdev_types[] = {
+       &mdpy_types[0].type,
+       &mdpy_types[1].type,
+       &mdpy_types[2].type,
+};
+
 static dev_t           mdpy_devt;
 static struct class    *mdpy_class;
 static struct cdev     mdpy_cdev;
@@ -222,7 +232,7 @@ static int mdpy_init_dev(struct vfio_device *vdev)
                container_of(vdev, struct mdev_state, vdev);
        struct mdev_device *mdev = to_mdev_device(vdev->dev);
        const struct mdpy_type *type =
-               &mdpy_types[mdev_get_type_group_id(mdev)];
+               container_of(mdev->type, struct mdpy_type, type);
        u32 fbsize;
        int ret = -ENOMEM;
 
@@ -655,8 +665,7 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
                         struct mdev_type_attribute *attr, char *buf)
 {
-       const struct mdpy_type *type =
-               &mdpy_types[mtype_get_type_group_id(mtype)];
+       struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
 
        return sprintf(buf, "%s\n", type->name);
 }
@@ -665,8 +674,7 @@ static MDEV_TYPE_ATTR_RO(name);
 static ssize_t description_show(struct mdev_type *mtype,
                                struct mdev_type_attribute *attr, char *buf)
 {
-       const struct mdpy_type *type =
-               &mdpy_types[mtype_get_type_group_id(mtype)];
+       struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
 
        return sprintf(buf, "virtual display, %dx%d framebuffer\n",
                       type->width, type->height);
@@ -688,7 +696,7 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
        &mdev_type_attr_name.attr,
        &mdev_type_attr_description.attr,
        &mdev_type_attr_device_api.attr,
@@ -696,28 +704,6 @@ static struct attribute *mdev_types_attrs[] = {
        NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-       .name  = MDPY_TYPE_1,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-       .name  = MDPY_TYPE_2,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group3 = {
-       .name  = MDPY_TYPE_3,
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-       &mdev_type_group1,
-       &mdev_type_group2,
-       &mdev_type_group3,
-       NULL,
-};
-
 static const struct vfio_device_ops mdpy_dev_ops = {
        .init = mdpy_init_dev,
        .release = mdpy_release_dev,
@@ -736,7 +722,7 @@ static struct mdev_driver mdpy_driver = {
        },
        .probe = mdpy_probe,
        .remove = mdpy_remove,
-       .supported_type_groups = mdev_type_groups,
+       .types_attrs = mdev_types_attrs,
 };
 
 static const struct file_operations vd_fops = {
@@ -779,7 +765,9 @@ static int __init mdpy_dev_init(void)
        if (ret)
                goto err_class;
 
-       ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver);
+       ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver,
+                                  mdpy_mdev_types,
+                                  ARRAY_SIZE(mdpy_mdev_types));
        if (ret)
                goto err_device;
 
index e80baac51381147965dbc671c6990443821d3ede..814a7f98738a261b2860e03cbd602d8f60d734e3 100644 (file)
@@ -143,6 +143,20 @@ struct mdev_state {
        int nr_ports;
 };
 
+static struct mtty_type {
+       struct mdev_type type;
+       int nr_ports;
+       const char *name;
+} mtty_types[2] = {
+       { .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port serial" },
+       { .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port serial" },
+};
+
+static struct mdev_type *mtty_mdev_types[] = {
+       &mtty_types[0].type,
+       &mtty_types[1].type,
+};
+
 static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS);
 
 static const struct file_operations vd_fops = {
@@ -707,17 +721,19 @@ static int mtty_init_dev(struct vfio_device *vdev)
        struct mdev_state *mdev_state =
                container_of(vdev, struct mdev_state, vdev);
        struct mdev_device *mdev = to_mdev_device(vdev->dev);
-       int nr_ports = mdev_get_type_group_id(mdev) + 1;
+       struct mtty_type *type =
+               container_of(mdev->type, struct mtty_type, type);
        int avail_ports = atomic_read(&mdev_avail_ports);
        int ret;
 
        do {
-               if (avail_ports < nr_ports)
+               if (avail_ports < type->nr_ports)
                        return -ENOSPC;
        } while (!atomic_try_cmpxchg(&mdev_avail_ports,
-                                    &avail_ports, avail_ports - nr_ports));
+                                    &avail_ports,
+                                    avail_ports - type->nr_ports));
 
-       mdev_state->nr_ports = nr_ports;
+       mdev_state->nr_ports = type->nr_ports;
        mdev_state->irq_index = -1;
        mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
        mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE;
@@ -735,7 +751,7 @@ static int mtty_init_dev(struct vfio_device *vdev)
        return 0;
 
 err_nr_ports:
-       atomic_add(nr_ports, &mdev_avail_ports);
+       atomic_add(type->nr_ports, &mdev_avail_ports);
        return ret;
 }
 
@@ -1242,11 +1258,9 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
                         struct mdev_type_attribute *attr, char *buf)
 {
-       static const char *name_str[2] = { "Single port serial",
-                                          "Dual port serial" };
+       struct mtty_type *type = container_of(mtype, struct mtty_type, type);
 
-       return sysfs_emit(buf, "%s\n",
-                         name_str[mtype_get_type_group_id(mtype)]);
+       return sysfs_emit(buf, "%s\n", type->name);
 }
 
 static MDEV_TYPE_ATTR_RO(name);
@@ -1255,9 +1269,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
                                        struct mdev_type_attribute *attr,
                                        char *buf)
 {
-       unsigned int ports = mtype_get_type_group_id(mtype) + 1;
+       struct mtty_type *type = container_of(mtype, struct mtty_type, type);
 
-       return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / ports);
+       return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
+                       type->nr_ports);
 }
 
 static MDEV_TYPE_ATTR_RO(available_instances);
@@ -1270,29 +1285,13 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
        &mdev_type_attr_name.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_available_instances.attr,
        NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-       .name  = "1",
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-       .name  = "2",
-       .attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-       &mdev_type_group1,
-       &mdev_type_group2,
-       NULL,
-};
-
 static const struct vfio_device_ops mtty_dev_ops = {
        .name = "vfio-mtty",
        .init = mtty_init_dev,
@@ -1311,7 +1310,7 @@ static struct mdev_driver mtty_driver = {
        },
        .probe = mtty_probe,
        .remove = mtty_remove,
-       .supported_type_groups = mdev_type_groups,
+       .types_attrs = mdev_types_attrs,
 };
 
 static void mtty_device_release(struct device *dev)
@@ -1363,7 +1362,8 @@ static int __init mtty_dev_init(void)
                goto err_class;
 
        ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,
-                                  &mtty_driver);
+                                  &mtty_driver, mtty_mdev_types,
+                                  ARRAY_SIZE(mtty_mdev_types));
        if (ret)
                goto err_device;
        return 0;