diff options
Diffstat (limited to 'drivers/base/component.c')
-rw-r--r-- | drivers/base/component.c | 158 |
1 files changed, 121 insertions, 37 deletions
diff --git a/drivers/base/component.c b/drivers/base/component.c index 1624c2a892a5..7dbc41cccd58 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c | |||
@@ -47,6 +47,7 @@ struct component; | |||
47 | struct component_match_array { | 47 | struct component_match_array { |
48 | void *data; | 48 | void *data; |
49 | int (*compare)(struct device *, void *); | 49 | int (*compare)(struct device *, void *); |
50 | int (*compare_typed)(struct device *, int, void *); | ||
50 | void (*release)(struct device *, void *); | 51 | void (*release)(struct device *, void *); |
51 | struct component *component; | 52 | struct component *component; |
52 | bool duplicate; | 53 | bool duplicate; |
@@ -74,6 +75,7 @@ struct component { | |||
74 | bool bound; | 75 | bool bound; |
75 | 76 | ||
76 | const struct component_ops *ops; | 77 | const struct component_ops *ops; |
78 | int subcomponent; | ||
77 | struct device *dev; | 79 | struct device *dev; |
78 | }; | 80 | }; |
79 | 81 | ||
@@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev, | |||
158 | } | 160 | } |
159 | 161 | ||
160 | static struct component *find_component(struct master *master, | 162 | static struct component *find_component(struct master *master, |
161 | int (*compare)(struct device *, void *), void *compare_data) | 163 | struct component_match_array *mc) |
162 | { | 164 | { |
163 | struct component *c; | 165 | struct component *c; |
164 | 166 | ||
@@ -166,7 +168,11 @@ static struct component *find_component(struct master *master, | |||
166 | if (c->master && c->master != master) | 168 | if (c->master && c->master != master) |
167 | continue; | 169 | continue; |
168 | 170 | ||
169 | if (compare(c->dev, compare_data)) | 171 | if (mc->compare && mc->compare(c->dev, mc->data)) |
172 | return c; | ||
173 | |||
174 | if (mc->compare_typed && | ||
175 | mc->compare_typed(c->dev, c->subcomponent, mc->data)) | ||
170 | return c; | 176 | return c; |
171 | } | 177 | } |
172 | 178 | ||
@@ -192,7 +198,7 @@ static int find_components(struct master *master) | |||
192 | if (match->compare[i].component) | 198 | if (match->compare[i].component) |
193 | continue; | 199 | continue; |
194 | 200 | ||
195 | c = find_component(master, mc->compare, mc->data); | 201 | c = find_component(master, mc); |
196 | if (!c) { | 202 | if (!c) { |
197 | ret = -ENXIO; | 203 | ret = -ENXIO; |
198 | break; | 204 | break; |
@@ -327,29 +333,12 @@ static int component_match_realloc(struct device *dev, | |||
327 | return 0; | 333 | return 0; |
328 | } | 334 | } |
329 | 335 | ||
330 | /** | 336 | static void __component_match_add(struct device *master, |
331 | * component_match_add_release - add a component match with release callback | ||
332 | * @master: device with the aggregate driver | ||
333 | * @matchptr: pointer to the list of component matches | ||
334 | * @release: release function for @compare_data | ||
335 | * @compare: compare function to match against all components | ||
336 | * @compare_data: opaque pointer passed to the @compare function | ||
337 | * | ||
338 | * Adds a new component match to the list stored in @matchptr, which the @master | ||
339 | * aggregate driver needs to function. The list of component matches pointed to | ||
340 | * by @matchptr must be initialized to NULL before adding the first match. | ||
341 | * | ||
342 | * The allocated match list in @matchptr is automatically released using devm | ||
343 | * actions, where upon @release will be called to free any references held by | ||
344 | * @compare_data, e.g. when @compare_data is a &device_node that must be | ||
345 | * released with of_node_put(). | ||
346 | * | ||
347 | * See also component_match_add(). | ||
348 | */ | ||
349 | void component_match_add_release(struct device *master, | ||
350 | struct component_match **matchptr, | 337 | struct component_match **matchptr, |
351 | void (*release)(struct device *, void *), | 338 | void (*release)(struct device *, void *), |
352 | int (*compare)(struct device *, void *), void *compare_data) | 339 | int (*compare)(struct device *, void *), |
340 | int (*compare_typed)(struct device *, int, void *), | ||
341 | void *compare_data) | ||
353 | { | 342 | { |
354 | struct component_match *match = *matchptr; | 343 | struct component_match *match = *matchptr; |
355 | 344 | ||
@@ -381,13 +370,69 @@ void component_match_add_release(struct device *master, | |||
381 | } | 370 | } |
382 | 371 | ||
383 | match->compare[match->num].compare = compare; | 372 | match->compare[match->num].compare = compare; |
373 | match->compare[match->num].compare_typed = compare_typed; | ||
384 | match->compare[match->num].release = release; | 374 | match->compare[match->num].release = release; |
385 | match->compare[match->num].data = compare_data; | 375 | match->compare[match->num].data = compare_data; |
386 | match->compare[match->num].component = NULL; | 376 | match->compare[match->num].component = NULL; |
387 | match->num++; | 377 | match->num++; |
388 | } | 378 | } |
379 | |||
380 | /** | ||
381 | * component_match_add_release - add a component match with release callback | ||
382 | * @master: device with the aggregate driver | ||
383 | * @matchptr: pointer to the list of component matches | ||
384 | * @release: release function for @compare_data | ||
385 | * @compare: compare function to match against all components | ||
386 | * @compare_data: opaque pointer passed to the @compare function | ||
387 | * | ||
388 | * Adds a new component match to the list stored in @matchptr, which the @master | ||
389 | * aggregate driver needs to function. The list of component matches pointed to | ||
390 | * by @matchptr must be initialized to NULL before adding the first match. This | ||
391 | * only matches against components added with component_add(). | ||
392 | * | ||
393 | * The allocated match list in @matchptr is automatically released using devm | ||
394 | * actions, where upon @release will be called to free any references held by | ||
395 | * @compare_data, e.g. when @compare_data is a &device_node that must be | ||
396 | * released with of_node_put(). | ||
397 | * | ||
398 | * See also component_match_add() and component_match_add_typed(). | ||
399 | */ | ||
400 | void component_match_add_release(struct device *master, | ||
401 | struct component_match **matchptr, | ||
402 | void (*release)(struct device *, void *), | ||
403 | int (*compare)(struct device *, void *), void *compare_data) | ||
404 | { | ||
405 | __component_match_add(master, matchptr, release, compare, NULL, | ||
406 | compare_data); | ||
407 | } | ||
389 | EXPORT_SYMBOL(component_match_add_release); | 408 | EXPORT_SYMBOL(component_match_add_release); |
390 | 409 | ||
410 | /** | ||
411 | * component_match_add_typed - add a compent match for a typed component | ||
412 | * @master: device with the aggregate driver | ||
413 | * @matchptr: pointer to the list of component matches | ||
414 | * @compare_typed: compare function to match against all typed components | ||
415 | * @compare_data: opaque pointer passed to the @compare function | ||
416 | * | ||
417 | * Adds a new component match to the list stored in @matchptr, which the @master | ||
418 | * aggregate driver needs to function. The list of component matches pointed to | ||
419 | * by @matchptr must be initialized to NULL before adding the first match. This | ||
420 | * only matches against components added with component_add_typed(). | ||
421 | * | ||
422 | * The allocated match list in @matchptr is automatically released using devm | ||
423 | * actions. | ||
424 | * | ||
425 | * See also component_match_add_release() and component_match_add_typed(). | ||
426 | */ | ||
427 | void component_match_add_typed(struct device *master, | ||
428 | struct component_match **matchptr, | ||
429 | int (*compare_typed)(struct device *, int, void *), void *compare_data) | ||
430 | { | ||
431 | __component_match_add(master, matchptr, NULL, NULL, compare_typed, | ||
432 | compare_data); | ||
433 | } | ||
434 | EXPORT_SYMBOL(component_match_add_typed); | ||
435 | |||
391 | static void free_master(struct master *master) | 436 | static void free_master(struct master *master) |
392 | { | 437 | { |
393 | struct component_match *match = master->match; | 438 | struct component_match *match = master->match; |
@@ -616,19 +661,8 @@ int component_bind_all(struct device *master_dev, void *data) | |||
616 | } | 661 | } |
617 | EXPORT_SYMBOL_GPL(component_bind_all); | 662 | EXPORT_SYMBOL_GPL(component_bind_all); |
618 | 663 | ||
619 | /** | 664 | static int __component_add(struct device *dev, const struct component_ops *ops, |
620 | * component_add - register a component | 665 | int subcomponent) |
621 | * @dev: component device | ||
622 | * @ops: component callbacks | ||
623 | * | ||
624 | * Register a new component for @dev. Functions in @ops will be called when the | ||
625 | * aggregate driver is ready to bind the overall driver by calling | ||
626 | * component_bind_all(). See also &struct component_ops. | ||
627 | * | ||
628 | * The component needs to be unregistered at driver unload/disconnect by calling | ||
629 | * component_del(). | ||
630 | */ | ||
631 | int component_add(struct device *dev, const struct component_ops *ops) | ||
632 | { | 666 | { |
633 | struct component *component; | 667 | struct component *component; |
634 | int ret; | 668 | int ret; |
@@ -639,6 +673,7 @@ int component_add(struct device *dev, const struct component_ops *ops) | |||
639 | 673 | ||
640 | component->ops = ops; | 674 | component->ops = ops; |
641 | component->dev = dev; | 675 | component->dev = dev; |
676 | component->subcomponent = subcomponent; | ||
642 | 677 | ||
643 | dev_dbg(dev, "adding component (ops %ps)\n", ops); | 678 | dev_dbg(dev, "adding component (ops %ps)\n", ops); |
644 | 679 | ||
@@ -657,6 +692,55 @@ int component_add(struct device *dev, const struct component_ops *ops) | |||
657 | 692 | ||
658 | return ret < 0 ? ret : 0; | 693 | return ret < 0 ? ret : 0; |
659 | } | 694 | } |
695 | |||
696 | /** | ||
697 | * component_add_typed - register a component | ||
698 | * @dev: component device | ||
699 | * @ops: component callbacks | ||
700 | * @subcomponent: nonzero identifier for subcomponents | ||
701 | * | ||
702 | * Register a new component for @dev. Functions in @ops will be call when the | ||
703 | * aggregate driver is ready to bind the overall driver by calling | ||
704 | * component_bind_all(). See also &struct component_ops. | ||
705 | * | ||
706 | * @subcomponent must be nonzero and is used to differentiate between multiple | ||
707 | * components registerd on the same device @dev. These components are match | ||
708 | * using component_match_add_typed(). | ||
709 | * | ||
710 | * The component needs to be unregistered at driver unload/disconnect by | ||
711 | * calling component_del(). | ||
712 | * | ||
713 | * See also component_add(). | ||
714 | */ | ||
715 | int component_add_typed(struct device *dev, const struct component_ops *ops, | ||
716 | int subcomponent) | ||
717 | { | ||
718 | if (WARN_ON(subcomponent == 0)) | ||
719 | return -EINVAL; | ||
720 | |||
721 | return __component_add(dev, ops, subcomponent); | ||
722 | } | ||
723 | EXPORT_SYMBOL_GPL(component_add_typed); | ||
724 | |||
725 | /** | ||
726 | * component_add - register a component | ||
727 | * @dev: component device | ||
728 | * @ops: component callbacks | ||
729 | * | ||
730 | * Register a new component for @dev. Functions in @ops will be called when the | ||
731 | * aggregate driver is ready to bind the overall driver by calling | ||
732 | * component_bind_all(). See also &struct component_ops. | ||
733 | * | ||
734 | * The component needs to be unregistered at driver unload/disconnect by | ||
735 | * calling component_del(). | ||
736 | * | ||
737 | * See also component_add_typed() for a variant that allows multipled different | ||
738 | * components on the same device. | ||
739 | */ | ||
740 | int component_add(struct device *dev, const struct component_ops *ops) | ||
741 | { | ||
742 | return __component_add(dev, ops, 0); | ||
743 | } | ||
660 | EXPORT_SYMBOL_GPL(component_add); | 744 | EXPORT_SYMBOL_GPL(component_add); |
661 | 745 | ||
662 | /** | 746 | /** |