Documentation/auxiliary_bus: Clarify auxiliary_device creation

The documentation for creating an auxiliary device is a 3 step not a 2
step process.  Specifically the requirements of setting the name, id,
dev.release, and dev.parent fields was not clear as a precursor to the '2
step' process documented.

Clarify by declaring this a 3 step process starting with setting the
fields of struct auxiliary_device correctly.

Also add some sample code and tie the change into the rest of the
documentation.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Link: https://lore.kernel.org/r/20211202044305.4006853-2-ira.weiny@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ira Weiny 2021-12-01 20:42:59 -08:00 committed by Greg Kroah-Hartman
parent f1045056c7
commit b247703873
2 changed files with 63 additions and 22 deletions

View File

@ -71,26 +71,14 @@ they are not physical devices that are controlled by DT/ACPI. The same
argument applies for not using MFD in this scenario as MFD relies on individual
function devices being physical devices.
Auxiliary Device
================
Auxiliary Device Creation
=========================
An auxiliary_device represents a part of its parent device's functionality. It
is given a name that, combined with the registering drivers KBUILD_MODNAME,
creates a match_name that is used for driver binding, and an id that combined
with the match_name provide a unique name to register with the bus subsystem.
Registering an auxiliary_device is a two-step process. First call
auxiliary_device_init(), which checks several aspects of the auxiliary_device
struct and performs a device_initialize(). After this step completes, any
error state must have a call to auxiliary_device_uninit() in its resolution path.
The second step in registering an auxiliary_device is to perform a call to
auxiliary_device_add(), which sets the name of the device and add the device to
the bus.
Unregistering an auxiliary_device is also a two-step process to mirror the
register process. First call auxiliary_device_delete(), then call
auxiliary_device_uninit().
.. code-block:: c
struct auxiliary_device {
@ -99,15 +87,68 @@ auxiliary_device_uninit().
u32 id;
};
If two auxiliary_devices both with a match_name "mod.foo" are registered onto
the bus, they must have unique id values (e.g. "x" and "y") so that the
registered devices names are "mod.foo.x" and "mod.foo.y". If match_name + id
are not unique, then the device_add fails and generates an error message.
Registering an auxiliary_device is a three-step process.
First, a 'struct auxiliary_device' needs to be defined or allocated for each
sub-device desired. The name, id, dev.release, and dev.parent fields of this
structure must be filled in as follows.
The 'name' field is to be given a name that is recognized by the auxiliary
driver. If two auxiliary_devices with the same match_name, eg
"mod.MY_DEVICE_NAME", are registered onto the bus, they must have unique id
values (e.g. "x" and "y") so that the registered devices names are "mod.foo.x"
and "mod.foo.y". If match_name + id are not unique, then the device_add fails
and generates an error message.
The auxiliary_device.dev.type.release or auxiliary_device.dev.release must be
populated with a non-NULL pointer to successfully register the auxiliary_device.
populated with a non-NULL pointer to successfully register the
auxiliary_device. This release call is where resources associated with the
auxiliary device must be free'ed. Because once the device is placed on the bus
the parent driver can not tell what other code may have a reference to this
data.
The auxiliary_device.dev.parent should be set. Typically to the registering
drivers device.
Second, call auxiliary_device_init(), which checks several aspects of the
auxiliary_device struct and performs a device_initialize(). After this step
completes, any error state must have a call to auxiliary_device_uninit() in its
resolution path.
The third and final step in registering an auxiliary_device is to perform a
call to auxiliary_device_add(), which sets the name of the device and adds the
device to the bus.
.. code-block:: c
struct auxiliary_device *my_aux_dev = my_aux_dev_alloc(xxx);
/* Step 1: */
my_aux_dev->name = MY_DEVICE_NAME;
my_aux_dev->id = my_unique_id_alloc(xxx);
my_aux_dev->dev.release = my_aux_dev_release;
my_aux_dev->dev.parent = my_dev;
/* Step 2: */
if (auxiliary_device_init(my_aux_dev))
goto fail;
/* Step 3: */
if (auxiliary_device_add(my_aux_dev)) {
auxiliary_device_uninit(my_aux_dev);
goto fail;
}
Unregistering an auxiliary_device is a two-step process to mirror the register
process. First call auxiliary_device_delete(), then call
auxiliary_device_uninit().
.. code-block:: c
auxiliary_device_delete(my_dev->my_aux_dev);
auxiliary_device_uninit(my_dev->my_aux_dev);
The auxiliary_device.dev.parent must also be populated.
Auxiliary Device Memory Model and Lifespan
------------------------------------------

View File

@ -117,7 +117,7 @@ static struct bus_type auxiliary_bus_type = {
* auxiliary_device_init - check auxiliary_device and initialize
* @auxdev: auxiliary device struct
*
* This is the first step in the two-step process to register an
* This is the second step in the three-step process to register an
* auxiliary_device.
*
* When this function returns an error code, then the device_initialize will
@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(auxiliary_device_init);
* @auxdev: auxiliary bus device to add to the bus
* @modname: name of the parent device's driver module
*
* This is the second step in the two-step process to register an
* This is the third step in the three-step process to register an
* auxiliary_device.
*
* This function must be called after a successful call to