vfio/mdev: simplify mdev_type handling

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

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

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Link: https://lore.kernel.org/r/20220923092652.100656-6-hch@lst.de
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
Christoph Hellwig
2022-09-23 11:26:43 +02:00
committed by Alex Williamson
parent 89345d5177
commit da44c340c4
17 changed files with 165 additions and 326 deletions
+6 -25
View 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");
+2 -3
View 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);
-8
View File
@@ -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) \
+22 -69
View 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,