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