diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-11-24 18:52:21 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-11-24 18:52:21 -0500 |
commit | 2c22e6520ac87d8b12d4d9941e81d4119f2d903c (patch) | |
tree | 1c213ad56029c90ca38943ffdba091cff1aecded | |
parent | 25db115b0bf72acfdf8a339fa8e37d8b895214d6 (diff) |
ACPI / scan: Use direct recurrence for device hierarchy walks
Rework acpi_bus_trim() and acpi_bus_device_attach(), which is
renamed as acpi_bus_attach(), to walk the list of each device
object's children directly and call themselves recursively for
each child instead of using acpi_walk_namespace(). This
simplifies the code quite a bit and avoids the overhead of
callbacks and the ACPICA's internal processing which are not
really necessary for these two routines.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/scan.c | 120 |
1 files changed, 45 insertions, 75 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index cf773c918102..311904c720b1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1909,54 +1909,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
1909 | return ret; | 1909 | return ret; |
1910 | } | 1910 | } |
1911 | 1911 | ||
1912 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | 1912 | static void acpi_bus_attach(struct acpi_device *device) |
1913 | void *not_used, void **ret_not_used) | ||
1914 | { | 1913 | { |
1915 | struct acpi_device *device; | 1914 | struct acpi_device *child; |
1916 | unsigned long long sta; | ||
1917 | int ret; | 1915 | int ret; |
1918 | 1916 | ||
1919 | /* | 1917 | acpi_bus_get_status(device); |
1920 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating | ||
1921 | * namespace walks prematurely. | ||
1922 | */ | ||
1923 | if (acpi_bus_type_and_status(handle, &ret, &sta)) | ||
1924 | return AE_OK; | ||
1925 | |||
1926 | if (acpi_bus_get_device(handle, &device)) | ||
1927 | return AE_CTRL_DEPTH; | ||
1928 | |||
1929 | acpi_set_device_status(device, sta); | ||
1930 | /* Skip devices that are not present. */ | 1918 | /* Skip devices that are not present. */ |
1931 | if (!acpi_device_is_present(device)) | 1919 | if (!acpi_device_is_present(device)) { |
1932 | goto err; | 1920 | device->flags.visited = false; |
1933 | 1921 | return; | |
1922 | } | ||
1934 | if (device->handler) | 1923 | if (device->handler) |
1935 | return AE_OK; | 1924 | goto ok; |
1936 | 1925 | ||
1937 | if (!device->flags.initialized) { | 1926 | if (!device->flags.initialized) { |
1938 | acpi_bus_update_power(device, NULL); | 1927 | acpi_bus_update_power(device, NULL); |
1939 | device->flags.initialized = true; | 1928 | device->flags.initialized = true; |
1940 | } | 1929 | } |
1930 | device->flags.visited = false; | ||
1941 | ret = acpi_scan_attach_handler(device); | 1931 | ret = acpi_scan_attach_handler(device); |
1942 | if (ret < 0) | 1932 | if (ret < 0) |
1943 | goto err; | 1933 | return; |
1944 | 1934 | ||
1945 | device->flags.match_driver = true; | 1935 | device->flags.match_driver = true; |
1946 | if (ret > 0) | 1936 | if (!ret) { |
1947 | goto ok; | 1937 | ret = device_attach(&device->dev); |
1948 | 1938 | if (ret < 0) | |
1949 | ret = device_attach(&device->dev); | 1939 | return; |
1950 | if (ret < 0) | 1940 | } |
1951 | goto err; | ||
1952 | |||
1953 | ok: | ||
1954 | device->flags.visited = true; | 1941 | device->flags.visited = true; |
1955 | return AE_OK; | ||
1956 | 1942 | ||
1957 | err: | 1943 | ok: |
1958 | device->flags.visited = false; | 1944 | list_for_each_entry(child, &device->children, node) |
1959 | return AE_CTRL_DEPTH; | 1945 | acpi_bus_attach(child); |
1960 | } | 1946 | } |
1961 | 1947 | ||
1962 | /** | 1948 | /** |
@@ -1976,64 +1962,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1976 | int acpi_bus_scan(acpi_handle handle) | 1962 | int acpi_bus_scan(acpi_handle handle) |
1977 | { | 1963 | { |
1978 | void *device = NULL; | 1964 | void *device = NULL; |
1979 | int error = 0; | ||
1980 | 1965 | ||
1981 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 1966 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1982 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 1967 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1983 | acpi_bus_check_add, NULL, NULL, &device); | 1968 | acpi_bus_check_add, NULL, NULL, &device); |
1984 | 1969 | ||
1985 | if (!device) | 1970 | if (device) { |
1986 | error = -ENODEV; | 1971 | acpi_bus_attach(device); |
1987 | else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) | 1972 | return 0; |
1988 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
1989 | acpi_bus_device_attach, NULL, NULL, NULL); | ||
1990 | |||
1991 | return error; | ||
1992 | } | ||
1993 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1994 | |||
1995 | static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, | ||
1996 | void *not_used, void **ret_not_used) | ||
1997 | { | ||
1998 | struct acpi_device *device = NULL; | ||
1999 | |||
2000 | if (!acpi_bus_get_device(handle, &device)) { | ||
2001 | struct acpi_scan_handler *dev_handler = device->handler; | ||
2002 | |||
2003 | if (dev_handler) { | ||
2004 | if (dev_handler->detach) | ||
2005 | dev_handler->detach(device); | ||
2006 | |||
2007 | device->handler = NULL; | ||
2008 | } else { | ||
2009 | device_release_driver(&device->dev); | ||
2010 | } | ||
2011 | /* | ||
2012 | * Most likely, the device is going away, so put it into D3cold | ||
2013 | * before that. | ||
2014 | */ | ||
2015 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); | ||
2016 | device->flags.initialized = false; | ||
2017 | device->flags.visited = false; | ||
2018 | } | 1973 | } |
2019 | return AE_OK; | 1974 | return -ENODEV; |
2020 | } | 1975 | } |
1976 | EXPORT_SYMBOL(acpi_bus_scan); | ||
2021 | 1977 | ||
2022 | /** | 1978 | /** |
2023 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | 1979 | * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. |
2024 | * @start: Root of the ACPI device nodes subtree to remove. | 1980 | * @adev: Root of the ACPI namespace scope to walk. |
2025 | * | 1981 | * |
2026 | * Must be called under acpi_scan_lock. | 1982 | * Must be called under acpi_scan_lock. |
2027 | */ | 1983 | */ |
2028 | void acpi_bus_trim(struct acpi_device *start) | 1984 | void acpi_bus_trim(struct acpi_device *adev) |
2029 | { | 1985 | { |
1986 | struct acpi_scan_handler *handler = adev->handler; | ||
1987 | struct acpi_device *child; | ||
1988 | |||
1989 | list_for_each_entry_reverse(child, &adev->children, node) | ||
1990 | acpi_bus_trim(child); | ||
1991 | |||
1992 | if (handler) { | ||
1993 | if (handler->detach) | ||
1994 | handler->detach(adev); | ||
1995 | |||
1996 | adev->handler = NULL; | ||
1997 | } else { | ||
1998 | device_release_driver(&adev->dev); | ||
1999 | } | ||
2030 | /* | 2000 | /* |
2031 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 2001 | * Most likely, the device is going away, so put it into D3cold before |
2032 | * all ACPI drivers from the device nodes being removed. | 2002 | * that. |
2033 | */ | 2003 | */ |
2034 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | 2004 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); |
2035 | acpi_bus_device_detach, NULL, NULL); | 2005 | adev->flags.initialized = false; |
2036 | acpi_bus_device_detach(start->handle, 0, NULL, NULL); | 2006 | adev->flags.visited = false; |
2037 | } | 2007 | } |
2038 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 2008 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
2039 | 2009 | ||