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