diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-15 07:24:02 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-15 07:24:02 -0500 |
commit | cecdb193c8d91a42d9489d00618cc3dfff92e55a (patch) | |
tree | 7d7e16d389efab64ff2c0799de50e0b19ab20077 /drivers/acpi/scan.c | |
parent | ae281795ec92d35dd1631401829124acab965b1f (diff) |
ACPI / scan: Change the implementation of acpi_bus_trim()
The current acpi_bus_trim() implementation is not really
straightforward and may be simplified significantly by using
acpi_walk_namespace() with acpi_bus_remove() as a post-order
callback.
Observe that acpi_bus_remove(), as called by acpi_bus_trim(), cannot
actually fail, because its first argument is guaranteed not to be
NULL thanks to the acpi_bus_get_device() check in acpi_bus_trim(),
so simply move the acpi_bus_get_device() check to acpi_bus_remove()
and use acpi_walk_namespace() to execute it for every device under
start->handle as a post-order callback. The, run it directly for
start->handle itself.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 64 |
1 files changed, 15 insertions, 49 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d14ce446b469..1ee62bd25828 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1374,17 +1374,20 @@ static int acpi_device_set_context(struct acpi_device *device) | |||
1374 | return -ENODEV; | 1374 | return -ENODEV; |
1375 | } | 1375 | } |
1376 | 1376 | ||
1377 | static int acpi_bus_remove(struct acpi_device *dev) | 1377 | static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, |
1378 | void *not_used, void **ret_not_used) | ||
1378 | { | 1379 | { |
1379 | if (!dev) | 1380 | struct acpi_device *dev = NULL; |
1380 | return -EINVAL; | 1381 | |
1382 | if (acpi_bus_get_device(handle, &dev)) | ||
1383 | return AE_OK; | ||
1381 | 1384 | ||
1382 | dev->removal_type = ACPI_BUS_REMOVAL_EJECT; | 1385 | dev->removal_type = ACPI_BUS_REMOVAL_EJECT; |
1383 | device_release_driver(&dev->dev); | 1386 | device_release_driver(&dev->dev); |
1384 | 1387 | ||
1385 | acpi_device_unregister(dev); | 1388 | acpi_device_unregister(dev); |
1386 | 1389 | ||
1387 | return 0; | 1390 | return AE_OK; |
1388 | } | 1391 | } |
1389 | 1392 | ||
1390 | static int acpi_add_single_object(struct acpi_device **child, | 1393 | static int acpi_add_single_object(struct acpi_device **child, |
@@ -1641,51 +1644,14 @@ EXPORT_SYMBOL(acpi_bus_add); | |||
1641 | 1644 | ||
1642 | int acpi_bus_trim(struct acpi_device *start) | 1645 | int acpi_bus_trim(struct acpi_device *start) |
1643 | { | 1646 | { |
1644 | acpi_status status; | 1647 | /* |
1645 | struct acpi_device *parent, *child; | 1648 | * Execute acpi_bus_remove() as a post-order callback to remove device |
1646 | acpi_handle phandle, chandle; | 1649 | * nodes in the given namespace scope. |
1647 | acpi_object_type type; | 1650 | */ |
1648 | u32 level = 1; | 1651 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, |
1649 | int err = 0; | 1652 | acpi_bus_remove, NULL, NULL); |
1650 | 1653 | acpi_bus_remove(start->handle, 0, NULL, NULL); | |
1651 | parent = start; | 1654 | return 0; |
1652 | phandle = start->handle; | ||
1653 | child = chandle = NULL; | ||
1654 | |||
1655 | while ((level > 0) && parent && (!err)) { | ||
1656 | status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, | ||
1657 | chandle, &chandle); | ||
1658 | |||
1659 | /* | ||
1660 | * If this scope is exhausted then move our way back up. | ||
1661 | */ | ||
1662 | if (ACPI_FAILURE(status)) { | ||
1663 | level--; | ||
1664 | chandle = phandle; | ||
1665 | acpi_get_parent(phandle, &phandle); | ||
1666 | child = parent; | ||
1667 | parent = parent->parent; | ||
1668 | err = acpi_bus_remove(child); | ||
1669 | continue; | ||
1670 | } | ||
1671 | |||
1672 | status = acpi_get_type(chandle, &type); | ||
1673 | if (ACPI_FAILURE(status)) { | ||
1674 | continue; | ||
1675 | } | ||
1676 | /* | ||
1677 | * If there is a device corresponding to chandle then | ||
1678 | * parse it (depth-first). | ||
1679 | */ | ||
1680 | if (acpi_bus_get_device(chandle, &child) == 0) { | ||
1681 | level++; | ||
1682 | phandle = chandle; | ||
1683 | chandle = NULL; | ||
1684 | parent = child; | ||
1685 | } | ||
1686 | continue; | ||
1687 | } | ||
1688 | return err; | ||
1689 | } | 1655 | } |
1690 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1656 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1691 | 1657 | ||