1.. SPDX-License-Identifier: GPL-2.0-only 2 3.. _auxiliary_bus: 4 5============= 6Auxiliary Bus 7============= 8 9In some subsystems, the functionality of the core device (PCI/ACPI/other) is 10too complex for a single device to be managed by a monolithic driver 11(e.g. Sound Open Firmware), multiple devices might implement a common 12intersection of functionality (e.g. NICs + RDMA), or a driver may want to 13export an interface for another subsystem to drive (e.g. SIOV Physical Function 14export Virtual Function management). A split of the functionality into child- 15devices representing sub-domains of functionality makes it possible to 16compartmentalize, layer, and distribute domain-specific concerns via a Linux 17device-driver model. 18 19An example for this kind of requirement is the audio subsystem where a single 20IP is handling multiple entities such as HDMI, Soundwire, local devices such as 21mics/speakers etc. The split for the core's functionality can be arbitrary or 22be defined by the DSP firmware topology and include hooks for test/debug. This 23allows for the audio core device to be minimal and focused on hardware-specific 24control and communication. 25 26Each auxiliary_device represents a part of its parent functionality. The 27generic behavior can be extended and specialized as needed by encapsulating an 28auxiliary_device within other domain-specific structures and the use of .ops 29callbacks. Devices on the auxiliary bus do not share any structures and the use 30of a communication channel with the parent is domain-specific. 31 32Note that ops are intended as a way to augment instance behavior within a class 33of auxiliary devices, it is not the mechanism for exporting common 34infrastructure from the parent. Consider EXPORT_SYMBOL_NS() to convey 35infrastructure from the parent module to the auxiliary module(s). 36 37 38When Should the Auxiliary Bus Be Used 39===================================== 40 41The auxiliary bus is to be used when a driver and one or more kernel modules, 42who share a common header file with the driver, need a mechanism to connect and 43provide access to a shared object allocated by the auxiliary_device's 44registering driver. The registering driver for the auxiliary_device(s) and the 45kernel module(s) registering auxiliary_drivers can be from the same subsystem, 46or from multiple subsystems. 47 48The emphasis here is on a common generic interface that keeps subsystem 49customization out of the bus infrastructure. 50 51One example is a PCI network device that is RDMA-capable and exports a child 52device to be driven by an auxiliary_driver in the RDMA subsystem. The PCI 53driver allocates and registers an auxiliary_device for each physical 54function on the NIC. The RDMA driver registers an auxiliary_driver that claims 55each of these auxiliary_devices. This conveys data/ops published by the parent 56PCI device/driver to the RDMA auxiliary_driver. 57 58Another use case is for the PCI device to be split out into multiple sub 59functions. For each sub function an auxiliary_device is created. A PCI sub 60function driver binds to such devices that creates its own one or more class 61devices. A PCI sub function auxiliary device is likely to be contained in a 62struct with additional attributes such as user defined sub function number and 63optional attributes such as resources and a link to the parent device. These 64attributes could be used by systemd/udev; and hence should be initialized 65before a driver binds to an auxiliary_device. 66 67A key requirement for utilizing the auxiliary bus is that there is no 68dependency on a physical bus, device, register accesses or regmap support. 69These individual devices split from the core cannot live on the platform bus as 70they are not physical devices that are controlled by DT/ACPI. The same 71argument applies for not using MFD in this scenario as MFD relies on individual 72function devices being physical devices. 73 74Auxiliary Device Creation 75========================= 76 77An auxiliary_device represents a part of its parent device's functionality. It 78is given a name that, combined with the registering drivers KBUILD_MODNAME, 79creates a match_name that is used for driver binding, and an id that combined 80with the match_name provide a unique name to register with the bus subsystem. 81For example, a driver registering an auxiliary device is named 'foo_mod.ko' and 82the subdevice is named 'foo_dev'. The match name is therefore 83'foo_mod.foo_dev'. 84 85.. code-block:: c 86 87 struct auxiliary_device { 88 struct device dev; 89 const char *name; 90 u32 id; 91 }; 92 93Registering an auxiliary_device is a three-step process. 94 95First, a 'struct auxiliary_device' needs to be defined or allocated for each 96sub-device desired. The name, id, dev.release, and dev.parent fields of this 97structure must be filled in as follows. 98 99The 'name' field is to be given a name that is recognized by the auxiliary 100driver. If two auxiliary_devices with the same match_name, eg 101"foo_mod.foo_dev", are registered onto the bus, they must have unique id 102values (e.g. "x" and "y") so that the registered devices names are "foo_mod.foo_dev.x" 103and "foo_mod.foo_dev.y". If match_name + id are not unique, then the device_add fails 104and generates an error message. 105 106The auxiliary_device.dev.type.release or auxiliary_device.dev.release must be 107populated with a non-NULL pointer to successfully register the 108auxiliary_device. This release call is where resources associated with the 109auxiliary device must be free'ed. Because once the device is placed on the bus 110the parent driver can not tell what other code may have a reference to this 111data. 112 113The auxiliary_device.dev.parent should be set. Typically to the registering 114drivers device. 115 116Second, call auxiliary_device_init(), which checks several aspects of the 117auxiliary_device struct and performs a device_initialize(). After this step 118completes, any error state must have a call to auxiliary_device_uninit() in its 119resolution path. 120 121The third and final step in registering an auxiliary_device is to perform a 122call to auxiliary_device_add(), which sets the name of the device and adds the 123device to the bus. 124 125.. code-block:: c 126 127 #define MY_DEVICE_NAME "foo_dev" 128 129 ... 130 131 struct auxiliary_device *my_aux_dev = my_aux_dev_alloc(xxx); 132 133 /* Step 1: */ 134 my_aux_dev->name = MY_DEVICE_NAME; 135 my_aux_dev->id = my_unique_id_alloc(xxx); 136 my_aux_dev->dev.release = my_aux_dev_release; 137 my_aux_dev->dev.parent = my_dev; 138 139 /* Step 2: */ 140 if (auxiliary_device_init(my_aux_dev)) 141 goto fail; 142 143 /* Step 3: */ 144 if (auxiliary_device_add(my_aux_dev)) { 145 auxiliary_device_uninit(my_aux_dev); 146 goto fail; 147 } 148 149 ... 150 151 152Unregistering an auxiliary_device is a two-step process to mirror the register 153process. First call auxiliary_device_delete(), then call 154auxiliary_device_uninit(). 155 156 157.. code-block:: c 158 159 auxiliary_device_delete(my_dev->my_aux_dev); 160 auxiliary_device_uninit(my_dev->my_aux_dev); 161 162 163Auxiliary Device Memory Model and Lifespan 164------------------------------------------ 165 166The registering driver is the entity that allocates memory for the 167auxiliary_device and registers it on the auxiliary bus. It is important to note 168that, as opposed to the platform bus, the registering driver is wholly 169responsible for the management of the memory used for the device object. 170 171To be clear the memory for the auxiliary_device is freed in the release() 172callback defined by the registering driver. The registering driver should only 173call auxiliary_device_delete() and then auxiliary_device_uninit() when it is 174done with the device. The release() function is then automatically called if 175and when other code releases their reference to the devices. 176 177A parent object, defined in the shared header file, contains the 178auxiliary_device. It also contains a pointer to the shared object(s), which 179also is defined in the shared header. Both the parent object and the shared 180object(s) are allocated by the registering driver. This layout allows the 181auxiliary_driver's registering module to perform a container_of() call to go 182from the pointer to the auxiliary_device, that is passed during the call to the 183auxiliary_driver's probe function, up to the parent object, and then have 184access to the shared object(s). 185 186The memory for the shared object(s) must have a lifespan equal to, or greater 187than, the lifespan of the memory for the auxiliary_device. The 188auxiliary_driver should only consider that the shared object is valid as long 189as the auxiliary_device is still registered on the auxiliary bus. It is up to 190the registering driver to manage (e.g. free or keep available) the memory for 191the shared object beyond the life of the auxiliary_device. 192 193The registering driver must unregister all auxiliary devices before its own 194driver.remove() is completed. An easy way to ensure this is to use the 195devm_add_action_or_reset() call to register a function against the parent device 196which unregisters the auxiliary device object(s). 197 198Finally, any operations which operate on the auxiliary devices must continue to 199function (if only to return an error) after the registering driver unregisters 200the auxiliary device. 201 202 203Auxiliary Drivers 204================= 205 206Auxiliary drivers follow the standard driver model convention, where 207discovery/enumeration is handled by the core, and drivers 208provide probe() and remove() methods. They support power management 209and shutdown notifications using the standard conventions. 210 211.. code-block:: c 212 213 struct auxiliary_driver { 214 int (*probe)(struct auxiliary_device *, 215 const struct auxiliary_device_id *id); 216 void (*remove)(struct auxiliary_device *); 217 void (*shutdown)(struct auxiliary_device *); 218 int (*suspend)(struct auxiliary_device *, pm_message_t); 219 int (*resume)(struct auxiliary_device *); 220 struct device_driver driver; 221 const struct auxiliary_device_id *id_table; 222 }; 223 224Auxiliary drivers register themselves with the bus by calling 225auxiliary_driver_register(). The id_table contains the match_names of auxiliary 226devices that a driver can bind with. 227 228.. code-block:: c 229 230 static const struct auxiliary_device_id my_auxiliary_id_table[] = { 231 { .name = "foo_mod.foo_dev" }, 232 {}, 233 }; 234 235 MODULE_DEVICE_TABLE(auxiliary, my_auxiliary_id_table); 236 237 struct auxiliary_driver my_drv = { 238 .name = "myauxiliarydrv", 239 .id_table = my_auxiliary_id_table, 240 .probe = my_drv_probe, 241 .remove = my_drv_remove 242 }; 243 244 245Example Usage 246============= 247 248Auxiliary devices are created and registered by a subsystem-level core device 249that needs to break up its functionality into smaller fragments. One way to 250extend the scope of an auxiliary_device is to encapsulate it within a domain- 251pecific structure defined by the parent device. This structure contains the 252auxiliary_device and any associated shared data/callbacks needed to establish 253the connection with the parent. 254 255An example is: 256 257.. code-block:: c 258 259 struct foo { 260 struct auxiliary_device auxdev; 261 void (*connect)(struct auxiliary_device *auxdev); 262 void (*disconnect)(struct auxiliary_device *auxdev); 263 void *data; 264 }; 265 266The parent device then registers the auxiliary_device by calling 267auxiliary_device_init(), and then auxiliary_device_add(), with the pointer to 268the auxdev member of the above structure. The parent provides a name for the 269auxiliary_device that, combined with the parent's KBUILD_MODNAME, creates a 270match_name that is be used for matching and binding with a driver. 271 272Whenever an auxiliary_driver is registered, based on the match_name, the 273auxiliary_driver's probe() is invoked for the matching devices. The 274auxiliary_driver can also be encapsulated inside custom drivers that make the 275core device's functionality extensible by adding additional domain-specific ops 276as follows: 277 278.. code-block:: c 279 280 struct my_ops { 281 void (*send)(struct auxiliary_device *auxdev); 282 void (*receive)(struct auxiliary_device *auxdev); 283 }; 284 285 286 struct my_driver { 287 struct auxiliary_driver auxiliary_drv; 288 const struct my_ops ops; 289 }; 290 291An example of this type of usage is: 292 293.. code-block:: c 294 295 const struct auxiliary_device_id my_auxiliary_id_table[] = { 296 { .name = "foo_mod.foo_dev" }, 297 { }, 298 }; 299 300 const struct my_ops my_custom_ops = { 301 .send = my_tx, 302 .receive = my_rx, 303 }; 304 305 const struct my_driver my_drv = { 306 .auxiliary_drv = { 307 .name = "myauxiliarydrv", 308 .id_table = my_auxiliary_id_table, 309 .probe = my_probe, 310 .remove = my_remove, 311 .shutdown = my_shutdown, 312 }, 313 .ops = my_custom_ops, 314 }; 315