aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:54:37 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-22 15:54:37 -0500
commit202317a573b20d77a9abb7c16a3fd5b40cef3d9d (patch)
tree2429aae549168cea780ac759939e1818b3487696 /drivers
parentd783156ea38431b20af0d4f910a6f9f9054d33b9 (diff)
ACPI / scan: Add acpi_device objects for all device nodes in the namespace
Modify the ACPI namespace scanning code to register a struct acpi_device object for every namespace node representing a device, processor and so on, even if the device represented by that namespace node is reported to be not present and not functional by _STA. There are multiple reasons to do that. First of all, it avoids quite a lot of overhead when struct acpi_device objects are deleted every time acpi_bus_trim() is run and then added again by a subsequent acpi_bus_scan() for the same scope, although the namespace objects they correspond to stay in memory all the time (which always is the case on a vast majority of systems). Second, it will allow user space to see that there are namespace nodes representing devices that are not present at the moment and may be added to the system. It will also allow user space to evaluate _SUN for those nodes to check what physical slots the "missing" devices may be put into and it will make sense to add a sysfs attribute for _STA evaluation after this change (that will be useful for thermal management on some systems). Next, it will help to consolidate the ACPI hotplug handling among subsystems by making it possible to store hotplug-related information in struct acpi_device objects in a standard common way. Finally, it will help to avoid a race condition related to the deletion of ACPI namespace nodes. Namely, namespace nodes may be deleted as a result of a table unload triggered by _EJ0 or _DCK. If a hotplug notification for one of those nodes is triggered right before the deletion and it executes a hotplug callback via acpi_hotplug_execute(), the ACPI handle passed to that callback may be stale when the callback actually runs. One way to work around that is to always pass struct acpi_device pointers to hotplug callbacks after doing a get_device() on the objects in question which eliminates the use-after-free possibility (the ACPI handles in those objects are invalidated by acpi_scan_drop_device(), so they will trigger ACPICA errors on attempts to use them). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/device_pm.c22
-rw-r--r--drivers/acpi/dock.c9
-rw-r--r--drivers/acpi/internal.h3
-rw-r--r--drivers/acpi/pci_root.c5
-rw-r--r--drivers/acpi/scan.c107
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c2
-rw-r--r--drivers/xen/xen-acpi-cpuhotplug.c8
-rw-r--r--drivers/xen/xen-acpi-memhotplug.c7
8 files changed, 88 insertions, 75 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index b3480cf7db1a..d49f1e464703 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -256,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device)
256 return -EINVAL; 256 return -EINVAL;
257 257
258 device->power.state = ACPI_STATE_UNKNOWN; 258 device->power.state = ACPI_STATE_UNKNOWN;
259 if (!acpi_device_is_present(device))
260 return 0;
259 261
260 result = acpi_device_get_power(device, &state); 262 result = acpi_device_get_power(device, &state);
261 if (result) 263 if (result)
@@ -302,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device)
302 return ret; 304 return ret;
303} 305}
304 306
305int acpi_bus_update_power(acpi_handle handle, int *state_p) 307int acpi_device_update_power(struct acpi_device *device, int *state_p)
306{ 308{
307 struct acpi_device *device;
308 int state; 309 int state;
309 int result; 310 int result;
310 311
311 result = acpi_bus_get_device(handle, &device); 312 if (device->power.state == ACPI_STATE_UNKNOWN) {
312 if (result) 313 result = acpi_bus_init_power(device);
314 if (!result && state_p)
315 *state_p = device->power.state;
316
313 return result; 317 return result;
318 }
314 319
315 result = acpi_device_get_power(device, &state); 320 result = acpi_device_get_power(device, &state);
316 if (result) 321 if (result)
@@ -338,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
338 343
339 return 0; 344 return 0;
340} 345}
346
347int acpi_bus_update_power(acpi_handle handle, int *state_p)
348{
349 struct acpi_device *device;
350 int result;
351
352 result = acpi_bus_get_device(handle, &device);
353 return result ? result : acpi_device_update_power(device, state_p);
354}
341EXPORT_SYMBOL_GPL(acpi_bus_update_power); 355EXPORT_SYMBOL_GPL(acpi_bus_update_power);
342 356
343bool acpi_bus_power_manageable(acpi_handle handle) 357bool acpi_bus_power_manageable(acpi_handle handle)
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index dcd73ccb514c..de032010da3c 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -323,14 +323,11 @@ static int dock_present(struct dock_station *ds)
323 */ 323 */
324static void dock_create_acpi_device(acpi_handle handle) 324static void dock_create_acpi_device(acpi_handle handle)
325{ 325{
326 struct acpi_device *device; 326 struct acpi_device *device = NULL;
327 int ret; 327 int ret;
328 328
329 if (acpi_bus_get_device(handle, &device)) { 329 acpi_bus_get_device(handle, &device);
330 /* 330 if (!acpi_device_enumerated(device)) {
331 * no device created for this object,
332 * so we should create one.
333 */
334 ret = acpi_bus_scan(handle); 331 ret = acpi_bus_scan(handle);
335 if (ret) 332 if (ret)
336 pr_debug("error adding bus, %x\n", -ret); 333 pr_debug("error adding bus, %x\n", -ret);
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index d8606498bf6f..809b8082c134 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -90,6 +90,7 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
90int acpi_bind_one(struct device *dev, acpi_handle handle); 90int acpi_bind_one(struct device *dev, acpi_handle handle);
91int acpi_unbind_one(struct device *dev); 91int acpi_unbind_one(struct device *dev);
92void acpi_bus_device_eject(void *data, u32 ost_src); 92void acpi_bus_device_eject(void *data, u32 ost_src);
93bool acpi_device_is_present(struct acpi_device *adev);
93 94
94/* -------------------------------------------------------------------------- 95/* --------------------------------------------------------------------------
95 Power Resource 96 Power Resource
@@ -107,6 +108,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
107int acpi_power_on_resources(struct acpi_device *device, int state); 108int acpi_power_on_resources(struct acpi_device *device, int state);
108int acpi_power_transition(struct acpi_device *device, int state); 109int acpi_power_transition(struct acpi_device *device, int state);
109 110
111int acpi_device_update_power(struct acpi_device *device, int *state_p);
112
110int acpi_wakeup_device_init(void); 113int acpi_wakeup_device_init(void);
111void acpi_early_processor_set_pdc(void); 114void acpi_early_processor_set_pdc(void);
112 115
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 20360e480bd8..4076491c6ded 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -634,9 +634,10 @@ void __init acpi_pci_root_init(void)
634 634
635static void handle_root_bridge_insertion(acpi_handle handle) 635static void handle_root_bridge_insertion(acpi_handle handle)
636{ 636{
637 struct acpi_device *device; 637 struct acpi_device *device = NULL;
638 638
639 if (!acpi_bus_get_device(handle, &device)) { 639 acpi_bus_get_device(handle, &device);
640 if (acpi_device_enumerated(device)) {
640 dev_printk(KERN_DEBUG, &device->dev, 641 dev_printk(KERN_DEBUG, &device->dev,
641 "acpi device already exists; ignoring notify\n"); 642 "acpi device already exists; ignoring notify\n");
642 return; 643 return;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index ad2522015e5e..bc52192785f1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -259,7 +259,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
259 259
260 acpi_bus_trim(device); 260 acpi_bus_trim(device);
261 261
262 /* Device node has been unregistered. */
263 put_device(&device->dev); 262 put_device(&device->dev);
264 device = NULL; 263 device = NULL;
265 264
@@ -328,7 +327,7 @@ void acpi_bus_device_eject(void *data, u32 ost_src)
328static void acpi_scan_bus_device_check(void *data, u32 ost_source) 327static void acpi_scan_bus_device_check(void *data, u32 ost_source)
329{ 328{
330 acpi_handle handle = data; 329 acpi_handle handle = data;
331 struct acpi_device *device = NULL; 330 struct acpi_device *device;
332 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; 331 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
333 int error; 332 int error;
334 333
@@ -336,8 +335,9 @@ static void acpi_scan_bus_device_check(void *data, u32 ost_source)
336 mutex_lock(&acpi_scan_lock); 335 mutex_lock(&acpi_scan_lock);
337 336
338 if (ost_source != ACPI_NOTIFY_BUS_CHECK) { 337 if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
338 device = NULL;
339 acpi_bus_get_device(handle, &device); 339 acpi_bus_get_device(handle, &device);
340 if (device) { 340 if (acpi_device_enumerated(device)) {
341 dev_warn(&device->dev, "Attempt to re-insert\n"); 341 dev_warn(&device->dev, "Attempt to re-insert\n");
342 goto out; 342 goto out;
343 } 343 }
@@ -347,9 +347,10 @@ static void acpi_scan_bus_device_check(void *data, u32 ost_source)
347 acpi_handle_warn(handle, "Namespace scan failure\n"); 347 acpi_handle_warn(handle, "Namespace scan failure\n");
348 goto out; 348 goto out;
349 } 349 }
350 error = acpi_bus_get_device(handle, &device); 350 device = NULL;
351 if (error) { 351 acpi_bus_get_device(handle, &device);
352 acpi_handle_warn(handle, "Missing device node object\n"); 352 if (!acpi_device_enumerated(device)) {
353 acpi_handle_warn(handle, "Device not enumerated\n");
353 goto out; 354 goto out;
354 } 355 }
355 ost_code = ACPI_OST_SC_SUCCESS; 356 ost_code = ACPI_OST_SC_SUCCESS;
@@ -1111,20 +1112,6 @@ int acpi_device_add(struct acpi_device *device,
1111 return result; 1112 return result;
1112} 1113}
1113 1114
1114static void acpi_device_unregister(struct acpi_device *device)
1115{
1116 acpi_detach_data(device->handle, acpi_scan_drop_device);
1117 acpi_device_del(device);
1118 /*
1119 * Transition the device to D3cold to drop the reference counts of all
1120 * power resources the device depends on and turn off the ones that have
1121 * no more references.
1122 */
1123 acpi_device_set_power(device, ACPI_STATE_D3_COLD);
1124 device->handle = NULL;
1125 put_device(&device->dev);
1126}
1127
1128/* -------------------------------------------------------------------------- 1115/* --------------------------------------------------------------------------
1129 Driver Management 1116 Driver Management
1130 -------------------------------------------------------------------------- */ 1117 -------------------------------------------------------------------------- */
@@ -1703,6 +1690,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
1703 acpi_set_pnp_ids(handle, &device->pnp, type); 1690 acpi_set_pnp_ids(handle, &device->pnp, type);
1704 acpi_bus_get_flags(device); 1691 acpi_bus_get_flags(device);
1705 device->flags.match_driver = false; 1692 device->flags.match_driver = false;
1693 device->flags.initialized = true;
1694 device->flags.visited = false;
1706 device_initialize(&device->dev); 1695 device_initialize(&device->dev);
1707 dev_set_uevent_suppress(&device->dev, true); 1696 dev_set_uevent_suppress(&device->dev, true);
1708} 1697}
@@ -1787,6 +1776,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
1787 return 0; 1776 return 0;
1788} 1777}
1789 1778
1779bool acpi_device_is_present(struct acpi_device *adev)
1780{
1781 if (adev->status.present || adev->status.functional)
1782 return true;
1783
1784 adev->flags.initialized = false;
1785 return false;
1786}
1787
1790static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, 1788static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
1791 char *idstr, 1789 char *idstr,
1792 const struct acpi_device_id **matchid) 1790 const struct acpi_device_id **matchid)
@@ -1880,18 +1878,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1880 1878
1881 acpi_scan_init_hotplug(handle, type); 1879 acpi_scan_init_hotplug(handle, type);
1882 1880
1883 if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
1884 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
1885 struct acpi_device_wakeup wakeup;
1886
1887 if (acpi_has_method(handle, "_PRW")) {
1888 acpi_bus_extract_wakeup_device_power_package(handle,
1889 &wakeup);
1890 acpi_power_resources_list_free(&wakeup.resources);
1891 }
1892 return AE_CTRL_DEPTH;
1893 }
1894
1895 acpi_add_single_object(&device, handle, type, sta); 1881 acpi_add_single_object(&device, handle, type, sta);
1896 if (!device) 1882 if (!device)
1897 return AE_CTRL_DEPTH; 1883 return AE_CTRL_DEPTH;
@@ -1930,32 +1916,50 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
1930 void *not_used, void **ret_not_used) 1916 void *not_used, void **ret_not_used)
1931{ 1917{
1932 struct acpi_device *device; 1918 struct acpi_device *device;
1933 unsigned long long sta_not_used; 1919 unsigned long long sta;
1934 int ret; 1920 int ret;
1935 1921
1936 /* 1922 /*
1937 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating 1923 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
1938 * namespace walks prematurely. 1924 * namespace walks prematurely.
1939 */ 1925 */
1940 if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) 1926 if (acpi_bus_type_and_status(handle, &ret, &sta))
1941 return AE_OK; 1927 return AE_OK;
1942 1928
1943 if (acpi_bus_get_device(handle, &device)) 1929 if (acpi_bus_get_device(handle, &device))
1944 return AE_CTRL_DEPTH; 1930 return AE_CTRL_DEPTH;
1945 1931
1932 STRUCT_TO_INT(device->status) = sta;
1933 /* Skip devices that are not present. */
1934 if (!acpi_device_is_present(device))
1935 goto err;
1936
1946 if (device->handler) 1937 if (device->handler)
1947 return AE_OK; 1938 return AE_OK;
1948 1939
1940 if (!device->flags.initialized) {
1941 acpi_bus_update_power(device, NULL);
1942 device->flags.initialized = true;
1943 }
1949 ret = acpi_scan_attach_handler(device); 1944 ret = acpi_scan_attach_handler(device);
1950 if (ret < 0) 1945 if (ret < 0)
1951 return AE_CTRL_DEPTH; 1946 goto err;
1952 1947
1953 device->flags.match_driver = true; 1948 device->flags.match_driver = true;
1954 if (ret > 0) 1949 if (ret > 0)
1955 return AE_OK; 1950 goto ok;
1956 1951
1957 ret = device_attach(&device->dev); 1952 ret = device_attach(&device->dev);
1958 return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; 1953 if (ret < 0)
1954 goto err;
1955
1956 ok:
1957 device->flags.visited = true;
1958 return AE_OK;
1959
1960 err:
1961 device->flags.visited = false;
1962 return AE_CTRL_DEPTH;
1959} 1963}
1960 1964
1961/** 1965/**
@@ -2007,21 +2011,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
2007 } else { 2011 } else {
2008 device_release_driver(&device->dev); 2012 device_release_driver(&device->dev);
2009 } 2013 }
2014 /*
2015 * Most likely, the device is going away, so put it into D3cold
2016 * before that.
2017 */
2018 acpi_device_set_power(device, ACPI_STATE_D3_COLD);
2019 device->flags.initialized = false;
2020 device->flags.visited = false;
2010 } 2021 }
2011 return AE_OK; 2022 return AE_OK;
2012} 2023}
2013 2024
2014static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
2015 void *not_used, void **ret_not_used)
2016{
2017 struct acpi_device *device = NULL;
2018
2019 if (!acpi_bus_get_device(handle, &device))
2020 acpi_device_unregister(device);
2021
2022 return AE_OK;
2023}
2024
2025/** 2025/**
2026 * acpi_bus_trim - Remove ACPI device node and all of its descendants 2026 * acpi_bus_trim - Remove ACPI device node and all of its descendants
2027 * @start: Root of the ACPI device nodes subtree to remove. 2027 * @start: Root of the ACPI device nodes subtree to remove.
@@ -2037,13 +2037,6 @@ void acpi_bus_trim(struct acpi_device *start)
2037 acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, 2037 acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
2038 acpi_bus_device_detach, NULL, NULL); 2038 acpi_bus_device_detach, NULL, NULL);
2039 acpi_bus_device_detach(start->handle, 0, NULL, NULL); 2039 acpi_bus_device_detach(start->handle, 0, NULL, NULL);
2040 /*
2041 * Execute acpi_bus_remove() as a post-order callback to remove device
2042 * nodes in the given namespace scope.
2043 */
2044 acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
2045 acpi_bus_remove, NULL, NULL);
2046 acpi_bus_remove(start->handle, 0, NULL, NULL);
2047} 2040}
2048EXPORT_SYMBOL_GPL(acpi_bus_trim); 2041EXPORT_SYMBOL_GPL(acpi_bus_trim);
2049 2042
@@ -2121,7 +2114,9 @@ int __init acpi_scan_init(void)
2121 2114
2122 result = acpi_bus_scan_fixed(); 2115 result = acpi_bus_scan_fixed();
2123 if (result) { 2116 if (result) {
2124 acpi_device_unregister(acpi_root); 2117 acpi_detach_data(acpi_root->handle, acpi_scan_drop_device);
2118 acpi_device_del(acpi_root);
2119 put_device(&acpi_root->dev);
2125 goto out; 2120 goto out;
2126 } 2121 }
2127 2122
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 1cf605f67673..67be6bab7535 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -489,7 +489,7 @@ static void acpiphp_bus_add(acpi_handle handle)
489 489
490 acpi_bus_scan(handle); 490 acpi_bus_scan(handle);
491 acpi_bus_get_device(handle, &adev); 491 acpi_bus_get_device(handle, &adev);
492 if (adev) 492 if (acpi_device_enumerated(adev))
493 acpi_device_set_power(adev, ACPI_STATE_D0); 493 acpi_device_set_power(adev, ACPI_STATE_D0);
494} 494}
495 495
diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c
index 8dae6c13063a..73496c3d18ae 100644
--- a/drivers/xen/xen-acpi-cpuhotplug.c
+++ b/drivers/xen/xen-acpi-cpuhotplug.c
@@ -269,7 +269,8 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
269 if (!is_processor_present(handle)) 269 if (!is_processor_present(handle))
270 break; 270 break;
271 271
272 if (!acpi_bus_get_device(handle, &device)) 272 acpi_bus_get_device(handle, &device);
273 if (acpi_device_enumerated(device))
273 break; 274 break;
274 275
275 result = acpi_bus_scan(handle); 276 result = acpi_bus_scan(handle);
@@ -277,8 +278,9 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
277 pr_err(PREFIX "Unable to add the device\n"); 278 pr_err(PREFIX "Unable to add the device\n");
278 break; 279 break;
279 } 280 }
280 result = acpi_bus_get_device(handle, &device); 281 device = NULL;
281 if (result) { 282 acpi_bus_get_device(handle, &device);
283 if (!acpi_device_enumerated(device)) {
282 pr_err(PREFIX "Missing device object\n"); 284 pr_err(PREFIX "Missing device object\n");
283 break; 285 break;
284 } 286 }
diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c
index 9083f1e474f8..9b056f06691f 100644
--- a/drivers/xen/xen-acpi-memhotplug.c
+++ b/drivers/xen/xen-acpi-memhotplug.c
@@ -169,7 +169,7 @@ static int acpi_memory_get_device(acpi_handle handle,
169 acpi_scan_lock_acquire(); 169 acpi_scan_lock_acquire();
170 170
171 acpi_bus_get_device(handle, &device); 171 acpi_bus_get_device(handle, &device);
172 if (device) 172 if (acpi_device_enumerated(device))
173 goto end; 173 goto end;
174 174
175 /* 175 /*
@@ -182,8 +182,9 @@ static int acpi_memory_get_device(acpi_handle handle,
182 result = -EINVAL; 182 result = -EINVAL;
183 goto out; 183 goto out;
184 } 184 }
185 result = acpi_bus_get_device(handle, &device); 185 device = NULL;
186 if (result) { 186 acpi_bus_get_device(handle, &device);
187 if (!acpi_device_enumerated(device)) {
187 pr_warn(PREFIX "Missing device object\n"); 188 pr_warn(PREFIX "Missing device object\n");
188 result = -EINVAL; 189 result = -EINVAL;
189 goto out; 190 goto out;