Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Componentized device handling.
4 : : *
5 : : * This is work in progress. We gather up the component devices into a list,
6 : : * and bind them when instructed. At the moment, we're specific to the DRM
7 : : * subsystem, and only handles one master device, but this doesn't have to be
8 : : * the case.
9 : : */
10 : : #include <linux/component.h>
11 : : #include <linux/device.h>
12 : : #include <linux/kref.h>
13 : : #include <linux/list.h>
14 : : #include <linux/mutex.h>
15 : : #include <linux/slab.h>
16 : : #include <linux/debugfs.h>
17 : :
18 : : /**
19 : : * DOC: overview
20 : : *
21 : : * The component helper allows drivers to collect a pile of sub-devices,
22 : : * including their bound drivers, into an aggregate driver. Various subsystems
23 : : * already provide functions to get hold of such components, e.g.
24 : : * of_clk_get_by_name(). The component helper can be used when such a
25 : : * subsystem-specific way to find a device is not available: The component
26 : : * helper fills the niche of aggregate drivers for specific hardware, where
27 : : * further standardization into a subsystem would not be practical. The common
28 : : * example is when a logical device (e.g. a DRM display driver) is spread around
29 : : * the SoC on various components (scanout engines, blending blocks, transcoders
30 : : * for various outputs and so on).
31 : : *
32 : : * The component helper also doesn't solve runtime dependencies, e.g. for system
33 : : * suspend and resume operations. See also :ref:`device links<device_link>`.
34 : : *
35 : : * Components are registered using component_add() and unregistered with
36 : : * component_del(), usually from the driver's probe and disconnect functions.
37 : : *
38 : : * Aggregate drivers first assemble a component match list of what they need
39 : : * using component_match_add(). This is then registered as an aggregate driver
40 : : * using component_master_add_with_match(), and unregistered using
41 : : * component_master_del().
42 : : */
43 : :
44 : : struct component;
45 : :
46 : : struct component_match_array {
47 : : void *data;
48 : : int (*compare)(struct device *, void *);
49 : : int (*compare_typed)(struct device *, int, void *);
50 : : void (*release)(struct device *, void *);
51 : : struct component *component;
52 : : bool duplicate;
53 : : };
54 : :
55 : : struct component_match {
56 : : size_t alloc;
57 : : size_t num;
58 : : struct component_match_array *compare;
59 : : };
60 : :
61 : : struct master {
62 : : struct list_head node;
63 : : bool bound;
64 : :
65 : : const struct component_master_ops *ops;
66 : : struct device *dev;
67 : : struct component_match *match;
68 : : struct dentry *dentry;
69 : : };
70 : :
71 : : struct component {
72 : : struct list_head node;
73 : : struct master *master;
74 : : bool bound;
75 : :
76 : : const struct component_ops *ops;
77 : : int subcomponent;
78 : : struct device *dev;
79 : : };
80 : :
81 : : static DEFINE_MUTEX(component_mutex);
82 : : static LIST_HEAD(component_list);
83 : : static LIST_HEAD(masters);
84 : :
85 : : #ifdef CONFIG_DEBUG_FS
86 : :
87 : : static struct dentry *component_debugfs_dir;
88 : :
89 : 0 : static int component_devices_show(struct seq_file *s, void *data)
90 : : {
91 : 0 : struct master *m = s->private;
92 : 0 : struct component_match *match = m->match;
93 : 0 : size_t i;
94 : :
95 : 0 : mutex_lock(&component_mutex);
96 : 0 : seq_printf(s, "%-40s %20s\n", "master name", "status");
97 : 0 : seq_puts(s, "-------------------------------------------------------------\n");
98 : 0 : seq_printf(s, "%-40s %20s\n\n",
99 [ # # # # ]: 0 : dev_name(m->dev), m->bound ? "bound" : "not bound");
100 : :
101 : 0 : seq_printf(s, "%-40s %20s\n", "device name", "status");
102 : 0 : seq_puts(s, "-------------------------------------------------------------\n");
103 [ # # ]: 0 : for (i = 0; i < match->num; i++) {
104 : 0 : struct component *component = match->compare[i].component;
105 : :
106 [ # # # # ]: 0 : seq_printf(s, "%-40s %20s\n",
107 [ # # ]: 0 : component ? dev_name(component->dev) : "(unknown)",
108 [ # # ]: 0 : component ? (component->bound ? "bound" : "not bound") : "not registered");
109 : : }
110 : 0 : mutex_unlock(&component_mutex);
111 : :
112 : 0 : return 0;
113 : : }
114 : :
115 : 0 : DEFINE_SHOW_ATTRIBUTE(component_devices);
116 : :
117 : 11 : static int __init component_debug_init(void)
118 : : {
119 : 11 : component_debugfs_dir = debugfs_create_dir("device_component", NULL);
120 : :
121 : 11 : return 0;
122 : : }
123 : :
124 : : core_initcall(component_debug_init);
125 : :
126 : 0 : static void component_master_debugfs_add(struct master *m)
127 : : {
128 [ # # ]: 0 : m->dentry = debugfs_create_file(dev_name(m->dev), 0444,
129 : : component_debugfs_dir,
130 : : m, &component_devices_fops);
131 : 0 : }
132 : :
133 : 0 : static void component_master_debugfs_del(struct master *m)
134 : : {
135 : 0 : debugfs_remove(m->dentry);
136 : 0 : m->dentry = NULL;
137 : : }
138 : :
139 : : #else
140 : :
141 : : static void component_master_debugfs_add(struct master *m)
142 : : { }
143 : :
144 : : static void component_master_debugfs_del(struct master *m)
145 : : { }
146 : :
147 : : #endif
148 : :
149 : 0 : static struct master *__master_find(struct device *dev,
150 : : const struct component_master_ops *ops)
151 : : {
152 : 0 : struct master *m;
153 : :
154 [ # # # # : 0 : list_for_each_entry(m, &masters, node)
# # ]
155 [ # # # # : 0 : if (m->dev == dev && (!ops || m->ops == ops))
# # # # #
# ]
156 : : return m;
157 : :
158 : : return NULL;
159 : : }
160 : :
161 : 0 : static struct component *find_component(struct master *master,
162 : : struct component_match_array *mc)
163 : : {
164 : 0 : struct component *c;
165 : :
166 [ # # ]: 0 : list_for_each_entry(c, &component_list, node) {
167 [ # # # # ]: 0 : if (c->master && c->master != master)
168 : 0 : continue;
169 : :
170 [ # # # # ]: 0 : if (mc->compare && mc->compare(c->dev, mc->data))
171 : 0 : return c;
172 : :
173 [ # # # # ]: 0 : if (mc->compare_typed &&
174 : 0 : mc->compare_typed(c->dev, c->subcomponent, mc->data))
175 : 0 : return c;
176 : : }
177 : :
178 : : return NULL;
179 : : }
180 : :
181 : 0 : static int find_components(struct master *master)
182 : : {
183 : 0 : struct component_match *match = master->match;
184 : 0 : size_t i;
185 : 0 : int ret = 0;
186 : :
187 : : /*
188 : : * Scan the array of match functions and attach
189 : : * any components which are found to this master.
190 : : */
191 [ # # ]: 0 : for (i = 0; i < match->num; i++) {
192 : 0 : struct component_match_array *mc = &match->compare[i];
193 : 0 : struct component *c;
194 : :
195 : 0 : dev_dbg(master->dev, "Looking for component %zu\n", i);
196 : :
197 [ # # ]: 0 : if (match->compare[i].component)
198 : 0 : continue;
199 : :
200 : 0 : c = find_component(master, mc);
201 [ # # ]: 0 : if (!c) {
202 : : ret = -ENXIO;
203 : : break;
204 : : }
205 : :
206 : 0 : dev_dbg(master->dev, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
207 : :
208 : : /* Attach this component to the master */
209 : 0 : match->compare[i].duplicate = !!c->master;
210 : 0 : match->compare[i].component = c;
211 : 0 : c->master = master;
212 : : }
213 : 0 : return ret;
214 : : }
215 : :
216 : : /* Detach component from associated master */
217 : 0 : static void remove_component(struct master *master, struct component *c)
218 : : {
219 : : size_t i;
220 : :
221 : : /* Detach the component from this master. */
222 [ # # # # ]: 0 : for (i = 0; i < master->match->num; i++)
223 [ # # # # ]: 0 : if (master->match->compare[i].component == c)
224 : 0 : master->match->compare[i].component = NULL;
225 : : }
226 : :
227 : : /*
228 : : * Try to bring up a master. If component is NULL, we're interested in
229 : : * this master, otherwise it's a component which must be present to try
230 : : * and bring up the master.
231 : : *
232 : : * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
233 : : */
234 : 0 : static int try_to_bring_up_master(struct master *master,
235 : : struct component *component)
236 : : {
237 : 0 : int ret;
238 : :
239 : 0 : dev_dbg(master->dev, "trying to bring up master\n");
240 : :
241 [ # # ]: 0 : if (find_components(master)) {
242 : : dev_dbg(master->dev, "master has incomplete components\n");
243 : : return 0;
244 : : }
245 : :
246 [ # # # # ]: 0 : if (component && component->master != master) {
247 : : dev_dbg(master->dev, "master is not for this component (%s)\n",
248 : : dev_name(component->dev));
249 : : return 0;
250 : : }
251 : :
252 [ # # ]: 0 : if (!devres_open_group(master->dev, NULL, GFP_KERNEL))
253 : : return -ENOMEM;
254 : :
255 : : /* Found all components */
256 : 0 : ret = master->ops->bind(master->dev);
257 [ # # ]: 0 : if (ret < 0) {
258 : 0 : devres_release_group(master->dev, NULL);
259 : 0 : dev_info(master->dev, "master bind failed: %d\n", ret);
260 : 0 : return ret;
261 : : }
262 : :
263 : 0 : master->bound = true;
264 : 0 : return 1;
265 : : }
266 : :
267 : 0 : static int try_to_bring_up_masters(struct component *component)
268 : : {
269 : 0 : struct master *m;
270 : 0 : int ret = 0;
271 : :
272 [ # # ]: 0 : list_for_each_entry(m, &masters, node) {
273 [ # # ]: 0 : if (!m->bound) {
274 : 0 : ret = try_to_bring_up_master(m, component);
275 [ # # ]: 0 : if (ret != 0)
276 : : break;
277 : : }
278 : : }
279 : :
280 : 0 : return ret;
281 : : }
282 : :
283 : 0 : static void take_down_master(struct master *master)
284 : : {
285 [ # # ]: 0 : if (master->bound) {
286 : 0 : master->ops->unbind(master->dev);
287 : 0 : devres_release_group(master->dev, NULL);
288 : 0 : master->bound = false;
289 : : }
290 : 0 : }
291 : :
292 : : static void component_match_release(struct device *master,
293 : : struct component_match *match)
294 : : {
295 : : unsigned int i;
296 : :
297 : : for (i = 0; i < match->num; i++) {
298 : : struct component_match_array *mc = &match->compare[i];
299 : :
300 : : if (mc->release)
301 : : mc->release(master, mc->data);
302 : : }
303 : :
304 : : kfree(match->compare);
305 : : }
306 : :
307 : 0 : static void devm_component_match_release(struct device *dev, void *res)
308 : : {
309 : 0 : component_match_release(dev, res);
310 : 0 : }
311 : :
312 : : static int component_match_realloc(struct device *dev,
313 : : struct component_match *match, size_t num)
314 : : {
315 : : struct component_match_array *new;
316 : :
317 : : if (match->alloc == num)
318 : : return 0;
319 : :
320 : : new = kmalloc_array(num, sizeof(*new), GFP_KERNEL);
321 : : if (!new)
322 : : return -ENOMEM;
323 : :
324 : : if (match->compare) {
325 : : memcpy(new, match->compare, sizeof(*new) *
326 : : min(match->num, num));
327 : : kfree(match->compare);
328 : : }
329 : : match->compare = new;
330 : : match->alloc = num;
331 : :
332 : : return 0;
333 : : }
334 : :
335 : 0 : static void __component_match_add(struct device *master,
336 : : struct component_match **matchptr,
337 : : void (*release)(struct device *, void *),
338 : : int (*compare)(struct device *, void *),
339 : : int (*compare_typed)(struct device *, int, void *),
340 : : void *compare_data)
341 : : {
342 : 0 : struct component_match *match = *matchptr;
343 : :
344 [ # # ]: 0 : if (IS_ERR(match))
345 : : return;
346 : :
347 [ # # ]: 0 : if (!match) {
348 : 0 : match = devres_alloc(devm_component_match_release,
349 : : sizeof(*match), GFP_KERNEL);
350 [ # # ]: 0 : if (!match) {
351 : 0 : *matchptr = ERR_PTR(-ENOMEM);
352 : 0 : return;
353 : : }
354 : :
355 : 0 : devres_add(master, match);
356 : :
357 : 0 : *matchptr = match;
358 : : }
359 : :
360 [ # # ]: 0 : if (match->num == match->alloc) {
361 : 0 : size_t new_size = match->alloc + 16;
362 : 0 : int ret;
363 : :
364 : 0 : ret = component_match_realloc(master, match, new_size);
365 [ # # ]: 0 : if (ret) {
366 : 0 : *matchptr = ERR_PTR(ret);
367 : 0 : return;
368 : : }
369 : : }
370 : :
371 : 0 : match->compare[match->num].compare = compare;
372 : 0 : match->compare[match->num].compare_typed = compare_typed;
373 : 0 : match->compare[match->num].release = release;
374 : 0 : match->compare[match->num].data = compare_data;
375 : 0 : match->compare[match->num].component = NULL;
376 : 0 : match->num++;
377 : : }
378 : :
379 : : /**
380 : : * component_match_add_release - add a component match entry with release callback
381 : : * @master: device with the aggregate driver
382 : : * @matchptr: pointer to the list of component matches
383 : : * @release: release function for @compare_data
384 : : * @compare: compare function to match against all components
385 : : * @compare_data: opaque pointer passed to the @compare function
386 : : *
387 : : * Adds a new component match to the list stored in @matchptr, which the @master
388 : : * aggregate driver needs to function. The list of component matches pointed to
389 : : * by @matchptr must be initialized to NULL before adding the first match. This
390 : : * only matches against components added with component_add().
391 : : *
392 : : * The allocated match list in @matchptr is automatically released using devm
393 : : * actions, where upon @release will be called to free any references held by
394 : : * @compare_data, e.g. when @compare_data is a &device_node that must be
395 : : * released with of_node_put().
396 : : *
397 : : * See also component_match_add() and component_match_add_typed().
398 : : */
399 : 0 : void component_match_add_release(struct device *master,
400 : : struct component_match **matchptr,
401 : : void (*release)(struct device *, void *),
402 : : int (*compare)(struct device *, void *), void *compare_data)
403 : : {
404 : 0 : __component_match_add(master, matchptr, release, compare, NULL,
405 : : compare_data);
406 : 0 : }
407 : : EXPORT_SYMBOL(component_match_add_release);
408 : :
409 : : /**
410 : : * component_match_add_typed - add a component match entry for a typed component
411 : : * @master: device with the aggregate driver
412 : : * @matchptr: pointer to the list of component matches
413 : : * @compare_typed: compare function to match against all typed components
414 : : * @compare_data: opaque pointer passed to the @compare function
415 : : *
416 : : * Adds a new component match to the list stored in @matchptr, which the @master
417 : : * aggregate driver needs to function. The list of component matches pointed to
418 : : * by @matchptr must be initialized to NULL before adding the first match. This
419 : : * only matches against components added with component_add_typed().
420 : : *
421 : : * The allocated match list in @matchptr is automatically released using devm
422 : : * actions.
423 : : *
424 : : * See also component_match_add_release() and component_match_add_typed().
425 : : */
426 : 0 : void component_match_add_typed(struct device *master,
427 : : struct component_match **matchptr,
428 : : int (*compare_typed)(struct device *, int, void *), void *compare_data)
429 : : {
430 : 0 : __component_match_add(master, matchptr, NULL, NULL, compare_typed,
431 : : compare_data);
432 : 0 : }
433 : : EXPORT_SYMBOL(component_match_add_typed);
434 : :
435 : 0 : static void free_master(struct master *master)
436 : : {
437 : 0 : struct component_match *match = master->match;
438 : 0 : int i;
439 : :
440 : 0 : component_master_debugfs_del(master);
441 [ # # ]: 0 : list_del(&master->node);
442 : :
443 [ # # ]: 0 : if (match) {
444 [ # # ]: 0 : for (i = 0; i < match->num; i++) {
445 : 0 : struct component *c = match->compare[i].component;
446 [ # # ]: 0 : if (c)
447 : 0 : c->master = NULL;
448 : : }
449 : : }
450 : :
451 : 0 : kfree(master);
452 : 0 : }
453 : :
454 : : /**
455 : : * component_master_add_with_match - register an aggregate driver
456 : : * @dev: device with the aggregate driver
457 : : * @ops: callbacks for the aggregate driver
458 : : * @match: component match list for the aggregate driver
459 : : *
460 : : * Registers a new aggregate driver consisting of the components added to @match
461 : : * by calling one of the component_match_add() functions. Once all components in
462 : : * @match are available, it will be assembled by calling
463 : : * &component_master_ops.bind from @ops. Must be unregistered by calling
464 : : * component_master_del().
465 : : */
466 : 0 : int component_master_add_with_match(struct device *dev,
467 : : const struct component_master_ops *ops,
468 : : struct component_match *match)
469 : : {
470 : 0 : struct master *master;
471 : 0 : int ret;
472 : :
473 : : /* Reallocate the match array for its true size */
474 : 0 : ret = component_match_realloc(dev, match, match->num);
475 [ # # ]: 0 : if (ret)
476 : : return ret;
477 : :
478 : 0 : master = kzalloc(sizeof(*master), GFP_KERNEL);
479 [ # # ]: 0 : if (!master)
480 : : return -ENOMEM;
481 : :
482 : 0 : master->dev = dev;
483 : 0 : master->ops = ops;
484 : 0 : master->match = match;
485 : :
486 : 0 : component_master_debugfs_add(master);
487 : : /* Add to the list of available masters. */
488 : 0 : mutex_lock(&component_mutex);
489 : 0 : list_add(&master->node, &masters);
490 : :
491 : 0 : ret = try_to_bring_up_master(master, NULL);
492 : :
493 [ # # ]: 0 : if (ret < 0)
494 : 0 : free_master(master);
495 : :
496 : 0 : mutex_unlock(&component_mutex);
497 : :
498 : 0 : return ret < 0 ? ret : 0;
499 : : }
500 : : EXPORT_SYMBOL_GPL(component_master_add_with_match);
501 : :
502 : : /**
503 : : * component_master_del - unregister an aggregate driver
504 : : * @dev: device with the aggregate driver
505 : : * @ops: callbacks for the aggregate driver
506 : : *
507 : : * Unregisters an aggregate driver registered with
508 : : * component_master_add_with_match(). If necessary the aggregate driver is first
509 : : * disassembled by calling &component_master_ops.unbind from @ops.
510 : : */
511 : 0 : void component_master_del(struct device *dev,
512 : : const struct component_master_ops *ops)
513 : : {
514 : 0 : struct master *master;
515 : :
516 : 0 : mutex_lock(&component_mutex);
517 : 0 : master = __master_find(dev, ops);
518 [ # # ]: 0 : if (master) {
519 : 0 : take_down_master(master);
520 : 0 : free_master(master);
521 : : }
522 : 0 : mutex_unlock(&component_mutex);
523 : 0 : }
524 : : EXPORT_SYMBOL_GPL(component_master_del);
525 : :
526 : : static void component_unbind(struct component *component,
527 : : struct master *master, void *data)
528 : : {
529 : : WARN_ON(!component->bound);
530 : :
531 : : component->ops->unbind(component->dev, master->dev, data);
532 : : component->bound = false;
533 : :
534 : : /* Release all resources claimed in the binding of this component */
535 : : devres_release_group(component->dev, component);
536 : : }
537 : :
538 : : /**
539 : : * component_unbind_all - unbind all components of an aggregate driver
540 : : * @master_dev: device with the aggregate driver
541 : : * @data: opaque pointer, passed to all components
542 : : *
543 : : * Unbinds all components of the aggregate @dev by passing @data to their
544 : : * &component_ops.unbind functions. Should be called from
545 : : * &component_master_ops.unbind.
546 : : */
547 : 0 : void component_unbind_all(struct device *master_dev, void *data)
548 : : {
549 : 0 : struct master *master;
550 : 0 : struct component *c;
551 : 0 : size_t i;
552 : :
553 [ # # ]: 0 : WARN_ON(!mutex_is_locked(&component_mutex));
554 : :
555 : 0 : master = __master_find(master_dev, NULL);
556 [ # # ]: 0 : if (!master)
557 : : return;
558 : :
559 : : /* Unbind components in reverse order */
560 [ # # ]: 0 : for (i = master->match->num; i--; )
561 [ # # ]: 0 : if (!master->match->compare[i].duplicate) {
562 : 0 : c = master->match->compare[i].component;
563 : 0 : component_unbind(c, master, data);
564 : : }
565 : : }
566 : : EXPORT_SYMBOL_GPL(component_unbind_all);
567 : :
568 : : static int component_bind(struct component *component, struct master *master,
569 : : void *data)
570 : : {
571 : : int ret;
572 : :
573 : : /*
574 : : * Each component initialises inside its own devres group.
575 : : * This allows us to roll-back a failed component without
576 : : * affecting anything else.
577 : : */
578 : : if (!devres_open_group(master->dev, NULL, GFP_KERNEL))
579 : : return -ENOMEM;
580 : :
581 : : /*
582 : : * Also open a group for the device itself: this allows us
583 : : * to release the resources claimed against the sub-device
584 : : * at the appropriate moment.
585 : : */
586 : : if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
587 : : devres_release_group(master->dev, NULL);
588 : : return -ENOMEM;
589 : : }
590 : :
591 : : dev_dbg(master->dev, "binding %s (ops %ps)\n",
592 : : dev_name(component->dev), component->ops);
593 : :
594 : : ret = component->ops->bind(component->dev, master->dev, data);
595 : : if (!ret) {
596 : : component->bound = true;
597 : :
598 : : /*
599 : : * Close the component device's group so that resources
600 : : * allocated in the binding are encapsulated for removal
601 : : * at unbind. Remove the group on the DRM device as we
602 : : * can clean those resources up independently.
603 : : */
604 : : devres_close_group(component->dev, NULL);
605 : : devres_remove_group(master->dev, NULL);
606 : :
607 : : dev_info(master->dev, "bound %s (ops %ps)\n",
608 : : dev_name(component->dev), component->ops);
609 : : } else {
610 : : devres_release_group(component->dev, NULL);
611 : : devres_release_group(master->dev, NULL);
612 : :
613 : : dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
614 : : dev_name(component->dev), component->ops, ret);
615 : : }
616 : :
617 : : return ret;
618 : : }
619 : :
620 : : /**
621 : : * component_bind_all - bind all components of an aggregate driver
622 : : * @master_dev: device with the aggregate driver
623 : : * @data: opaque pointer, passed to all components
624 : : *
625 : : * Binds all components of the aggregate @dev by passing @data to their
626 : : * &component_ops.bind functions. Should be called from
627 : : * &component_master_ops.bind.
628 : : */
629 : 0 : int component_bind_all(struct device *master_dev, void *data)
630 : : {
631 : 0 : struct master *master;
632 : 0 : struct component *c;
633 : 0 : size_t i;
634 : 0 : int ret = 0;
635 : :
636 [ # # ]: 0 : WARN_ON(!mutex_is_locked(&component_mutex));
637 : :
638 : 0 : master = __master_find(master_dev, NULL);
639 [ # # ]: 0 : if (!master)
640 : : return -EINVAL;
641 : :
642 : : /* Bind components in match order */
643 [ # # ]: 0 : for (i = 0; i < master->match->num; i++)
644 [ # # ]: 0 : if (!master->match->compare[i].duplicate) {
645 : 0 : c = master->match->compare[i].component;
646 : 0 : ret = component_bind(c, master, data);
647 [ # # ]: 0 : if (ret)
648 : : break;
649 : : }
650 : :
651 [ # # ]: 0 : if (ret != 0) {
652 [ # # ]: 0 : for (; i > 0; i--)
653 [ # # ]: 0 : if (!master->match->compare[i - 1].duplicate) {
654 : 0 : c = master->match->compare[i - 1].component;
655 : 0 : component_unbind(c, master, data);
656 : : }
657 : : }
658 : :
659 : : return ret;
660 : : }
661 : : EXPORT_SYMBOL_GPL(component_bind_all);
662 : :
663 : 0 : static int __component_add(struct device *dev, const struct component_ops *ops,
664 : : int subcomponent)
665 : : {
666 : 0 : struct component *component;
667 : 0 : int ret;
668 : :
669 : 0 : component = kzalloc(sizeof(*component), GFP_KERNEL);
670 [ # # ]: 0 : if (!component)
671 : : return -ENOMEM;
672 : :
673 : 0 : component->ops = ops;
674 : 0 : component->dev = dev;
675 : 0 : component->subcomponent = subcomponent;
676 : :
677 : 0 : dev_dbg(dev, "adding component (ops %ps)\n", ops);
678 : :
679 : 0 : mutex_lock(&component_mutex);
680 : 0 : list_add_tail(&component->node, &component_list);
681 : :
682 : 0 : ret = try_to_bring_up_masters(component);
683 [ # # ]: 0 : if (ret < 0) {
684 [ # # ]: 0 : if (component->master)
685 : : remove_component(component->master, component);
686 : 0 : list_del(&component->node);
687 : :
688 : 0 : kfree(component);
689 : : }
690 : 0 : mutex_unlock(&component_mutex);
691 : :
692 : 0 : return ret < 0 ? ret : 0;
693 : : }
694 : :
695 : : /**
696 : : * component_add_typed - register a component
697 : : * @dev: component device
698 : : * @ops: component callbacks
699 : : * @subcomponent: nonzero identifier for subcomponents
700 : : *
701 : : * Register a new component for @dev. Functions in @ops will be call when the
702 : : * aggregate driver is ready to bind the overall driver by calling
703 : : * component_bind_all(). See also &struct component_ops.
704 : : *
705 : : * @subcomponent must be nonzero and is used to differentiate between multiple
706 : : * components registerd on the same device @dev. These components are match
707 : : * using component_match_add_typed().
708 : : *
709 : : * The component needs to be unregistered at driver unload/disconnect by
710 : : * calling component_del().
711 : : *
712 : : * See also component_add().
713 : : */
714 : 0 : int component_add_typed(struct device *dev, const struct component_ops *ops,
715 : : int subcomponent)
716 : : {
717 [ # # # # ]: 0 : if (WARN_ON(subcomponent == 0))
718 : : return -EINVAL;
719 : :
720 : 0 : return __component_add(dev, ops, subcomponent);
721 : : }
722 : : EXPORT_SYMBOL_GPL(component_add_typed);
723 : :
724 : : /**
725 : : * component_add - register a component
726 : : * @dev: component device
727 : : * @ops: component callbacks
728 : : *
729 : : * Register a new component for @dev. Functions in @ops will be called when the
730 : : * aggregate driver is ready to bind the overall driver by calling
731 : : * component_bind_all(). See also &struct component_ops.
732 : : *
733 : : * The component needs to be unregistered at driver unload/disconnect by
734 : : * calling component_del().
735 : : *
736 : : * See also component_add_typed() for a variant that allows multipled different
737 : : * components on the same device.
738 : : */
739 : 0 : int component_add(struct device *dev, const struct component_ops *ops)
740 : : {
741 : 0 : return __component_add(dev, ops, 0);
742 : : }
743 : : EXPORT_SYMBOL_GPL(component_add);
744 : :
745 : : /**
746 : : * component_del - unregister a component
747 : : * @dev: component device
748 : : * @ops: component callbacks
749 : : *
750 : : * Unregister a component added with component_add(). If the component is bound
751 : : * into an aggregate driver, this will force the entire aggregate driver, including
752 : : * all its components, to be unbound.
753 : : */
754 : 0 : void component_del(struct device *dev, const struct component_ops *ops)
755 : : {
756 : 0 : struct component *c, *component = NULL;
757 : :
758 : 0 : mutex_lock(&component_mutex);
759 [ # # ]: 0 : list_for_each_entry(c, &component_list, node)
760 [ # # # # ]: 0 : if (c->dev == dev && c->ops == ops) {
761 : 0 : list_del(&c->node);
762 : 0 : component = c;
763 : 0 : break;
764 : : }
765 : :
766 [ # # # # ]: 0 : if (component && component->master) {
767 : 0 : take_down_master(component->master);
768 : 0 : remove_component(component->master, component);
769 : : }
770 : :
771 : 0 : mutex_unlock(&component_mutex);
772 : :
773 [ # # ]: 0 : WARN_ON(!component);
774 : 0 : kfree(component);
775 : 0 : }
776 : : EXPORT_SYMBOL_GPL(component_del);
|