Re: [PATCH 05/14] vfio/mdev: simplify mdev_type handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> 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@xxxxxx>
> Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>
> Reviewed-by: Tony Krowiak <akrowiak@xxxxxxxxxxxxx>
> Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx>
> Reviewed-by: Kirti Wankhede <kwankhede@xxxxxxxxxx>

Reviewed-by: Eric Farman <farman@xxxxxxxxxxxxx>

> ---
>  .../driver-api/vfio-mediated-device.rst       |   2 +-
>  drivers/gpu/drm/i915/gvt/gvt.h                |   3 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c              | 102 +++-------------
> --
>  drivers/gpu/drm/i915/gvt/vgpu.c               |  13 ++-
>  drivers/s390/cio/vfio_ccw_drv.c               |   6 +-
>  drivers/s390/cio/vfio_ccw_ops.c               |  14 +--
>  drivers/s390/cio/vfio_ccw_private.h           |   2 +
>  drivers/s390/crypto/vfio_ap_ops.c             |  19 ++--
>  drivers/s390/crypto/vfio_ap_private.h         |   2 +
>  drivers/vfio/mdev/mdev_core.c                 |  31 ++----
>  drivers/vfio/mdev/mdev_driver.c               |   5 +-
>  drivers/vfio/mdev/mdev_private.h              |   8 --
>  drivers/vfio/mdev/mdev_sysfs.c                |  91 ++++------------
>  include/linux/mdev.h                          |  26 +++--
>  samples/vfio-mdev/mbochs.c                    |  57 ++++------
>  samples/vfio-mdev/mdpy.c                      |  50 ++++-----
>  samples/vfio-mdev/mtty.c                      |  60 +++++------
>  17 files changed, 165 insertions(+), 326 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index cd1667608ab5d..ff7342d2e332d 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -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;
>       };
>  
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> b/drivers/gpu/drm/i915/gvt/gvt.h
> index fa4a56b50c828..db182066d56c9 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -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;
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 29531b797010f..ce6b8cb37be0c 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -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);
>  }
>  
> @@ -1624,7 +1556,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)
> @@ -1923,7 +1855,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);
>  
> @@ -2023,20 +1954,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);
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 1b67328c714f1..8fa06d00fd4b9 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -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 @@ int intel_gvt_init_vgpu_types(struct intel_gvt
> *gvt)
>  
>  void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
>  {
> +       kfree(gvt->mdev_types);
>         kfree(gvt->types);
>  }
>  
> diff --git a/drivers/s390/cio/vfio_ccw_drv.c
> b/drivers/s390/cio/vfio_ccw_drv.c
> index 7d105915bd149..25a5de08b3902 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -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;
>  
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 9a0e0c5ffb1a5..c37e712a4b069 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -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,
>  };
> diff --git a/drivers/s390/cio/vfio_ccw_private.h
> b/drivers/s390/cio/vfio_ccw_private.h
> index 1a4bfb1b5a808..52caa721ec06c 100644
> --- a/drivers/s390/cio/vfio_ccw_private.h
> +++ b/drivers/s390/cio/vfio_ccw_private.h
> @@ -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);
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 724d09a74a8f1..24d131c502ca3 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -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;
> diff --git a/drivers/s390/crypto/vfio_ap_private.h
> b/drivers/s390/crypto/vfio_ap_private.h
> index 35165730f5174..441dc8dda380b 100644
> --- a/drivers/s390/crypto/vfio_ap_private.h
> +++ b/drivers/s390/crypto/vfio_ap_private.h
> @@ -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;
> diff --git a/drivers/vfio/mdev/mdev_core.c
> b/drivers/vfio/mdev/mdev_core.c
> index fa05ac3396950..2d95a497fd3b2 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -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");
> diff --git a/drivers/vfio/mdev/mdev_driver.c
> b/drivers/vfio/mdev/mdev_driver.c
> index 7bd4bb9850e81..1da1ecf76a0d5 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -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);
> diff --git a/drivers/vfio/mdev/mdev_private.h
> b/drivers/vfio/mdev/mdev_private.h
> index 297f911fdc890..ba1b2dbddc0bc 100644
> --- a/drivers/vfio/mdev/mdev_private.h
> +++ b/drivers/vfio/mdev/mdev_private.h
> @@ -13,14 +13,6 @@
>  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)       \
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index b71ffc5594870..38b4c2466ec43 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -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 @@ static struct mdev_type
> *add_mdev_supported_type(struct mdev_parent *parent,
>  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,
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index 262512c2a8ffc..19bc93c10e8c7 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -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);
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 2c4791abbc3d3..4d0839cb51943 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -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;
>  
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 01f345430b975..4a341f4849e73 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -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;
>  
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index e80baac513811..814a7f98738a2 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -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;





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux