driver core: auxiliary bus: add device creation helpers

Add helper functions to create a device on the auxiliary bus.

This is meant for fairly simple usage of the auxiliary bus, to avoid having
the same code repeated in the different drivers.

Suggested-by: Stephen Boyd <sboyd@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Link: https://lore.kernel.org/r/20250218-aux-device-create-helper-v4-1-c3d7dfdea2e6@baylibre.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jerome Brunet 2025-02-18 20:29:46 +01:00 committed by Greg Kroah-Hartman
parent d487858ebf
commit eaa0d30216
2 changed files with 125 additions and 0 deletions

View file

@ -385,6 +385,114 @@ void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv)
} }
EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); EXPORT_SYMBOL_GPL(auxiliary_driver_unregister);
static void auxiliary_device_release(struct device *dev)
{
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
kfree(auxdev);
}
/**
* auxiliary_device_create - create a device on the auxiliary bus
* @dev: parent device
* @modname: module name used to create the auxiliary driver name.
* @devname: auxiliary bus device name
* @platform_data: auxiliary bus device platform data
* @id: auxiliary bus device id
*
* Helper to create an auxiliary bus device.
* The device created matches driver 'modname.devname' on the auxiliary bus.
*/
struct auxiliary_device *auxiliary_device_create(struct device *dev,
const char *modname,
const char *devname,
void *platform_data,
int id)
{
struct auxiliary_device *auxdev;
int ret;
auxdev = kzalloc(sizeof(*auxdev), GFP_KERNEL);
if (!auxdev)
return NULL;
auxdev->id = id;
auxdev->name = devname;
auxdev->dev.parent = dev;
auxdev->dev.platform_data = platform_data;
auxdev->dev.release = auxiliary_device_release;
device_set_of_node_from_dev(&auxdev->dev, dev);
ret = auxiliary_device_init(auxdev);
if (ret) {
kfree(auxdev);
return NULL;
}
ret = __auxiliary_device_add(auxdev, modname);
if (ret) {
/*
* It may look odd but auxdev should not be freed here.
* auxiliary_device_uninit() calls device_put() which call
* the device release function, freeing auxdev.
*/
auxiliary_device_uninit(auxdev);
return NULL;
}
return auxdev;
}
EXPORT_SYMBOL_GPL(auxiliary_device_create);
/**
* auxiliary_device_destroy - remove an auxiliary device
* @auxdev: pointer to the auxdev to be removed
*
* Helper to remove an auxiliary device created with
* auxiliary_device_create()
*/
void auxiliary_device_destroy(void *auxdev)
{
struct auxiliary_device *_auxdev = auxdev;
auxiliary_device_delete(_auxdev);
auxiliary_device_uninit(_auxdev);
}
EXPORT_SYMBOL_GPL(auxiliary_device_destroy);
/**
* __devm_auxiliary_device_create - create a managed device on the auxiliary bus
* @dev: parent device
* @modname: module name used to create the auxiliary driver name.
* @devname: auxiliary bus device name
* @platform_data: auxiliary bus device platform data
* @id: auxiliary bus device id
*
* Device managed helper to create an auxiliary bus device.
* The device created matches driver 'modname.devname' on the auxiliary bus.
*/
struct auxiliary_device *__devm_auxiliary_device_create(struct device *dev,
const char *modname,
const char *devname,
void *platform_data,
int id)
{
struct auxiliary_device *auxdev;
int ret;
auxdev = auxiliary_device_create(dev, modname, devname, platform_data, id);
if (IS_ERR(auxdev))
return auxdev;
ret = devm_add_action_or_reset(dev, auxiliary_device_destroy,
auxdev);
if (ret)
return ERR_PTR(ret);
return auxdev;
}
EXPORT_SYMBOL_GPL(__devm_auxiliary_device_create);
void __init auxiliary_bus_init(void) void __init auxiliary_bus_init(void)
{ {
WARN_ON(bus_register(&auxiliary_bus_type)); WARN_ON(bus_register(&auxiliary_bus_type));

View file

@ -254,6 +254,23 @@ int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *
void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv); void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv);
struct auxiliary_device *auxiliary_device_create(struct device *dev,
const char *modname,
const char *devname,
void *platform_data,
int id);
void auxiliary_device_destroy(void *auxdev);
struct auxiliary_device *__devm_auxiliary_device_create(struct device *dev,
const char *modname,
const char *devname,
void *platform_data,
int id);
#define devm_auxiliary_device_create(dev, devname, platform_data) \
__devm_auxiliary_device_create(dev, KBUILD_MODNAME, devname, \
platform_data, 0)
/** /**
* module_auxiliary_driver() - Helper macro for registering an auxiliary driver * module_auxiliary_driver() - Helper macro for registering an auxiliary driver
* @__auxiliary_driver: auxiliary driver struct * @__auxiliary_driver: auxiliary driver struct