diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 18:51:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-24 18:51:02 -0500 |
commit | 09da8dfa98682d871987145ed11e3232accac860 (patch) | |
tree | 152a9bb1e52f70db6efb66fffbdc4871f749d7df /drivers/acpi/scan.c | |
parent | 3aacd625f20129f5a41ea3ff3b5353b0e4dabd01 (diff) | |
parent | 7744064731a9543105e207504e0262f883bc14c0 (diff) |
Merge tag 'pm+acpi-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management updates from Rafael Wysocki:
"As far as the number of commits goes, the top spot belongs to ACPI
this time with cpufreq in the second position and a handful of PM
core, PNP and cpuidle updates. They are fixes and cleanups mostly, as
usual, with a couple of new features in the mix.
The most visible change is probably that we will create struct
acpi_device objects (visible in sysfs) for all devices represented in
the ACPI tables regardless of their status and there will be a new
sysfs attribute under those objects allowing user space to check that
status via _STA.
Consequently, ACPI device eject or generally hot-removal will not
delete those objects, unless the table containing the corresponding
namespace nodes is unloaded, which is extremely rare. Also ACPI
container hotplug will be handled quite a bit differently and cpufreq
will support CPU boost ("turbo") generically and not only in the
acpi-cpufreq driver.
Specifics:
- ACPI core changes to make it create a struct acpi_device object for
every device represented in the ACPI tables during all namespace
scans regardless of the current status of that device. In
accordance with this, ACPI hotplug operations will not delete those
objects, unless the underlying ACPI tables go away.
- On top of the above, new sysfs attribute for ACPI device objects
allowing user space to check device status by triggering the
execution of _STA for its ACPI object. From Srinivas Pandruvada.
- ACPI core hotplug changes reducing code duplication, integrating
the PCI root hotplug with the core and reworking container hotplug.
- ACPI core simplifications making it use ACPI_COMPANION() in the
code "glueing" ACPI device objects to "physical" devices.
- ACPICA update to upstream version 20131218. This adds support for
the DBG2 and PCCT tables to ACPICA, fixes some bugs and improves
debug facilities. From Bob Moore, Lv Zheng and Betty Dall.
- Init code change to carry out the early ACPI initialization
earlier. That should allow us to use ACPI during the timekeeping
initialization and possibly to simplify the EFI initialization too.
From Chun-Yi Lee.
- Clenups of the inclusions of ACPI headers in many places all over
from Lv Zheng and Rashika Kheria (work in progress).
- New helper for ACPI _DSM execution and rework of the code in
drivers that uses _DSM to execute it via the new helper. From
Jiang Liu.
- New Win8 OSI blacklist entries from Takashi Iwai.
- Assorted ACPI fixes and cleanups from Al Stone, Emil Goode, Hanjun
Guo, Lan Tianyu, Masanari Iida, Oliver Neukum, Prarit Bhargava,
Rashika Kheria, Tang Chen, Zhang Rui.
- intel_pstate driver updates, including proper Baytrail support,
from Dirk Brandewie and intel_pstate documentation from Ramkumar
Ramachandra.
- Generic CPU boost ("turbo") support for cpufreq from Lukasz
Majewski.
- powernow-k6 cpufreq driver fixes from Mikulas Patocka.
- cpufreq core fixes and cleanups from Viresh Kumar, Jane Li, Mark
Brown.
- Assorted cpufreq drivers fixes and cleanups from Anson Huang, John
Tobias, Paul Bolle, Paul Walmsley, Sachin Kamat, Shawn Guo, Viresh
Kumar.
- cpuidle cleanups from Bartlomiej Zolnierkiewicz.
- Support for hibernation APM events from Bin Shi.
- Hibernation fix to avoid bringing up nonboot CPUs with ACPI EC
disabled during thaw transitions from Bjørn Mork.
- PM core fixes and cleanups from Ben Dooks, Leonardo Potenza, Ulf
Hansson.
- PNP subsystem fixes and cleanups from Dmitry Torokhov, Levente
Kurusa, Rashika Kheria.
- New tool for profiling system suspend from Todd E Brandt and a
cpupower tool cleanup from One Thousand Gnomes"
* tag 'pm+acpi-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (153 commits)
thermal: exynos: boost: Automatic enable/disable of BOOST feature (at Exynos4412)
cpufreq: exynos4x12: Change L0 driver data to CPUFREQ_BOOST_FREQ
Documentation: cpufreq / boost: Update BOOST documentation
cpufreq: exynos: Extend Exynos cpufreq driver to support boost
cpufreq / boost: Kconfig: Support for software-managed BOOST
acpi-cpufreq: Adjust the code to use the common boost attribute
cpufreq: Add boost frequency support in core
intel_pstate: Add trace point to report internal state.
cpufreq: introduce cpufreq_generic_get() routine
ARM: SA1100: Create dummy clk_get_rate() to avoid build failures
cpufreq: stats: create sysfs entries when cpufreq_stats is a module
cpufreq: stats: free table and remove sysfs entry in a single routine
cpufreq: stats: remove hotplug notifiers
cpufreq: stats: handle cpufreq_unregister_driver() and suspend/resume properly
cpufreq: speedstep: remove unused speedstep_get_state
platform: introduce OF style 'modalias' support for platform bus
PM / tools: new tool for suspend/resume performance optimization
ACPI: fix module autoloading for ACPI enumerated devices
ACPI: add module autoloading support for ACPI enumerated devices
ACPI: fix create_modalias() return value handling
...
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 620 |
1 files changed, 385 insertions, 235 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index fd39459926b1..e00365ccb897 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -12,13 +12,12 @@ | |||
12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
13 | #include <linux/nls.h> | 13 | #include <linux/nls.h> |
14 | 14 | ||
15 | #include <acpi/acpi_drivers.h> | 15 | #include <asm/pgtable.h> |
16 | 16 | ||
17 | #include "internal.h" | 17 | #include "internal.h" |
18 | 18 | ||
19 | #define _COMPONENT ACPI_BUS_COMPONENT | 19 | #define _COMPONENT ACPI_BUS_COMPONENT |
20 | ACPI_MODULE_NAME("scan"); | 20 | ACPI_MODULE_NAME("scan"); |
21 | #define STRUCT_TO_INT(s) (*((int*)&s)) | ||
22 | extern struct acpi_device *acpi_root; | 21 | extern struct acpi_device *acpi_root; |
23 | 22 | ||
24 | #define ACPI_BUS_CLASS "system_bus" | 23 | #define ACPI_BUS_CLASS "system_bus" |
@@ -27,6 +26,8 @@ extern struct acpi_device *acpi_root; | |||
27 | 26 | ||
28 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) | 27 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
29 | 28 | ||
29 | #define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) | ||
30 | |||
30 | /* | 31 | /* |
31 | * If set, devices will be hot-removed even if they cannot be put offline | 32 | * If set, devices will be hot-removed even if they cannot be put offline |
32 | * gracefully (from the kernel's standpoint). | 33 | * gracefully (from the kernel's standpoint). |
@@ -85,6 +86,9 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | |||
85 | * Creates hid/cid(s) string needed for modalias and uevent | 86 | * Creates hid/cid(s) string needed for modalias and uevent |
86 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 87 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
87 | * char *modalias: "acpi:IBM0001:ACPI0001" | 88 | * char *modalias: "acpi:IBM0001:ACPI0001" |
89 | * Return: 0: no _HID and no _CID | ||
90 | * -EINVAL: output error | ||
91 | * -ENOMEM: output is truncated | ||
88 | */ | 92 | */ |
89 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | 93 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, |
90 | int size) | 94 | int size) |
@@ -101,8 +105,10 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
101 | 105 | ||
102 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 106 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { |
103 | count = snprintf(&modalias[len], size, "%s:", id->id); | 107 | count = snprintf(&modalias[len], size, "%s:", id->id); |
104 | if (count < 0 || count >= size) | 108 | if (count < 0) |
105 | return -EINVAL; | 109 | return EINVAL; |
110 | if (count >= size) | ||
111 | return -ENOMEM; | ||
106 | len += count; | 112 | len += count; |
107 | size -= count; | 113 | size -= count; |
108 | } | 114 | } |
@@ -111,20 +117,96 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
111 | return len; | 117 | return len; |
112 | } | 118 | } |
113 | 119 | ||
120 | /* | ||
121 | * Creates uevent modalias field for ACPI enumerated devices. | ||
122 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
123 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
124 | * "acpi:IBM0001:ACPI0001" | ||
125 | */ | ||
126 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | ||
127 | { | ||
128 | struct acpi_device *acpi_dev; | ||
129 | int len; | ||
130 | |||
131 | acpi_dev = ACPI_COMPANION(dev); | ||
132 | if (!acpi_dev) | ||
133 | return -ENODEV; | ||
134 | |||
135 | /* Fall back to bus specific way of modalias exporting */ | ||
136 | if (list_empty(&acpi_dev->pnp.ids)) | ||
137 | return -ENODEV; | ||
138 | |||
139 | if (add_uevent_var(env, "MODALIAS=")) | ||
140 | return -ENOMEM; | ||
141 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | ||
142 | sizeof(env->buf) - env->buflen); | ||
143 | if (len <= 0) | ||
144 | return len; | ||
145 | env->buflen += len; | ||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | ||
149 | |||
150 | /* | ||
151 | * Creates modalias sysfs attribute for ACPI enumerated devices. | ||
152 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
153 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
154 | * "acpi:IBM0001:ACPI0001" | ||
155 | */ | ||
156 | int acpi_device_modalias(struct device *dev, char *buf, int size) | ||
157 | { | ||
158 | struct acpi_device *acpi_dev; | ||
159 | int len; | ||
160 | |||
161 | acpi_dev = ACPI_COMPANION(dev); | ||
162 | if (!acpi_dev) | ||
163 | return -ENODEV; | ||
164 | |||
165 | /* Fall back to bus specific way of modalias exporting */ | ||
166 | if (list_empty(&acpi_dev->pnp.ids)) | ||
167 | return -ENODEV; | ||
168 | |||
169 | len = create_modalias(acpi_dev, buf, size -1); | ||
170 | if (len <= 0) | ||
171 | return len; | ||
172 | buf[len++] = '\n'; | ||
173 | return len; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(acpi_device_modalias); | ||
176 | |||
114 | static ssize_t | 177 | static ssize_t |
115 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { | 178 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { |
116 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 179 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
117 | int len; | 180 | int len; |
118 | 181 | ||
119 | /* Device has no HID and no CID or string is >1024 */ | ||
120 | len = create_modalias(acpi_dev, buf, 1024); | 182 | len = create_modalias(acpi_dev, buf, 1024); |
121 | if (len <= 0) | 183 | if (len <= 0) |
122 | return 0; | 184 | return len; |
123 | buf[len++] = '\n'; | 185 | buf[len++] = '\n'; |
124 | return len; | 186 | return len; |
125 | } | 187 | } |
126 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 188 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
127 | 189 | ||
190 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) | ||
191 | { | ||
192 | struct acpi_device_physical_node *pn; | ||
193 | bool offline = true; | ||
194 | |||
195 | mutex_lock(&adev->physical_node_lock); | ||
196 | |||
197 | list_for_each_entry(pn, &adev->physical_node_list, node) | ||
198 | if (device_supports_offline(pn->dev) && !pn->dev->offline) { | ||
199 | if (uevent) | ||
200 | kobject_uevent(&pn->dev->kobj, KOBJ_CHANGE); | ||
201 | |||
202 | offline = false; | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | mutex_unlock(&adev->physical_node_lock); | ||
207 | return offline; | ||
208 | } | ||
209 | |||
128 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, | 210 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, |
129 | void **ret_p) | 211 | void **ret_p) |
130 | { | 212 | { |
@@ -195,19 +277,11 @@ static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, | |||
195 | return AE_OK; | 277 | return AE_OK; |
196 | } | 278 | } |
197 | 279 | ||
198 | static int acpi_scan_hot_remove(struct acpi_device *device) | 280 | static int acpi_scan_try_to_offline(struct acpi_device *device) |
199 | { | 281 | { |
200 | acpi_handle handle = device->handle; | 282 | acpi_handle handle = device->handle; |
201 | struct device *errdev; | 283 | struct device *errdev = NULL; |
202 | acpi_status status; | 284 | acpi_status status; |
203 | unsigned long long sta; | ||
204 | |||
205 | /* If there is no handle, the device node has been unregistered. */ | ||
206 | if (!handle) { | ||
207 | dev_dbg(&device->dev, "ACPI handle missing\n"); | ||
208 | put_device(&device->dev); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | 285 | ||
212 | /* | 286 | /* |
213 | * Carry out two passes here and ignore errors in the first pass, | 287 | * Carry out two passes here and ignore errors in the first pass, |
@@ -218,7 +292,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
218 | * | 292 | * |
219 | * If the first pass is successful, the second one isn't needed, though. | 293 | * If the first pass is successful, the second one isn't needed, though. |
220 | */ | 294 | */ |
221 | errdev = NULL; | ||
222 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 295 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
223 | NULL, acpi_bus_offline, (void *)false, | 296 | NULL, acpi_bus_offline, (void *)false, |
224 | (void **)&errdev); | 297 | (void **)&errdev); |
@@ -226,7 +299,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
226 | dev_warn(errdev, "Offline disabled.\n"); | 299 | dev_warn(errdev, "Offline disabled.\n"); |
227 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 300 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
228 | acpi_bus_online, NULL, NULL, NULL); | 301 | acpi_bus_online, NULL, NULL, NULL); |
229 | put_device(&device->dev); | ||
230 | return -EPERM; | 302 | return -EPERM; |
231 | } | 303 | } |
232 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); | 304 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); |
@@ -245,20 +317,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
245 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, | 317 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, |
246 | ACPI_UINT32_MAX, acpi_bus_online, | 318 | ACPI_UINT32_MAX, acpi_bus_online, |
247 | NULL, NULL, NULL); | 319 | NULL, NULL, NULL); |
248 | put_device(&device->dev); | ||
249 | return -EBUSY; | 320 | return -EBUSY; |
250 | } | 321 | } |
251 | } | 322 | } |
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int acpi_scan_hot_remove(struct acpi_device *device) | ||
327 | { | ||
328 | acpi_handle handle = device->handle; | ||
329 | unsigned long long sta; | ||
330 | acpi_status status; | ||
331 | |||
332 | if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { | ||
333 | if (!acpi_scan_is_offline(device, true)) | ||
334 | return -EBUSY; | ||
335 | } else { | ||
336 | int error = acpi_scan_try_to_offline(device); | ||
337 | if (error) | ||
338 | return error; | ||
339 | } | ||
252 | 340 | ||
253 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 341 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
254 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 342 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
255 | 343 | ||
256 | acpi_bus_trim(device); | 344 | acpi_bus_trim(device); |
257 | 345 | ||
258 | /* Device node has been unregistered. */ | ||
259 | put_device(&device->dev); | ||
260 | device = NULL; | ||
261 | |||
262 | acpi_evaluate_lck(handle, 0); | 346 | acpi_evaluate_lck(handle, 0); |
263 | /* | 347 | /* |
264 | * TBD: _EJD support. | 348 | * TBD: _EJD support. |
@@ -285,115 +369,127 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
285 | return 0; | 369 | return 0; |
286 | } | 370 | } |
287 | 371 | ||
288 | void acpi_bus_device_eject(void *data, u32 ost_src) | 372 | static int acpi_scan_device_not_present(struct acpi_device *adev) |
289 | { | 373 | { |
290 | struct acpi_device *device = data; | 374 | if (!acpi_device_enumerated(adev)) { |
291 | acpi_handle handle = device->handle; | 375 | dev_warn(&adev->dev, "Still not present\n"); |
292 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 376 | return -EALREADY; |
293 | int error; | 377 | } |
378 | acpi_bus_trim(adev); | ||
379 | return 0; | ||
380 | } | ||
294 | 381 | ||
295 | lock_device_hotplug(); | 382 | static int acpi_scan_device_check(struct acpi_device *adev) |
296 | mutex_lock(&acpi_scan_lock); | 383 | { |
384 | int error; | ||
297 | 385 | ||
298 | if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) | 386 | acpi_bus_get_status(adev); |
299 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 387 | if (adev->status.present || adev->status.functional) { |
300 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 388 | /* |
389 | * This function is only called for device objects for which | ||
390 | * matching scan handlers exist. The only situation in which | ||
391 | * the scan handler is not attached to this device object yet | ||
392 | * is when the device has just appeared (either it wasn't | ||
393 | * present at all before or it was removed and then added | ||
394 | * again). | ||
395 | */ | ||
396 | if (adev->handler) { | ||
397 | dev_warn(&adev->dev, "Already enumerated\n"); | ||
398 | return -EALREADY; | ||
399 | } | ||
400 | error = acpi_bus_scan(adev->handle); | ||
401 | if (error) { | ||
402 | dev_warn(&adev->dev, "Namespace scan failure\n"); | ||
403 | return error; | ||
404 | } | ||
405 | if (!adev->handler) { | ||
406 | dev_warn(&adev->dev, "Enumeration failure\n"); | ||
407 | error = -ENODEV; | ||
408 | } | ||
409 | } else { | ||
410 | error = acpi_scan_device_not_present(adev); | ||
411 | } | ||
412 | return error; | ||
413 | } | ||
301 | 414 | ||
302 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | 415 | static int acpi_scan_bus_check(struct acpi_device *adev) |
303 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 416 | { |
417 | struct acpi_scan_handler *handler = adev->handler; | ||
418 | struct acpi_device *child; | ||
419 | int error; | ||
304 | 420 | ||
305 | error = acpi_scan_hot_remove(device); | 421 | acpi_bus_get_status(adev); |
306 | if (error == -EPERM) { | 422 | if (!(adev->status.present || adev->status.functional)) { |
307 | goto err_support; | 423 | acpi_scan_device_not_present(adev); |
308 | } else if (error) { | 424 | return 0; |
309 | goto err_out; | ||
310 | } | 425 | } |
426 | if (handler && handler->hotplug.scan_dependent) | ||
427 | return handler->hotplug.scan_dependent(adev); | ||
311 | 428 | ||
312 | out: | 429 | error = acpi_bus_scan(adev->handle); |
313 | mutex_unlock(&acpi_scan_lock); | 430 | if (error) { |
314 | unlock_device_hotplug(); | 431 | dev_warn(&adev->dev, "Namespace scan failure\n"); |
315 | return; | 432 | return error; |
316 | 433 | } | |
317 | err_support: | 434 | list_for_each_entry(child, &adev->children, node) { |
318 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 435 | error = acpi_scan_bus_check(child); |
319 | err_out: | 436 | if (error) |
320 | acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); | 437 | return error; |
321 | goto out; | 438 | } |
439 | return 0; | ||
322 | } | 440 | } |
323 | 441 | ||
324 | static void acpi_scan_bus_device_check(void *data, u32 ost_source) | 442 | static void acpi_device_hotplug(void *data, u32 src) |
325 | { | 443 | { |
326 | acpi_handle handle = data; | ||
327 | struct acpi_device *device = NULL; | ||
328 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 444 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
445 | struct acpi_device *adev = data; | ||
329 | int error; | 446 | int error; |
330 | 447 | ||
331 | lock_device_hotplug(); | 448 | lock_device_hotplug(); |
332 | mutex_lock(&acpi_scan_lock); | 449 | mutex_lock(&acpi_scan_lock); |
333 | 450 | ||
334 | if (ost_source != ACPI_NOTIFY_BUS_CHECK) { | 451 | /* |
335 | acpi_bus_get_device(handle, &device); | 452 | * The device object's ACPI handle cannot become invalid as long as we |
336 | if (device) { | 453 | * are holding acpi_scan_lock, but it may have become invalid before |
337 | dev_warn(&device->dev, "Attempt to re-insert\n"); | 454 | * that lock was acquired. |
338 | goto out; | 455 | */ |
339 | } | 456 | if (adev->handle == INVALID_ACPI_HANDLE) |
340 | } | ||
341 | error = acpi_bus_scan(handle); | ||
342 | if (error) { | ||
343 | acpi_handle_warn(handle, "Namespace scan failure\n"); | ||
344 | goto out; | ||
345 | } | ||
346 | error = acpi_bus_get_device(handle, &device); | ||
347 | if (error) { | ||
348 | acpi_handle_warn(handle, "Missing device node object\n"); | ||
349 | goto out; | 457 | goto out; |
350 | } | ||
351 | ost_code = ACPI_OST_SC_SUCCESS; | ||
352 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | ||
353 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | ||
354 | 458 | ||
355 | out: | 459 | switch (src) { |
356 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); | ||
357 | mutex_unlock(&acpi_scan_lock); | ||
358 | unlock_device_hotplug(); | ||
359 | } | ||
360 | |||
361 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | ||
362 | { | ||
363 | u32 ost_status; | ||
364 | |||
365 | switch (type) { | ||
366 | case ACPI_NOTIFY_BUS_CHECK: | 460 | case ACPI_NOTIFY_BUS_CHECK: |
367 | acpi_handle_debug(handle, | 461 | error = acpi_scan_bus_check(adev); |
368 | "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); | ||
369 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
370 | break; | 462 | break; |
371 | case ACPI_NOTIFY_DEVICE_CHECK: | 463 | case ACPI_NOTIFY_DEVICE_CHECK: |
372 | acpi_handle_debug(handle, | 464 | error = acpi_scan_device_check(adev); |
373 | "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); | ||
374 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
375 | break; | 465 | break; |
376 | case ACPI_NOTIFY_EJECT_REQUEST: | 466 | case ACPI_NOTIFY_EJECT_REQUEST: |
377 | acpi_handle_debug(handle, | 467 | case ACPI_OST_EC_OSPM_EJECT: |
378 | "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); | 468 | error = acpi_scan_hot_remove(adev); |
379 | ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
380 | break; | 469 | break; |
381 | default: | 470 | default: |
382 | /* non-hotplug event; possibly handled by other handler */ | 471 | error = -EINVAL; |
383 | return; | 472 | break; |
384 | } | 473 | } |
474 | if (!error) | ||
475 | ost_code = ACPI_OST_SC_SUCCESS; | ||
385 | 476 | ||
386 | acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); | 477 | out: |
478 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); | ||
479 | put_device(&adev->dev); | ||
480 | mutex_unlock(&acpi_scan_lock); | ||
481 | unlock_device_hotplug(); | ||
387 | } | 482 | } |
388 | 483 | ||
389 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
390 | { | 485 | { |
486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
391 | struct acpi_scan_handler *handler = data; | 487 | struct acpi_scan_handler *handler = data; |
392 | struct acpi_device *adev; | 488 | struct acpi_device *adev; |
393 | acpi_status status; | 489 | acpi_status status; |
394 | 490 | ||
395 | if (!handler->hotplug.enabled) | 491 | if (acpi_bus_get_device(handle, &adev)) |
396 | return acpi_hotplug_unsupported(handle, type); | 492 | goto err_out; |
397 | 493 | ||
398 | switch (type) { | 494 | switch (type) { |
399 | case ACPI_NOTIFY_BUS_CHECK: | 495 | case ACPI_NOTIFY_BUS_CHECK: |
@@ -404,27 +500,27 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
404 | break; | 500 | break; |
405 | case ACPI_NOTIFY_EJECT_REQUEST: | 501 | case ACPI_NOTIFY_EJECT_REQUEST: |
406 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 502 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
407 | if (acpi_bus_get_device(handle, &adev)) | 503 | if (!handler->hotplug.enabled) { |
504 | acpi_handle_err(handle, "Eject disabled\n"); | ||
505 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
408 | goto err_out; | 506 | goto err_out; |
409 | 507 | } | |
410 | get_device(&adev->dev); | 508 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
411 | status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); | 509 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
412 | if (ACPI_SUCCESS(status)) | 510 | break; |
413 | return; | ||
414 | |||
415 | put_device(&adev->dev); | ||
416 | goto err_out; | ||
417 | default: | 511 | default: |
418 | /* non-hotplug event; possibly handled by other handler */ | 512 | /* non-hotplug event; possibly handled by other handler */ |
419 | return; | 513 | return; |
420 | } | 514 | } |
421 | status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); | 515 | get_device(&adev->dev); |
516 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
422 | if (ACPI_SUCCESS(status)) | 517 | if (ACPI_SUCCESS(status)) |
423 | return; | 518 | return; |
424 | 519 | ||
520 | put_device(&adev->dev); | ||
521 | |||
425 | err_out: | 522 | err_out: |
426 | acpi_evaluate_hotplug_ost(handle, type, | 523 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); |
427 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | ||
428 | } | 524 | } |
429 | 525 | ||
430 | static ssize_t real_power_state_show(struct device *dev, | 526 | static ssize_t real_power_state_show(struct device *dev, |
@@ -475,7 +571,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
475 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 571 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
476 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 572 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
477 | get_device(&acpi_device->dev); | 573 | get_device(&acpi_device->dev); |
478 | status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, | 574 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, |
479 | ACPI_OST_EC_OSPM_EJECT); | 575 | ACPI_OST_EC_OSPM_EJECT); |
480 | if (ACPI_SUCCESS(status)) | 576 | if (ACPI_SUCCESS(status)) |
481 | return count; | 577 | return count; |
@@ -567,6 +663,20 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr, | |||
567 | } | 663 | } |
568 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); | 664 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); |
569 | 665 | ||
666 | static ssize_t status_show(struct device *dev, struct device_attribute *attr, | ||
667 | char *buf) { | ||
668 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
669 | acpi_status status; | ||
670 | unsigned long long sta; | ||
671 | |||
672 | status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta); | ||
673 | if (ACPI_FAILURE(status)) | ||
674 | return -ENODEV; | ||
675 | |||
676 | return sprintf(buf, "%llu\n", sta); | ||
677 | } | ||
678 | static DEVICE_ATTR_RO(status); | ||
679 | |||
570 | static int acpi_device_setup_files(struct acpi_device *dev) | 680 | static int acpi_device_setup_files(struct acpi_device *dev) |
571 | { | 681 | { |
572 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 682 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
@@ -622,6 +732,12 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
622 | dev->pnp.sun = (unsigned long)-1; | 732 | dev->pnp.sun = (unsigned long)-1; |
623 | } | 733 | } |
624 | 734 | ||
735 | if (acpi_has_method(dev->handle, "_STA")) { | ||
736 | result = device_create_file(&dev->dev, &dev_attr_status); | ||
737 | if (result) | ||
738 | goto end; | ||
739 | } | ||
740 | |||
625 | /* | 741 | /* |
626 | * If device has _EJ0, 'eject' file is created that is used to trigger | 742 | * If device has _EJ0, 'eject' file is created that is used to trigger |
627 | * hot-removal function from userland. | 743 | * hot-removal function from userland. |
@@ -677,6 +793,8 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
677 | device_remove_file(&dev->dev, &dev_attr_adr); | 793 | device_remove_file(&dev->dev, &dev_attr_adr); |
678 | device_remove_file(&dev->dev, &dev_attr_modalias); | 794 | device_remove_file(&dev->dev, &dev_attr_modalias); |
679 | device_remove_file(&dev->dev, &dev_attr_hid); | 795 | device_remove_file(&dev->dev, &dev_attr_hid); |
796 | if (acpi_has_method(dev->handle, "_STA")) | ||
797 | device_remove_file(&dev->dev, &dev_attr_status); | ||
680 | if (dev->handle) | 798 | if (dev->handle) |
681 | device_remove_file(&dev->dev, &dev_attr_path); | 799 | device_remove_file(&dev->dev, &dev_attr_path); |
682 | } | 800 | } |
@@ -782,8 +900,8 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
782 | return -ENOMEM; | 900 | return -ENOMEM; |
783 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 901 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], |
784 | sizeof(env->buf) - env->buflen); | 902 | sizeof(env->buf) - env->buflen); |
785 | if (len >= (sizeof(env->buf) - env->buflen)) | 903 | if (len <= 0) |
786 | return -ENOMEM; | 904 | return len; |
787 | env->buflen += len; | 905 | env->buflen += len; |
788 | return 0; | 906 | return 0; |
789 | } | 907 | } |
@@ -907,9 +1025,91 @@ struct bus_type acpi_bus_type = { | |||
907 | .uevent = acpi_device_uevent, | 1025 | .uevent = acpi_device_uevent, |
908 | }; | 1026 | }; |
909 | 1027 | ||
910 | static void acpi_bus_data_handler(acpi_handle handle, void *context) | 1028 | static void acpi_device_del(struct acpi_device *device) |
1029 | { | ||
1030 | mutex_lock(&acpi_device_lock); | ||
1031 | if (device->parent) | ||
1032 | list_del(&device->node); | ||
1033 | |||
1034 | list_del(&device->wakeup_list); | ||
1035 | mutex_unlock(&acpi_device_lock); | ||
1036 | |||
1037 | acpi_power_add_remove_device(device, false); | ||
1038 | acpi_device_remove_files(device); | ||
1039 | if (device->remove) | ||
1040 | device->remove(device); | ||
1041 | |||
1042 | device_del(&device->dev); | ||
1043 | } | ||
1044 | |||
1045 | static LIST_HEAD(acpi_device_del_list); | ||
1046 | static DEFINE_MUTEX(acpi_device_del_lock); | ||
1047 | |||
1048 | static void acpi_device_del_work_fn(struct work_struct *work_not_used) | ||
1049 | { | ||
1050 | for (;;) { | ||
1051 | struct acpi_device *adev; | ||
1052 | |||
1053 | mutex_lock(&acpi_device_del_lock); | ||
1054 | |||
1055 | if (list_empty(&acpi_device_del_list)) { | ||
1056 | mutex_unlock(&acpi_device_del_lock); | ||
1057 | break; | ||
1058 | } | ||
1059 | adev = list_first_entry(&acpi_device_del_list, | ||
1060 | struct acpi_device, del_list); | ||
1061 | list_del(&adev->del_list); | ||
1062 | |||
1063 | mutex_unlock(&acpi_device_del_lock); | ||
1064 | |||
1065 | acpi_device_del(adev); | ||
1066 | /* | ||
1067 | * Drop references to all power resources that might have been | ||
1068 | * used by the device. | ||
1069 | */ | ||
1070 | acpi_power_transition(adev, ACPI_STATE_D3_COLD); | ||
1071 | put_device(&adev->dev); | ||
1072 | } | ||
1073 | } | ||
1074 | |||
1075 | /** | ||
1076 | * acpi_scan_drop_device - Drop an ACPI device object. | ||
1077 | * @handle: Handle of an ACPI namespace node, not used. | ||
1078 | * @context: Address of the ACPI device object to drop. | ||
1079 | * | ||
1080 | * This is invoked by acpi_ns_delete_node() during the removal of the ACPI | ||
1081 | * namespace node the device object pointed to by @context is attached to. | ||
1082 | * | ||
1083 | * The unregistration is carried out asynchronously to avoid running | ||
1084 | * acpi_device_del() under the ACPICA's namespace mutex and the list is used to | ||
1085 | * ensure the correct ordering (the device objects must be unregistered in the | ||
1086 | * same order in which the corresponding namespace nodes are deleted). | ||
1087 | */ | ||
1088 | static void acpi_scan_drop_device(acpi_handle handle, void *context) | ||
911 | { | 1089 | { |
912 | /* Intentionally empty. */ | 1090 | static DECLARE_WORK(work, acpi_device_del_work_fn); |
1091 | struct acpi_device *adev = context; | ||
1092 | |||
1093 | mutex_lock(&acpi_device_del_lock); | ||
1094 | |||
1095 | /* | ||
1096 | * Use the ACPI hotplug workqueue which is ordered, so this work item | ||
1097 | * won't run after any hotplug work items submitted subsequently. That | ||
1098 | * prevents attempts to register device objects identical to those being | ||
1099 | * deleted from happening concurrently (such attempts result from | ||
1100 | * hotplug events handled via the ACPI hotplug workqueue). It also will | ||
1101 | * run after all of the work items submitted previosuly, which helps | ||
1102 | * those work items to ensure that they are not accessing stale device | ||
1103 | * objects. | ||
1104 | */ | ||
1105 | if (list_empty(&acpi_device_del_list)) | ||
1106 | acpi_queue_hotplug_work(&work); | ||
1107 | |||
1108 | list_add_tail(&adev->del_list, &acpi_device_del_list); | ||
1109 | /* Make acpi_ns_validate_handle() return NULL for this handle. */ | ||
1110 | adev->handle = INVALID_ACPI_HANDLE; | ||
1111 | |||
1112 | mutex_unlock(&acpi_device_del_lock); | ||
913 | } | 1113 | } |
914 | 1114 | ||
915 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 1115 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) |
@@ -919,7 +1119,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | |||
919 | if (!device) | 1119 | if (!device) |
920 | return -EINVAL; | 1120 | return -EINVAL; |
921 | 1121 | ||
922 | status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); | 1122 | status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); |
923 | if (ACPI_FAILURE(status) || !*device) { | 1123 | if (ACPI_FAILURE(status) || !*device) { |
924 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 1124 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
925 | handle)); | 1125 | handle)); |
@@ -939,7 +1139,7 @@ int acpi_device_add(struct acpi_device *device, | |||
939 | if (device->handle) { | 1139 | if (device->handle) { |
940 | acpi_status status; | 1140 | acpi_status status; |
941 | 1141 | ||
942 | status = acpi_attach_data(device->handle, acpi_bus_data_handler, | 1142 | status = acpi_attach_data(device->handle, acpi_scan_drop_device, |
943 | device); | 1143 | device); |
944 | if (ACPI_FAILURE(status)) { | 1144 | if (ACPI_FAILURE(status)) { |
945 | acpi_handle_err(device->handle, | 1145 | acpi_handle_err(device->handle, |
@@ -957,6 +1157,7 @@ int acpi_device_add(struct acpi_device *device, | |||
957 | INIT_LIST_HEAD(&device->node); | 1157 | INIT_LIST_HEAD(&device->node); |
958 | INIT_LIST_HEAD(&device->wakeup_list); | 1158 | INIT_LIST_HEAD(&device->wakeup_list); |
959 | INIT_LIST_HEAD(&device->physical_node_list); | 1159 | INIT_LIST_HEAD(&device->physical_node_list); |
1160 | INIT_LIST_HEAD(&device->del_list); | ||
960 | mutex_init(&device->physical_node_lock); | 1161 | mutex_init(&device->physical_node_lock); |
961 | 1162 | ||
962 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 1163 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
@@ -1020,37 +1221,10 @@ int acpi_device_add(struct acpi_device *device, | |||
1020 | mutex_unlock(&acpi_device_lock); | 1221 | mutex_unlock(&acpi_device_lock); |
1021 | 1222 | ||
1022 | err_detach: | 1223 | err_detach: |
1023 | acpi_detach_data(device->handle, acpi_bus_data_handler); | 1224 | acpi_detach_data(device->handle, acpi_scan_drop_device); |
1024 | return result; | 1225 | return result; |
1025 | } | 1226 | } |
1026 | 1227 | ||
1027 | static void acpi_device_unregister(struct acpi_device *device) | ||
1028 | { | ||
1029 | mutex_lock(&acpi_device_lock); | ||
1030 | if (device->parent) | ||
1031 | list_del(&device->node); | ||
1032 | |||
1033 | list_del(&device->wakeup_list); | ||
1034 | mutex_unlock(&acpi_device_lock); | ||
1035 | |||
1036 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
1037 | |||
1038 | acpi_power_add_remove_device(device, false); | ||
1039 | acpi_device_remove_files(device); | ||
1040 | if (device->remove) | ||
1041 | device->remove(device); | ||
1042 | |||
1043 | device_del(&device->dev); | ||
1044 | /* | ||
1045 | * Transition the device to D3cold to drop the reference counts of all | ||
1046 | * power resources the device depends on and turn off the ones that have | ||
1047 | * no more references. | ||
1048 | */ | ||
1049 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); | ||
1050 | device->handle = NULL; | ||
1051 | put_device(&device->dev); | ||
1052 | } | ||
1053 | |||
1054 | /* -------------------------------------------------------------------------- | 1228 | /* -------------------------------------------------------------------------- |
1055 | Driver Management | 1229 | Driver Management |
1056 | -------------------------------------------------------------------------- */ | 1230 | -------------------------------------------------------------------------- */ |
@@ -1624,11 +1798,13 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1624 | device->device_type = type; | 1798 | device->device_type = type; |
1625 | device->handle = handle; | 1799 | device->handle = handle; |
1626 | device->parent = acpi_bus_get_parent(handle); | 1800 | device->parent = acpi_bus_get_parent(handle); |
1627 | STRUCT_TO_INT(device->status) = sta; | 1801 | acpi_set_device_status(device, sta); |
1628 | acpi_device_get_busid(device); | 1802 | acpi_device_get_busid(device); |
1629 | acpi_set_pnp_ids(handle, &device->pnp, type); | 1803 | acpi_set_pnp_ids(handle, &device->pnp, type); |
1630 | acpi_bus_get_flags(device); | 1804 | acpi_bus_get_flags(device); |
1631 | device->flags.match_driver = false; | 1805 | device->flags.match_driver = false; |
1806 | device->flags.initialized = true; | ||
1807 | device->flags.visited = false; | ||
1632 | device_initialize(&device->dev); | 1808 | device_initialize(&device->dev); |
1633 | dev_set_uevent_suppress(&device->dev, true); | 1809 | dev_set_uevent_suppress(&device->dev, true); |
1634 | } | 1810 | } |
@@ -1713,6 +1889,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, | |||
1713 | return 0; | 1889 | return 0; |
1714 | } | 1890 | } |
1715 | 1891 | ||
1892 | bool acpi_device_is_present(struct acpi_device *adev) | ||
1893 | { | ||
1894 | if (adev->status.present || adev->status.functional) | ||
1895 | return true; | ||
1896 | |||
1897 | adev->flags.initialized = false; | ||
1898 | return false; | ||
1899 | } | ||
1900 | |||
1716 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, | 1901 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, |
1717 | char *idstr, | 1902 | char *idstr, |
1718 | const struct acpi_device_id **matchid) | 1903 | const struct acpi_device_id **matchid) |
@@ -1772,7 +1957,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) | |||
1772 | */ | 1957 | */ |
1773 | list_for_each_entry(hwid, &pnp.ids, list) { | 1958 | list_for_each_entry(hwid, &pnp.ids, list) { |
1774 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1959 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1775 | if (handler && !handler->hotplug.ignore) { | 1960 | if (handler) { |
1776 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1961 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1777 | acpi_hotplug_notify_cb, handler); | 1962 | acpi_hotplug_notify_cb, handler); |
1778 | break; | 1963 | break; |
@@ -1806,18 +1991,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1806 | 1991 | ||
1807 | acpi_scan_init_hotplug(handle, type); | 1992 | acpi_scan_init_hotplug(handle, type); |
1808 | 1993 | ||
1809 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && | ||
1810 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { | ||
1811 | struct acpi_device_wakeup wakeup; | ||
1812 | |||
1813 | if (acpi_has_method(handle, "_PRW")) { | ||
1814 | acpi_bus_extract_wakeup_device_power_package(handle, | ||
1815 | &wakeup); | ||
1816 | acpi_power_resources_list_free(&wakeup.resources); | ||
1817 | } | ||
1818 | return AE_CTRL_DEPTH; | ||
1819 | } | ||
1820 | |||
1821 | acpi_add_single_object(&device, handle, type, sta); | 1994 | acpi_add_single_object(&device, handle, type, sta); |
1822 | if (!device) | 1995 | if (!device) |
1823 | return AE_CTRL_DEPTH; | 1996 | return AE_CTRL_DEPTH; |
@@ -1852,36 +2025,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
1852 | return ret; | 2025 | return ret; |
1853 | } | 2026 | } |
1854 | 2027 | ||
1855 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | 2028 | static void acpi_bus_attach(struct acpi_device *device) |
1856 | void *not_used, void **ret_not_used) | ||
1857 | { | 2029 | { |
1858 | struct acpi_device *device; | 2030 | struct acpi_device *child; |
1859 | unsigned long long sta_not_used; | ||
1860 | int ret; | 2031 | int ret; |
1861 | 2032 | ||
1862 | /* | 2033 | acpi_bus_get_status(device); |
1863 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating | 2034 | /* Skip devices that are not present. */ |
1864 | * namespace walks prematurely. | 2035 | if (!acpi_device_is_present(device)) { |
1865 | */ | 2036 | device->flags.visited = false; |
1866 | if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) | 2037 | return; |
1867 | return AE_OK; | 2038 | } |
1868 | |||
1869 | if (acpi_bus_get_device(handle, &device)) | ||
1870 | return AE_CTRL_DEPTH; | ||
1871 | |||
1872 | if (device->handler) | 2039 | if (device->handler) |
1873 | return AE_OK; | 2040 | goto ok; |
1874 | 2041 | ||
2042 | if (!device->flags.initialized) { | ||
2043 | acpi_bus_update_power(device, NULL); | ||
2044 | device->flags.initialized = true; | ||
2045 | } | ||
2046 | device->flags.visited = false; | ||
1875 | ret = acpi_scan_attach_handler(device); | 2047 | ret = acpi_scan_attach_handler(device); |
1876 | if (ret < 0) | 2048 | if (ret < 0) |
1877 | return AE_CTRL_DEPTH; | 2049 | return; |
1878 | 2050 | ||
1879 | device->flags.match_driver = true; | 2051 | device->flags.match_driver = true; |
1880 | if (ret > 0) | 2052 | if (!ret) { |
1881 | return AE_OK; | 2053 | ret = device_attach(&device->dev); |
2054 | if (ret < 0) | ||
2055 | return; | ||
2056 | } | ||
2057 | device->flags.visited = true; | ||
1882 | 2058 | ||
1883 | ret = device_attach(&device->dev); | 2059 | ok: |
1884 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; | 2060 | list_for_each_entry(child, &device->children, node) |
2061 | acpi_bus_attach(child); | ||
1885 | } | 2062 | } |
1886 | 2063 | ||
1887 | /** | 2064 | /** |
@@ -1901,75 +2078,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1901 | int acpi_bus_scan(acpi_handle handle) | 2078 | int acpi_bus_scan(acpi_handle handle) |
1902 | { | 2079 | { |
1903 | void *device = NULL; | 2080 | void *device = NULL; |
1904 | int error = 0; | ||
1905 | 2081 | ||
1906 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 2082 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1907 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 2083 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1908 | acpi_bus_check_add, NULL, NULL, &device); | 2084 | acpi_bus_check_add, NULL, NULL, &device); |
1909 | 2085 | ||
1910 | if (!device) | 2086 | if (device) { |
1911 | error = -ENODEV; | 2087 | acpi_bus_attach(device); |
1912 | else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) | 2088 | return 0; |
1913 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
1914 | acpi_bus_device_attach, NULL, NULL, NULL); | ||
1915 | |||
1916 | return error; | ||
1917 | } | ||
1918 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1919 | |||
1920 | static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, | ||
1921 | void *not_used, void **ret_not_used) | ||
1922 | { | ||
1923 | struct acpi_device *device = NULL; | ||
1924 | |||
1925 | if (!acpi_bus_get_device(handle, &device)) { | ||
1926 | struct acpi_scan_handler *dev_handler = device->handler; | ||
1927 | |||
1928 | if (dev_handler) { | ||
1929 | if (dev_handler->detach) | ||
1930 | dev_handler->detach(device); | ||
1931 | |||
1932 | device->handler = NULL; | ||
1933 | } else { | ||
1934 | device_release_driver(&device->dev); | ||
1935 | } | ||
1936 | } | 2089 | } |
1937 | return AE_OK; | 2090 | return -ENODEV; |
1938 | } | ||
1939 | |||
1940 | static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, | ||
1941 | void *not_used, void **ret_not_used) | ||
1942 | { | ||
1943 | struct acpi_device *device = NULL; | ||
1944 | |||
1945 | if (!acpi_bus_get_device(handle, &device)) | ||
1946 | acpi_device_unregister(device); | ||
1947 | |||
1948 | return AE_OK; | ||
1949 | } | 2091 | } |
2092 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1950 | 2093 | ||
1951 | /** | 2094 | /** |
1952 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | 2095 | * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. |
1953 | * @start: Root of the ACPI device nodes subtree to remove. | 2096 | * @adev: Root of the ACPI namespace scope to walk. |
1954 | * | 2097 | * |
1955 | * Must be called under acpi_scan_lock. | 2098 | * Must be called under acpi_scan_lock. |
1956 | */ | 2099 | */ |
1957 | void acpi_bus_trim(struct acpi_device *start) | 2100 | void acpi_bus_trim(struct acpi_device *adev) |
1958 | { | 2101 | { |
2102 | struct acpi_scan_handler *handler = adev->handler; | ||
2103 | struct acpi_device *child; | ||
2104 | |||
2105 | list_for_each_entry_reverse(child, &adev->children, node) | ||
2106 | acpi_bus_trim(child); | ||
2107 | |||
2108 | if (handler) { | ||
2109 | if (handler->detach) | ||
2110 | handler->detach(adev); | ||
2111 | |||
2112 | adev->handler = NULL; | ||
2113 | } else { | ||
2114 | device_release_driver(&adev->dev); | ||
2115 | } | ||
1959 | /* | 2116 | /* |
1960 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 2117 | * Most likely, the device is going away, so put it into D3cold before |
1961 | * all ACPI drivers from the device nodes being removed. | 2118 | * that. |
1962 | */ | ||
1963 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | ||
1964 | acpi_bus_device_detach, NULL, NULL); | ||
1965 | acpi_bus_device_detach(start->handle, 0, NULL, NULL); | ||
1966 | /* | ||
1967 | * Execute acpi_bus_remove() as a post-order callback to remove device | ||
1968 | * nodes in the given namespace scope. | ||
1969 | */ | 2119 | */ |
1970 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | 2120 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); |
1971 | acpi_bus_remove, NULL, NULL); | 2121 | adev->flags.initialized = false; |
1972 | acpi_bus_remove(start->handle, 0, NULL, NULL); | 2122 | adev->flags.visited = false; |
1973 | } | 2123 | } |
1974 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 2124 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1975 | 2125 | ||
@@ -2047,14 +2197,14 @@ int __init acpi_scan_init(void) | |||
2047 | 2197 | ||
2048 | result = acpi_bus_scan_fixed(); | 2198 | result = acpi_bus_scan_fixed(); |
2049 | if (result) { | 2199 | if (result) { |
2050 | acpi_device_unregister(acpi_root); | 2200 | acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); |
2201 | acpi_device_del(acpi_root); | ||
2202 | put_device(&acpi_root->dev); | ||
2051 | goto out; | 2203 | goto out; |
2052 | } | 2204 | } |
2053 | 2205 | ||
2054 | acpi_update_all_gpes(); | 2206 | acpi_update_all_gpes(); |
2055 | 2207 | ||
2056 | acpi_pci_root_hp_init(); | ||
2057 | |||
2058 | out: | 2208 | out: |
2059 | mutex_unlock(&acpi_scan_lock); | 2209 | mutex_unlock(&acpi_scan_lock); |
2060 | return result; | 2210 | return result; |