diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 17:45:04 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-12 17:45:04 -0500 |
commit | 25d412d932fb3289ae5b510845d523330b80bb71 (patch) | |
tree | 7234bf9bf03af4b0f1f40830169cd7219ef586ed /drivers | |
parent | 98feb7cc61c50fe0fa36eeb994d5db527ca9e103 (diff) | |
parent | c713cd7f2d799c50a0721bf51d178ea9567215dd (diff) |
Merge branch 'acpi-hotplug'
* acpi-hotplug:
ACPI / scan: ACPI device object sysfs attribute for _STA evaluation
ACPI / hotplug / driver core: Handle containers in a special way
ACPI / hotplug: Add demand_offline hotplug profile flag
ACPI / bind: Move acpi_get_child() to drivers/ide/ide-acpi.c
ACPI / bind: Pass struct acpi_device pointer to acpi_bind_one()
ACPI / bind: Rework struct acpi_bus_type
ACPI / bind: Redefine acpi_preset_companion()
ACPI / bind: Redefine acpi_get_child()
PCI / ACPI: Use acpi_find_child_device() for child devices lookup
ACPI / bind: Simplify child device lookups
ACPI / scan: Use direct recurrence for device hierarchy walks
ACPI: Introduce acpi_set_device_status()
ACPI / hotplug: Drop unfinished global notification handling routines
ACPI / hotplug: Rework generic code to handle suprise removals
ACPI / hotplug: Move container-specific code out of the core
ACPI / hotplug: Make ACPI PCI root hotplug use common hotplug code
ACPI / hotplug: Introduce common hotplug function acpi_device_hotplug()
ACPI / hotplug: Do not fail bus and device checks for disabled hotplug
ACPI / scan: Add acpi_device objects for all device nodes in the namespace
ACPI / scan: Define non-empty device removal handler
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/acpi_memhotplug.c | 15 | ||||
-rw-r--r-- | drivers/acpi/acpi_processor.c | 2 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 75 | ||||
-rw-r--r-- | drivers/acpi/container.c | 55 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 22 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 9 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 165 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 10 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 6 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 122 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 547 | ||||
-rw-r--r-- | drivers/ata/libata-acpi.c | 26 | ||||
-rw-r--r-- | drivers/base/Makefile | 2 | ||||
-rw-r--r-- | drivers/base/base.h | 1 | ||||
-rw-r--r-- | drivers/base/container.c | 44 | ||||
-rw-r--r-- | drivers/base/init.c | 1 | ||||
-rw-r--r-- | drivers/ide/ide-acpi.c | 11 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_bus.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 14 | ||||
-rw-r--r-- | drivers/pnp/pnpacpi/core.c | 21 | ||||
-rw-r--r-- | drivers/usb/core/usb-acpi.c | 40 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-cpuhotplug.c | 8 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-memhotplug.c | 7 |
24 files changed, 602 insertions, 605 deletions
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 551dad712ffe..9aeacdfca410 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -180,14 +180,14 @@ static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info) | |||
180 | 180 | ||
181 | static int acpi_bind_memblk(struct memory_block *mem, void *arg) | 181 | static int acpi_bind_memblk(struct memory_block *mem, void *arg) |
182 | { | 182 | { |
183 | return acpi_bind_one(&mem->dev, (acpi_handle)arg); | 183 | return acpi_bind_one(&mem->dev, arg); |
184 | } | 184 | } |
185 | 185 | ||
186 | static int acpi_bind_memory_blocks(struct acpi_memory_info *info, | 186 | static int acpi_bind_memory_blocks(struct acpi_memory_info *info, |
187 | acpi_handle handle) | 187 | struct acpi_device *adev) |
188 | { | 188 | { |
189 | return walk_memory_range(acpi_meminfo_start_pfn(info), | 189 | return walk_memory_range(acpi_meminfo_start_pfn(info), |
190 | acpi_meminfo_end_pfn(info), (void *)handle, | 190 | acpi_meminfo_end_pfn(info), adev, |
191 | acpi_bind_memblk); | 191 | acpi_bind_memblk); |
192 | } | 192 | } |
193 | 193 | ||
@@ -197,8 +197,7 @@ static int acpi_unbind_memblk(struct memory_block *mem, void *arg) | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void acpi_unbind_memory_blocks(struct acpi_memory_info *info, | 200 | static void acpi_unbind_memory_blocks(struct acpi_memory_info *info) |
201 | acpi_handle handle) | ||
202 | { | 201 | { |
203 | walk_memory_range(acpi_meminfo_start_pfn(info), | 202 | walk_memory_range(acpi_meminfo_start_pfn(info), |
204 | acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk); | 203 | acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk); |
@@ -242,9 +241,9 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) | |||
242 | if (result && result != -EEXIST) | 241 | if (result && result != -EEXIST) |
243 | continue; | 242 | continue; |
244 | 243 | ||
245 | result = acpi_bind_memory_blocks(info, handle); | 244 | result = acpi_bind_memory_blocks(info, mem_device->device); |
246 | if (result) { | 245 | if (result) { |
247 | acpi_unbind_memory_blocks(info, handle); | 246 | acpi_unbind_memory_blocks(info); |
248 | return -ENODEV; | 247 | return -ENODEV; |
249 | } | 248 | } |
250 | 249 | ||
@@ -285,7 +284,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device) | |||
285 | if (nid == NUMA_NO_NODE) | 284 | if (nid == NUMA_NO_NODE) |
286 | nid = memory_add_physaddr_to_nid(info->start_addr); | 285 | nid = memory_add_physaddr_to_nid(info->start_addr); |
287 | 286 | ||
288 | acpi_unbind_memory_blocks(info, handle); | 287 | acpi_unbind_memory_blocks(info); |
289 | remove_memory(nid, info->start_addr, info->length); | 288 | remove_memory(nid, info->start_addr, info->length); |
290 | list_del(&info->list); | 289 | list_del(&info->list); |
291 | kfree(info); | 290 | kfree(info); |
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 3c1d6b0c09a4..d58a2aba0930 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c | |||
@@ -395,7 +395,7 @@ static int acpi_processor_add(struct acpi_device *device, | |||
395 | goto err; | 395 | goto err; |
396 | } | 396 | } |
397 | 397 | ||
398 | result = acpi_bind_one(dev, pr->handle); | 398 | result = acpi_bind_one(dev, device); |
399 | if (result) | 399 | if (result) |
400 | goto err; | 400 | goto err; |
401 | 401 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 1d8c2bb905fe..384da5ab5955 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -50,9 +50,6 @@ struct acpi_device *acpi_root; | |||
50 | struct proc_dir_entry *acpi_root_dir; | 50 | struct proc_dir_entry *acpi_root_dir; |
51 | EXPORT_SYMBOL(acpi_root_dir); | 51 | EXPORT_SYMBOL(acpi_root_dir); |
52 | 52 | ||
53 | #define STRUCT_TO_INT(s) (*((int*)&s)) | ||
54 | |||
55 | |||
56 | #ifdef CONFIG_X86 | 53 | #ifdef CONFIG_X86 |
57 | static int set_copy_dsdt(const struct dmi_system_id *id) | 54 | static int set_copy_dsdt(const struct dmi_system_id *id) |
58 | { | 55 | { |
@@ -113,18 +110,16 @@ int acpi_bus_get_status(struct acpi_device *device) | |||
113 | if (ACPI_FAILURE(status)) | 110 | if (ACPI_FAILURE(status)) |
114 | return -ENODEV; | 111 | return -ENODEV; |
115 | 112 | ||
116 | STRUCT_TO_INT(device->status) = (int) sta; | 113 | acpi_set_device_status(device, sta); |
117 | 114 | ||
118 | if (device->status.functional && !device->status.present) { | 115 | if (device->status.functional && !device->status.present) { |
119 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " | 116 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: " |
120 | "functional but not present;\n", | 117 | "functional but not present;\n", |
121 | device->pnp.bus_id, | 118 | device->pnp.bus_id, (u32)sta)); |
122 | (u32) STRUCT_TO_INT(device->status))); | ||
123 | } | 119 | } |
124 | 120 | ||
125 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", | 121 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", |
126 | device->pnp.bus_id, | 122 | device->pnp.bus_id, (u32)sta)); |
127 | (u32) STRUCT_TO_INT(device->status))); | ||
128 | return 0; | 123 | return 0; |
129 | } | 124 | } |
130 | EXPORT_SYMBOL(acpi_bus_get_status); | 125 | EXPORT_SYMBOL(acpi_bus_get_status); |
@@ -337,58 +332,6 @@ static void acpi_bus_osc_support(void) | |||
337 | Notification Handling | 332 | Notification Handling |
338 | -------------------------------------------------------------------------- */ | 333 | -------------------------------------------------------------------------- */ |
339 | 334 | ||
340 | static void acpi_bus_check_device(acpi_handle handle) | ||
341 | { | ||
342 | struct acpi_device *device; | ||
343 | acpi_status status; | ||
344 | struct acpi_device_status old_status; | ||
345 | |||
346 | if (acpi_bus_get_device(handle, &device)) | ||
347 | return; | ||
348 | if (!device) | ||
349 | return; | ||
350 | |||
351 | old_status = device->status; | ||
352 | |||
353 | /* | ||
354 | * Make sure this device's parent is present before we go about | ||
355 | * messing with the device. | ||
356 | */ | ||
357 | if (device->parent && !device->parent->status.present) { | ||
358 | device->status = device->parent->status; | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | status = acpi_bus_get_status(device); | ||
363 | if (ACPI_FAILURE(status)) | ||
364 | return; | ||
365 | |||
366 | if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status)) | ||
367 | return; | ||
368 | |||
369 | /* | ||
370 | * Device Insertion/Removal | ||
371 | */ | ||
372 | if ((device->status.present) && !(old_status.present)) { | ||
373 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n")); | ||
374 | /* TBD: Handle device insertion */ | ||
375 | } else if (!(device->status.present) && (old_status.present)) { | ||
376 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n")); | ||
377 | /* TBD: Handle device removal */ | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void acpi_bus_check_scope(acpi_handle handle) | ||
382 | { | ||
383 | /* Status Change? */ | ||
384 | acpi_bus_check_device(handle); | ||
385 | |||
386 | /* | ||
387 | * TBD: Enumerate child devices within this device's scope and | ||
388 | * run acpi_bus_check_device()'s on them. | ||
389 | */ | ||
390 | } | ||
391 | |||
392 | /** | 335 | /** |
393 | * acpi_bus_notify | 336 | * acpi_bus_notify |
394 | * --------------- | 337 | * --------------- |
@@ -405,19 +348,11 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
405 | switch (type) { | 348 | switch (type) { |
406 | 349 | ||
407 | case ACPI_NOTIFY_BUS_CHECK: | 350 | case ACPI_NOTIFY_BUS_CHECK: |
408 | acpi_bus_check_scope(handle); | 351 | /* TBD */ |
409 | /* | ||
410 | * TBD: We'll need to outsource certain events to non-ACPI | ||
411 | * drivers via the device manager (device.c). | ||
412 | */ | ||
413 | break; | 352 | break; |
414 | 353 | ||
415 | case ACPI_NOTIFY_DEVICE_CHECK: | 354 | case ACPI_NOTIFY_DEVICE_CHECK: |
416 | acpi_bus_check_device(handle); | 355 | /* TBD */ |
417 | /* | ||
418 | * TBD: We'll need to outsource certain events to non-ACPI | ||
419 | * drivers via the device manager (device.c). | ||
420 | */ | ||
421 | break; | 356 | break; |
422 | 357 | ||
423 | case ACPI_NOTIFY_DEVICE_WAKE: | 358 | case ACPI_NOTIFY_DEVICE_WAKE: |
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index e23151667655..0b6ae6eb5c4a 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -27,8 +27,7 @@ | |||
27 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 27 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
28 | */ | 28 | */ |
29 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
30 | 30 | #include <linux/container.h> | |
31 | #include "internal.h" | ||
32 | 31 | ||
33 | #include "internal.h" | 32 | #include "internal.h" |
34 | 33 | ||
@@ -44,19 +43,65 @@ static const struct acpi_device_id container_device_ids[] = { | |||
44 | {"", 0}, | 43 | {"", 0}, |
45 | }; | 44 | }; |
46 | 45 | ||
47 | static int container_device_attach(struct acpi_device *device, | 46 | static int acpi_container_offline(struct container_dev *cdev) |
47 | { | ||
48 | struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); | ||
49 | struct acpi_device *child; | ||
50 | |||
51 | /* Check all of the dependent devices' physical companions. */ | ||
52 | list_for_each_entry(child, &adev->children, node) | ||
53 | if (!acpi_scan_is_offline(child, false)) | ||
54 | return -EBUSY; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static void acpi_container_release(struct device *dev) | ||
60 | { | ||
61 | kfree(to_container_dev(dev)); | ||
62 | } | ||
63 | |||
64 | static int container_device_attach(struct acpi_device *adev, | ||
48 | const struct acpi_device_id *not_used) | 65 | const struct acpi_device_id *not_used) |
49 | { | 66 | { |
50 | /* This is necessary for container hotplug to work. */ | 67 | struct container_dev *cdev; |
68 | struct device *dev; | ||
69 | int ret; | ||
70 | |||
71 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); | ||
72 | if (!cdev) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | cdev->offline = acpi_container_offline; | ||
76 | dev = &cdev->dev; | ||
77 | dev->bus = &container_subsys; | ||
78 | dev_set_name(dev, "%s", dev_name(&adev->dev)); | ||
79 | ACPI_COMPANION_SET(dev, adev); | ||
80 | dev->release = acpi_container_release; | ||
81 | ret = device_register(dev); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | |||
85 | adev->driver_data = dev; | ||
51 | return 1; | 86 | return 1; |
52 | } | 87 | } |
53 | 88 | ||
89 | static void container_device_detach(struct acpi_device *adev) | ||
90 | { | ||
91 | struct device *dev = acpi_driver_data(adev); | ||
92 | |||
93 | adev->driver_data = NULL; | ||
94 | if (dev) | ||
95 | device_unregister(dev); | ||
96 | } | ||
97 | |||
54 | static struct acpi_scan_handler container_handler = { | 98 | static struct acpi_scan_handler container_handler = { |
55 | .ids = container_device_ids, | 99 | .ids = container_device_ids, |
56 | .attach = container_device_attach, | 100 | .attach = container_device_attach, |
101 | .detach = container_device_detach, | ||
57 | .hotplug = { | 102 | .hotplug = { |
58 | .enabled = true, | 103 | .enabled = true, |
59 | .mode = AHM_CONTAINER, | 104 | .demand_offline = true, |
60 | }, | 105 | }, |
61 | }; | 106 | }; |
62 | 107 | ||
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 | ||
305 | int acpi_bus_update_power(acpi_handle handle, int *state_p) | 307 | int 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 | |||
347 | int 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 | } | ||
341 | EXPORT_SYMBOL_GPL(acpi_bus_update_power); | 355 | EXPORT_SYMBOL_GPL(acpi_bus_update_power); |
342 | 356 | ||
343 | bool acpi_bus_power_manageable(acpi_handle handle) | 357 | bool acpi_bus_power_manageable(acpi_handle handle) |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 38c2e325f325..c431c88faaff 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 | */ |
324 | static void dock_create_acpi_device(acpi_handle handle) | 324 | static 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/glue.c b/drivers/acpi/glue.c index a22a295edb69..0c789224d40d 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -37,7 +37,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type) | |||
37 | { | 37 | { |
38 | if (acpi_disabled) | 38 | if (acpi_disabled) |
39 | return -ENODEV; | 39 | return -ENODEV; |
40 | if (type && type->match && type->find_device) { | 40 | if (type && type->match && type->find_companion) { |
41 | down_write(&bus_type_sem); | 41 | down_write(&bus_type_sem); |
42 | list_add_tail(&type->list, &bus_type_list); | 42 | list_add_tail(&type->list, &bus_type_list); |
43 | up_write(&bus_type_sem); | 43 | up_write(&bus_type_sem); |
@@ -82,109 +82,74 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) | |||
82 | #define FIND_CHILD_MIN_SCORE 1 | 82 | #define FIND_CHILD_MIN_SCORE 1 |
83 | #define FIND_CHILD_MAX_SCORE 2 | 83 | #define FIND_CHILD_MAX_SCORE 2 |
84 | 84 | ||
85 | static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, | 85 | static int find_child_checks(struct acpi_device *adev, bool check_children) |
86 | void *not_used, void **ret_p) | ||
87 | { | ||
88 | struct acpi_device *adev = NULL; | ||
89 | |||
90 | acpi_bus_get_device(handle, &adev); | ||
91 | if (adev) { | ||
92 | *ret_p = handle; | ||
93 | return AE_CTRL_TERMINATE; | ||
94 | } | ||
95 | return AE_OK; | ||
96 | } | ||
97 | |||
98 | static int do_find_child_checks(acpi_handle handle, bool is_bridge) | ||
99 | { | 86 | { |
100 | bool sta_present = true; | 87 | bool sta_present = true; |
101 | unsigned long long sta; | 88 | unsigned long long sta; |
102 | acpi_status status; | 89 | acpi_status status; |
103 | 90 | ||
104 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 91 | status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); |
105 | if (status == AE_NOT_FOUND) | 92 | if (status == AE_NOT_FOUND) |
106 | sta_present = false; | 93 | sta_present = false; |
107 | else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) | 94 | else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) |
108 | return -ENODEV; | 95 | return -ENODEV; |
109 | 96 | ||
110 | if (is_bridge) { | 97 | if (check_children && list_empty(&adev->children)) |
111 | void *test = NULL; | 98 | return -ENODEV; |
112 | 99 | ||
113 | /* Check if this object has at least one child device. */ | ||
114 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
115 | acpi_dev_present, NULL, NULL, &test); | ||
116 | if (!test) | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; | 100 | return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; |
120 | } | 101 | } |
121 | 102 | ||
122 | struct find_child_context { | 103 | struct acpi_device *acpi_find_child_device(struct acpi_device *parent, |
123 | u64 addr; | 104 | u64 address, bool check_children) |
124 | bool is_bridge; | ||
125 | acpi_handle ret; | ||
126 | int ret_score; | ||
127 | }; | ||
128 | |||
129 | static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, | ||
130 | void *data, void **not_used) | ||
131 | { | ||
132 | struct find_child_context *context = data; | ||
133 | unsigned long long addr; | ||
134 | acpi_status status; | ||
135 | int score; | ||
136 | |||
137 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); | ||
138 | if (ACPI_FAILURE(status) || addr != context->addr) | ||
139 | return AE_OK; | ||
140 | |||
141 | if (!context->ret) { | ||
142 | /* This is the first matching object. Save its handle. */ | ||
143 | context->ret = handle; | ||
144 | return AE_OK; | ||
145 | } | ||
146 | /* | ||
147 | * There is more than one matching object with the same _ADR value. | ||
148 | * That really is unexpected, so we are kind of beyond the scope of the | ||
149 | * spec here. We have to choose which one to return, though. | ||
150 | * | ||
151 | * First, check if the previously found object is good enough and return | ||
152 | * its handle if so. Second, check the same for the object that we've | ||
153 | * just found. | ||
154 | */ | ||
155 | if (!context->ret_score) { | ||
156 | score = do_find_child_checks(context->ret, context->is_bridge); | ||
157 | if (score == FIND_CHILD_MAX_SCORE) | ||
158 | return AE_CTRL_TERMINATE; | ||
159 | else | ||
160 | context->ret_score = score; | ||
161 | } | ||
162 | score = do_find_child_checks(handle, context->is_bridge); | ||
163 | if (score == FIND_CHILD_MAX_SCORE) { | ||
164 | context->ret = handle; | ||
165 | return AE_CTRL_TERMINATE; | ||
166 | } else if (score > context->ret_score) { | ||
167 | context->ret = handle; | ||
168 | context->ret_score = score; | ||
169 | } | ||
170 | return AE_OK; | ||
171 | } | ||
172 | |||
173 | acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge) | ||
174 | { | 105 | { |
175 | if (parent) { | 106 | struct acpi_device *adev, *ret = NULL; |
176 | struct find_child_context context = { | 107 | int ret_score = 0; |
177 | .addr = addr, | 108 | |
178 | .is_bridge = is_bridge, | 109 | if (!parent) |
179 | }; | 110 | return NULL; |
180 | 111 | ||
181 | acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child, | 112 | list_for_each_entry(adev, &parent->children, node) { |
182 | NULL, &context, NULL); | 113 | unsigned long long addr; |
183 | return context.ret; | 114 | acpi_status status; |
115 | int score; | ||
116 | |||
117 | status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR, | ||
118 | NULL, &addr); | ||
119 | if (ACPI_FAILURE(status) || addr != address) | ||
120 | continue; | ||
121 | |||
122 | if (!ret) { | ||
123 | /* This is the first matching object. Save it. */ | ||
124 | ret = adev; | ||
125 | continue; | ||
126 | } | ||
127 | /* | ||
128 | * There is more than one matching device object with the same | ||
129 | * _ADR value. That really is unexpected, so we are kind of | ||
130 | * beyond the scope of the spec here. We have to choose which | ||
131 | * one to return, though. | ||
132 | * | ||
133 | * First, check if the previously found object is good enough | ||
134 | * and return it if so. Second, do the same for the object that | ||
135 | * we've just found. | ||
136 | */ | ||
137 | if (!ret_score) { | ||
138 | ret_score = find_child_checks(ret, check_children); | ||
139 | if (ret_score == FIND_CHILD_MAX_SCORE) | ||
140 | return ret; | ||
141 | } | ||
142 | score = find_child_checks(adev, check_children); | ||
143 | if (score == FIND_CHILD_MAX_SCORE) { | ||
144 | return adev; | ||
145 | } else if (score > ret_score) { | ||
146 | ret = adev; | ||
147 | ret_score = score; | ||
148 | } | ||
184 | } | 149 | } |
185 | return NULL; | 150 | return ret; |
186 | } | 151 | } |
187 | EXPORT_SYMBOL_GPL(acpi_find_child); | 152 | EXPORT_SYMBOL_GPL(acpi_find_child_device); |
188 | 153 | ||
189 | static void acpi_physnode_link_name(char *buf, unsigned int node_id) | 154 | static void acpi_physnode_link_name(char *buf, unsigned int node_id) |
190 | { | 155 | { |
@@ -195,9 +160,8 @@ static void acpi_physnode_link_name(char *buf, unsigned int node_id) | |||
195 | strcpy(buf, PHYSICAL_NODE_STRING); | 160 | strcpy(buf, PHYSICAL_NODE_STRING); |
196 | } | 161 | } |
197 | 162 | ||
198 | int acpi_bind_one(struct device *dev, acpi_handle handle) | 163 | int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev) |
199 | { | 164 | { |
200 | struct acpi_device *acpi_dev = NULL; | ||
201 | struct acpi_device_physical_node *physical_node, *pn; | 165 | struct acpi_device_physical_node *physical_node, *pn; |
202 | char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; | 166 | char physical_node_name[PHYSICAL_NODE_NAME_SIZE]; |
203 | struct list_head *physnode_list; | 167 | struct list_head *physnode_list; |
@@ -205,14 +169,12 @@ int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
205 | int retval = -EINVAL; | 169 | int retval = -EINVAL; |
206 | 170 | ||
207 | if (ACPI_COMPANION(dev)) { | 171 | if (ACPI_COMPANION(dev)) { |
208 | if (handle) { | 172 | if (acpi_dev) { |
209 | dev_warn(dev, "ACPI companion already set\n"); | 173 | dev_warn(dev, "ACPI companion already set\n"); |
210 | return -EINVAL; | 174 | return -EINVAL; |
211 | } else { | 175 | } else { |
212 | acpi_dev = ACPI_COMPANION(dev); | 176 | acpi_dev = ACPI_COMPANION(dev); |
213 | } | 177 | } |
214 | } else { | ||
215 | acpi_bus_get_device(handle, &acpi_dev); | ||
216 | } | 178 | } |
217 | if (!acpi_dev) | 179 | if (!acpi_dev) |
218 | return -EINVAL; | 180 | return -EINVAL; |
@@ -322,29 +284,22 @@ int acpi_unbind_one(struct device *dev) | |||
322 | } | 284 | } |
323 | EXPORT_SYMBOL_GPL(acpi_unbind_one); | 285 | EXPORT_SYMBOL_GPL(acpi_unbind_one); |
324 | 286 | ||
325 | void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr) | ||
326 | { | ||
327 | struct acpi_device *adev; | ||
328 | |||
329 | if (!acpi_bus_get_device(acpi_get_child(parent, addr), &adev)) | ||
330 | ACPI_COMPANION_SET(dev, adev); | ||
331 | } | ||
332 | EXPORT_SYMBOL_GPL(acpi_preset_companion); | ||
333 | |||
334 | static int acpi_platform_notify(struct device *dev) | 287 | static int acpi_platform_notify(struct device *dev) |
335 | { | 288 | { |
336 | struct acpi_bus_type *type = acpi_get_bus_type(dev); | 289 | struct acpi_bus_type *type = acpi_get_bus_type(dev); |
337 | acpi_handle handle; | ||
338 | int ret; | 290 | int ret; |
339 | 291 | ||
340 | ret = acpi_bind_one(dev, NULL); | 292 | ret = acpi_bind_one(dev, NULL); |
341 | if (ret && type) { | 293 | if (ret && type) { |
342 | ret = type->find_device(dev, &handle); | 294 | struct acpi_device *adev; |
343 | if (ret) { | 295 | |
296 | adev = type->find_companion(dev); | ||
297 | if (!adev) { | ||
344 | DBG("Unable to get handle for %s\n", dev_name(dev)); | 298 | DBG("Unable to get handle for %s\n", dev_name(dev)); |
299 | ret = -ENODEV; | ||
345 | goto out; | 300 | goto out; |
346 | } | 301 | } |
347 | ret = acpi_bind_one(dev, handle); | 302 | ret = acpi_bind_one(dev, adev); |
348 | if (ret) | 303 | if (ret) |
349 | goto out; | 304 | goto out; |
350 | } | 305 | } |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8ef9787dead4..dedbb2d802f1 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -28,7 +28,6 @@ int init_acpi_device_notify(void); | |||
28 | int acpi_scan_init(void); | 28 | int acpi_scan_init(void); |
29 | void acpi_pci_root_init(void); | 29 | void acpi_pci_root_init(void); |
30 | void acpi_pci_link_init(void); | 30 | void acpi_pci_link_init(void); |
31 | void acpi_pci_root_hp_init(void); | ||
32 | void acpi_processor_init(void); | 31 | void acpi_processor_init(void); |
33 | void acpi_platform_init(void); | 32 | void acpi_platform_init(void); |
34 | int acpi_sysfs_init(void); | 33 | int acpi_sysfs_init(void); |
@@ -73,6 +72,9 @@ void acpi_lpss_init(void); | |||
73 | static inline void acpi_lpss_init(void) {} | 72 | static inline void acpi_lpss_init(void) {} |
74 | #endif | 73 | #endif |
75 | 74 | ||
75 | bool acpi_queue_hotplug_work(struct work_struct *work); | ||
76 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); | ||
77 | |||
76 | /* -------------------------------------------------------------------------- | 78 | /* -------------------------------------------------------------------------- |
77 | Device Node Initialization / Removal | 79 | Device Node Initialization / Removal |
78 | -------------------------------------------------------------------------- */ | 80 | -------------------------------------------------------------------------- */ |
@@ -85,9 +87,9 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
85 | int type, unsigned long long sta); | 87 | int type, unsigned long long sta); |
86 | void acpi_device_add_finalize(struct acpi_device *device); | 88 | void acpi_device_add_finalize(struct acpi_device *device); |
87 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); | 89 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); |
88 | int acpi_bind_one(struct device *dev, acpi_handle handle); | 90 | int acpi_bind_one(struct device *dev, struct acpi_device *adev); |
89 | int acpi_unbind_one(struct device *dev); | 91 | int acpi_unbind_one(struct device *dev); |
90 | void acpi_bus_device_eject(void *data, u32 ost_src); | 92 | bool acpi_device_is_present(struct acpi_device *adev); |
91 | 93 | ||
92 | /* -------------------------------------------------------------------------- | 94 | /* -------------------------------------------------------------------------- |
93 | Power Resource | 95 | Power Resource |
@@ -105,6 +107,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state); | |||
105 | int acpi_power_on_resources(struct acpi_device *device, int state); | 107 | int acpi_power_on_resources(struct acpi_device *device, int state); |
106 | int acpi_power_transition(struct acpi_device *device, int state); | 108 | int acpi_power_transition(struct acpi_device *device, int state); |
107 | 109 | ||
110 | int acpi_device_update_power(struct acpi_device *device, int *state_p); | ||
111 | |||
108 | int acpi_wakeup_device_init(void); | 112 | int acpi_wakeup_device_init(void); |
109 | void acpi_early_processor_set_pdc(void); | 113 | void acpi_early_processor_set_pdc(void); |
110 | 114 | ||
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7865a8069340..fc1aa7909690 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -1211,6 +1211,10 @@ acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src) | |||
1211 | return AE_OK; | 1211 | return AE_OK; |
1212 | } | 1212 | } |
1213 | 1213 | ||
1214 | bool acpi_queue_hotplug_work(struct work_struct *work) | ||
1215 | { | ||
1216 | return queue_work(kacpi_hotplug_wq, work); | ||
1217 | } | ||
1214 | 1218 | ||
1215 | acpi_status | 1219 | acpi_status |
1216 | acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) | 1220 | acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) |
@@ -1790,7 +1794,7 @@ acpi_status __init acpi_os_initialize1(void) | |||
1790 | { | 1794 | { |
1791 | kacpid_wq = alloc_workqueue("kacpid", 0, 1); | 1795 | kacpid_wq = alloc_workqueue("kacpid", 0, 1); |
1792 | kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); | 1796 | kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); |
1793 | kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1); | 1797 | kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); |
1794 | BUG_ON(!kacpid_wq); | 1798 | BUG_ON(!kacpid_wq); |
1795 | BUG_ON(!kacpi_notify_wq); | 1799 | BUG_ON(!kacpi_notify_wq); |
1796 | BUG_ON(!kacpi_hotplug_wq); | 1800 | BUG_ON(!kacpi_hotplug_wq); |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 33f554bc43b4..afafee56cf8b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -49,6 +49,12 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
49 | const struct acpi_device_id *not_used); | 49 | const struct acpi_device_id *not_used); |
50 | static void acpi_pci_root_remove(struct acpi_device *device); | 50 | static void acpi_pci_root_remove(struct acpi_device *device); |
51 | 51 | ||
52 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) | ||
53 | { | ||
54 | acpiphp_check_host_bridge(adev->handle); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
52 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ | 58 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ |
53 | | OSC_PCI_ASPM_SUPPORT \ | 59 | | OSC_PCI_ASPM_SUPPORT \ |
54 | | OSC_PCI_CLOCK_PM_SUPPORT \ | 60 | | OSC_PCI_CLOCK_PM_SUPPORT \ |
@@ -64,7 +70,8 @@ static struct acpi_scan_handler pci_root_handler = { | |||
64 | .attach = acpi_pci_root_add, | 70 | .attach = acpi_pci_root_add, |
65 | .detach = acpi_pci_root_remove, | 71 | .detach = acpi_pci_root_remove, |
66 | .hotplug = { | 72 | .hotplug = { |
67 | .ignore = true, | 73 | .enabled = true, |
74 | .scan_dependent = acpi_pci_root_scan_dependent, | ||
68 | }, | 75 | }, |
69 | }; | 76 | }; |
70 | 77 | ||
@@ -622,116 +629,9 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
622 | void __init acpi_pci_root_init(void) | 629 | void __init acpi_pci_root_init(void) |
623 | { | 630 | { |
624 | acpi_hest_init(); | 631 | acpi_hest_init(); |
625 | 632 | if (acpi_pci_disabled) | |
626 | if (!acpi_pci_disabled) { | ||
627 | pci_acpi_crs_quirks(); | ||
628 | acpi_scan_add_handler(&pci_root_handler); | ||
629 | } | ||
630 | } | ||
631 | /* Support root bridge hotplug */ | ||
632 | |||
633 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
634 | { | ||
635 | struct acpi_device *device; | ||
636 | |||
637 | if (!acpi_bus_get_device(handle, &device)) { | ||
638 | dev_printk(KERN_DEBUG, &device->dev, | ||
639 | "acpi device already exists; ignoring notify\n"); | ||
640 | return; | 633 | return; |
641 | } | ||
642 | |||
643 | if (acpi_bus_scan(handle)) | ||
644 | acpi_handle_err(handle, "cannot add bridge to acpi list\n"); | ||
645 | } | ||
646 | |||
647 | static void hotplug_event_root(void *data, u32 type) | ||
648 | { | ||
649 | acpi_handle handle = data; | ||
650 | struct acpi_pci_root *root; | ||
651 | |||
652 | acpi_scan_lock_acquire(); | ||
653 | |||
654 | root = acpi_pci_find_root(handle); | ||
655 | |||
656 | switch (type) { | ||
657 | case ACPI_NOTIFY_BUS_CHECK: | ||
658 | /* bus enumerate */ | ||
659 | acpi_handle_printk(KERN_DEBUG, handle, | ||
660 | "Bus check notify on %s\n", __func__); | ||
661 | if (root) | ||
662 | acpiphp_check_host_bridge(handle); | ||
663 | else | ||
664 | handle_root_bridge_insertion(handle); | ||
665 | |||
666 | break; | ||
667 | |||
668 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
669 | /* device check */ | ||
670 | acpi_handle_printk(KERN_DEBUG, handle, | ||
671 | "Device check notify on %s\n", __func__); | ||
672 | if (!root) | ||
673 | handle_root_bridge_insertion(handle); | ||
674 | break; | ||
675 | |||
676 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
677 | /* request device eject */ | ||
678 | acpi_handle_printk(KERN_DEBUG, handle, | ||
679 | "Device eject notify on %s\n", __func__); | ||
680 | if (!root) | ||
681 | break; | ||
682 | |||
683 | get_device(&root->device->dev); | ||
684 | |||
685 | acpi_scan_lock_release(); | ||
686 | |||
687 | acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST); | ||
688 | return; | ||
689 | default: | ||
690 | acpi_handle_warn(handle, | ||
691 | "notify_handler: unknown event type 0x%x\n", | ||
692 | type); | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | acpi_scan_lock_release(); | ||
697 | } | ||
698 | |||
699 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
700 | void *context) | ||
701 | { | ||
702 | acpi_hotplug_execute(hotplug_event_root, handle, type); | ||
703 | } | ||
704 | |||
705 | static acpi_status __init | ||
706 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
707 | { | ||
708 | acpi_status status; | ||
709 | int *count = (int *)context; | ||
710 | |||
711 | if (!acpi_is_root_bridge(handle)) | ||
712 | return AE_OK; | ||
713 | |||
714 | (*count)++; | ||
715 | |||
716 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
717 | handle_hotplug_event_root, NULL); | ||
718 | if (ACPI_FAILURE(status)) | ||
719 | acpi_handle_printk(KERN_DEBUG, handle, | ||
720 | "notify handler is not installed, exit status: %u\n", | ||
721 | (unsigned int)status); | ||
722 | else | ||
723 | acpi_handle_printk(KERN_DEBUG, handle, | ||
724 | "notify handler is installed\n"); | ||
725 | |||
726 | return AE_OK; | ||
727 | } | ||
728 | |||
729 | void __init acpi_pci_root_hp_init(void) | ||
730 | { | ||
731 | int num = 0; | ||
732 | |||
733 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
734 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
735 | 634 | ||
736 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | 635 | pci_acpi_crs_quirks(); |
636 | acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root"); | ||
737 | } | 637 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 68d40ff066fd..c0f57ff15024 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -12,11 +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 <asm/pgtable.h> | ||
16 | |||
15 | #include "internal.h" | 17 | #include "internal.h" |
16 | 18 | ||
17 | #define _COMPONENT ACPI_BUS_COMPONENT | 19 | #define _COMPONENT ACPI_BUS_COMPONENT |
18 | ACPI_MODULE_NAME("scan"); | 20 | ACPI_MODULE_NAME("scan"); |
19 | #define STRUCT_TO_INT(s) (*((int*)&s)) | ||
20 | extern struct acpi_device *acpi_root; | 21 | extern struct acpi_device *acpi_root; |
21 | 22 | ||
22 | #define ACPI_BUS_CLASS "system_bus" | 23 | #define ACPI_BUS_CLASS "system_bus" |
@@ -25,6 +26,8 @@ extern struct acpi_device *acpi_root; | |||
25 | 26 | ||
26 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) | 27 | #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) |
27 | 28 | ||
29 | #define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page) | ||
30 | |||
28 | /* | 31 | /* |
29 | * 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 |
30 | * gracefully (from the kernel's standpoint). | 33 | * gracefully (from the kernel's standpoint). |
@@ -123,6 +126,26 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
123 | } | 126 | } |
124 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 127 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
125 | 128 | ||
129 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) | ||
130 | { | ||
131 | struct acpi_device_physical_node *pn; | ||
132 | bool offline = true; | ||
133 | |||
134 | mutex_lock(&adev->physical_node_lock); | ||
135 | |||
136 | list_for_each_entry(pn, &adev->physical_node_list, node) | ||
137 | if (device_supports_offline(pn->dev) && !pn->dev->offline) { | ||
138 | if (uevent) | ||
139 | kobject_uevent(&pn->dev->kobj, KOBJ_CHANGE); | ||
140 | |||
141 | offline = false; | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | mutex_unlock(&adev->physical_node_lock); | ||
146 | return offline; | ||
147 | } | ||
148 | |||
126 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, | 149 | static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, |
127 | void **ret_p) | 150 | void **ret_p) |
128 | { | 151 | { |
@@ -193,19 +216,11 @@ static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, | |||
193 | return AE_OK; | 216 | return AE_OK; |
194 | } | 217 | } |
195 | 218 | ||
196 | static int acpi_scan_hot_remove(struct acpi_device *device) | 219 | static int acpi_scan_try_to_offline(struct acpi_device *device) |
197 | { | 220 | { |
198 | acpi_handle handle = device->handle; | 221 | acpi_handle handle = device->handle; |
199 | struct device *errdev; | 222 | struct device *errdev = NULL; |
200 | acpi_status status; | 223 | acpi_status status; |
201 | unsigned long long sta; | ||
202 | |||
203 | /* If there is no handle, the device node has been unregistered. */ | ||
204 | if (!handle) { | ||
205 | dev_dbg(&device->dev, "ACPI handle missing\n"); | ||
206 | put_device(&device->dev); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | 224 | ||
210 | /* | 225 | /* |
211 | * Carry out two passes here and ignore errors in the first pass, | 226 | * Carry out two passes here and ignore errors in the first pass, |
@@ -216,7 +231,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
216 | * | 231 | * |
217 | * If the first pass is successful, the second one isn't needed, though. | 232 | * If the first pass is successful, the second one isn't needed, though. |
218 | */ | 233 | */ |
219 | errdev = NULL; | ||
220 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 234 | status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
221 | NULL, acpi_bus_offline, (void *)false, | 235 | NULL, acpi_bus_offline, (void *)false, |
222 | (void **)&errdev); | 236 | (void **)&errdev); |
@@ -224,7 +238,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
224 | dev_warn(errdev, "Offline disabled.\n"); | 238 | dev_warn(errdev, "Offline disabled.\n"); |
225 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 239 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
226 | acpi_bus_online, NULL, NULL, NULL); | 240 | acpi_bus_online, NULL, NULL, NULL); |
227 | put_device(&device->dev); | ||
228 | return -EPERM; | 241 | return -EPERM; |
229 | } | 242 | } |
230 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); | 243 | acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); |
@@ -243,20 +256,32 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
243 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, | 256 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, |
244 | ACPI_UINT32_MAX, acpi_bus_online, | 257 | ACPI_UINT32_MAX, acpi_bus_online, |
245 | NULL, NULL, NULL); | 258 | NULL, NULL, NULL); |
246 | put_device(&device->dev); | ||
247 | return -EBUSY; | 259 | return -EBUSY; |
248 | } | 260 | } |
249 | } | 261 | } |
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int acpi_scan_hot_remove(struct acpi_device *device) | ||
266 | { | ||
267 | acpi_handle handle = device->handle; | ||
268 | unsigned long long sta; | ||
269 | acpi_status status; | ||
270 | |||
271 | if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { | ||
272 | if (!acpi_scan_is_offline(device, true)) | ||
273 | return -EBUSY; | ||
274 | } else { | ||
275 | int error = acpi_scan_try_to_offline(device); | ||
276 | if (error) | ||
277 | return error; | ||
278 | } | ||
250 | 279 | ||
251 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 280 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
252 | "Hot-removing device %s...\n", dev_name(&device->dev))); | 281 | "Hot-removing device %s...\n", dev_name(&device->dev))); |
253 | 282 | ||
254 | acpi_bus_trim(device); | 283 | acpi_bus_trim(device); |
255 | 284 | ||
256 | /* Device node has been unregistered. */ | ||
257 | put_device(&device->dev); | ||
258 | device = NULL; | ||
259 | |||
260 | acpi_evaluate_lck(handle, 0); | 285 | acpi_evaluate_lck(handle, 0); |
261 | /* | 286 | /* |
262 | * TBD: _EJD support. | 287 | * TBD: _EJD support. |
@@ -283,115 +308,127 @@ static int acpi_scan_hot_remove(struct acpi_device *device) | |||
283 | return 0; | 308 | return 0; |
284 | } | 309 | } |
285 | 310 | ||
286 | void acpi_bus_device_eject(void *data, u32 ost_src) | 311 | static int acpi_scan_device_not_present(struct acpi_device *adev) |
287 | { | 312 | { |
288 | struct acpi_device *device = data; | 313 | if (!acpi_device_enumerated(adev)) { |
289 | acpi_handle handle = device->handle; | 314 | dev_warn(&adev->dev, "Still not present\n"); |
290 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 315 | return -EALREADY; |
291 | int error; | 316 | } |
317 | acpi_bus_trim(adev); | ||
318 | return 0; | ||
319 | } | ||
292 | 320 | ||
293 | lock_device_hotplug(); | 321 | static int acpi_scan_device_check(struct acpi_device *adev) |
294 | mutex_lock(&acpi_scan_lock); | 322 | { |
323 | int error; | ||
295 | 324 | ||
296 | if (ost_src == ACPI_NOTIFY_EJECT_REQUEST) | 325 | acpi_bus_get_status(adev); |
297 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | 326 | if (adev->status.present || adev->status.functional) { |
298 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 327 | /* |
328 | * This function is only called for device objects for which | ||
329 | * matching scan handlers exist. The only situation in which | ||
330 | * the scan handler is not attached to this device object yet | ||
331 | * is when the device has just appeared (either it wasn't | ||
332 | * present at all before or it was removed and then added | ||
333 | * again). | ||
334 | */ | ||
335 | if (adev->handler) { | ||
336 | dev_warn(&adev->dev, "Already enumerated\n"); | ||
337 | return -EALREADY; | ||
338 | } | ||
339 | error = acpi_bus_scan(adev->handle); | ||
340 | if (error) { | ||
341 | dev_warn(&adev->dev, "Namespace scan failure\n"); | ||
342 | return error; | ||
343 | } | ||
344 | if (!adev->handler) { | ||
345 | dev_warn(&adev->dev, "Enumeration failure\n"); | ||
346 | error = -ENODEV; | ||
347 | } | ||
348 | } else { | ||
349 | error = acpi_scan_device_not_present(adev); | ||
350 | } | ||
351 | return error; | ||
352 | } | ||
299 | 353 | ||
300 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | 354 | static int acpi_scan_bus_check(struct acpi_device *adev) |
301 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | 355 | { |
356 | struct acpi_scan_handler *handler = adev->handler; | ||
357 | struct acpi_device *child; | ||
358 | int error; | ||
302 | 359 | ||
303 | error = acpi_scan_hot_remove(device); | 360 | acpi_bus_get_status(adev); |
304 | if (error == -EPERM) { | 361 | if (!(adev->status.present || adev->status.functional)) { |
305 | goto err_support; | 362 | acpi_scan_device_not_present(adev); |
306 | } else if (error) { | 363 | return 0; |
307 | goto err_out; | ||
308 | } | 364 | } |
365 | if (handler && handler->hotplug.scan_dependent) | ||
366 | return handler->hotplug.scan_dependent(adev); | ||
309 | 367 | ||
310 | out: | 368 | error = acpi_bus_scan(adev->handle); |
311 | mutex_unlock(&acpi_scan_lock); | 369 | if (error) { |
312 | unlock_device_hotplug(); | 370 | dev_warn(&adev->dev, "Namespace scan failure\n"); |
313 | return; | 371 | return error; |
314 | 372 | } | |
315 | err_support: | 373 | list_for_each_entry(child, &adev->children, node) { |
316 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 374 | error = acpi_scan_bus_check(child); |
317 | err_out: | 375 | if (error) |
318 | acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL); | 376 | return error; |
319 | goto out; | 377 | } |
378 | return 0; | ||
320 | } | 379 | } |
321 | 380 | ||
322 | static void acpi_scan_bus_device_check(void *data, u32 ost_source) | 381 | static void acpi_device_hotplug(void *data, u32 src) |
323 | { | 382 | { |
324 | acpi_handle handle = data; | ||
325 | struct acpi_device *device = NULL; | ||
326 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 383 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
384 | struct acpi_device *adev = data; | ||
327 | int error; | 385 | int error; |
328 | 386 | ||
329 | lock_device_hotplug(); | 387 | lock_device_hotplug(); |
330 | mutex_lock(&acpi_scan_lock); | 388 | mutex_lock(&acpi_scan_lock); |
331 | 389 | ||
332 | if (ost_source != ACPI_NOTIFY_BUS_CHECK) { | 390 | /* |
333 | acpi_bus_get_device(handle, &device); | 391 | * The device object's ACPI handle cannot become invalid as long as we |
334 | if (device) { | 392 | * are holding acpi_scan_lock, but it may have become invalid before |
335 | dev_warn(&device->dev, "Attempt to re-insert\n"); | 393 | * that lock was acquired. |
336 | goto out; | 394 | */ |
337 | } | 395 | if (adev->handle == INVALID_ACPI_HANDLE) |
338 | } | ||
339 | error = acpi_bus_scan(handle); | ||
340 | if (error) { | ||
341 | acpi_handle_warn(handle, "Namespace scan failure\n"); | ||
342 | goto out; | ||
343 | } | ||
344 | error = acpi_bus_get_device(handle, &device); | ||
345 | if (error) { | ||
346 | acpi_handle_warn(handle, "Missing device node object\n"); | ||
347 | goto out; | 396 | goto out; |
348 | } | ||
349 | ost_code = ACPI_OST_SC_SUCCESS; | ||
350 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | ||
351 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | ||
352 | |||
353 | out: | ||
354 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); | ||
355 | mutex_unlock(&acpi_scan_lock); | ||
356 | unlock_device_hotplug(); | ||
357 | } | ||
358 | 397 | ||
359 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | 398 | switch (src) { |
360 | { | ||
361 | u32 ost_status; | ||
362 | |||
363 | switch (type) { | ||
364 | case ACPI_NOTIFY_BUS_CHECK: | 399 | case ACPI_NOTIFY_BUS_CHECK: |
365 | acpi_handle_debug(handle, | 400 | error = acpi_scan_bus_check(adev); |
366 | "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); | ||
367 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
368 | break; | 401 | break; |
369 | case ACPI_NOTIFY_DEVICE_CHECK: | 402 | case ACPI_NOTIFY_DEVICE_CHECK: |
370 | acpi_handle_debug(handle, | 403 | error = acpi_scan_device_check(adev); |
371 | "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); | ||
372 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
373 | break; | 404 | break; |
374 | case ACPI_NOTIFY_EJECT_REQUEST: | 405 | case ACPI_NOTIFY_EJECT_REQUEST: |
375 | acpi_handle_debug(handle, | 406 | case ACPI_OST_EC_OSPM_EJECT: |
376 | "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); | 407 | error = acpi_scan_hot_remove(adev); |
377 | ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
378 | break; | 408 | break; |
379 | default: | 409 | default: |
380 | /* non-hotplug event; possibly handled by other handler */ | 410 | error = -EINVAL; |
381 | return; | 411 | break; |
382 | } | 412 | } |
413 | if (!error) | ||
414 | ost_code = ACPI_OST_SC_SUCCESS; | ||
383 | 415 | ||
384 | acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); | 416 | out: |
417 | acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL); | ||
418 | put_device(&adev->dev); | ||
419 | mutex_unlock(&acpi_scan_lock); | ||
420 | unlock_device_hotplug(); | ||
385 | } | 421 | } |
386 | 422 | ||
387 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 423 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
388 | { | 424 | { |
425 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
389 | struct acpi_scan_handler *handler = data; | 426 | struct acpi_scan_handler *handler = data; |
390 | struct acpi_device *adev; | 427 | struct acpi_device *adev; |
391 | acpi_status status; | 428 | acpi_status status; |
392 | 429 | ||
393 | if (!handler->hotplug.enabled) | 430 | if (acpi_bus_get_device(handle, &adev)) |
394 | return acpi_hotplug_unsupported(handle, type); | 431 | goto err_out; |
395 | 432 | ||
396 | switch (type) { | 433 | switch (type) { |
397 | case ACPI_NOTIFY_BUS_CHECK: | 434 | case ACPI_NOTIFY_BUS_CHECK: |
@@ -402,27 +439,27 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
402 | break; | 439 | break; |
403 | case ACPI_NOTIFY_EJECT_REQUEST: | 440 | case ACPI_NOTIFY_EJECT_REQUEST: |
404 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 441 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
405 | if (acpi_bus_get_device(handle, &adev)) | 442 | if (!handler->hotplug.enabled) { |
443 | acpi_handle_err(handle, "Eject disabled\n"); | ||
444 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
406 | goto err_out; | 445 | goto err_out; |
407 | 446 | } | |
408 | get_device(&adev->dev); | 447 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, |
409 | status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type); | 448 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
410 | if (ACPI_SUCCESS(status)) | 449 | break; |
411 | return; | ||
412 | |||
413 | put_device(&adev->dev); | ||
414 | goto err_out; | ||
415 | default: | 450 | default: |
416 | /* non-hotplug event; possibly handled by other handler */ | 451 | /* non-hotplug event; possibly handled by other handler */ |
417 | return; | 452 | return; |
418 | } | 453 | } |
419 | status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type); | 454 | get_device(&adev->dev); |
455 | status = acpi_hotplug_execute(acpi_device_hotplug, adev, type); | ||
420 | if (ACPI_SUCCESS(status)) | 456 | if (ACPI_SUCCESS(status)) |
421 | return; | 457 | return; |
422 | 458 | ||
459 | put_device(&adev->dev); | ||
460 | |||
423 | err_out: | 461 | err_out: |
424 | acpi_evaluate_hotplug_ost(handle, type, | 462 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); |
425 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | ||
426 | } | 463 | } |
427 | 464 | ||
428 | static ssize_t real_power_state_show(struct device *dev, | 465 | static ssize_t real_power_state_show(struct device *dev, |
@@ -473,7 +510,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, | |||
473 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, | 510 | acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT, |
474 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | 511 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); |
475 | get_device(&acpi_device->dev); | 512 | get_device(&acpi_device->dev); |
476 | status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device, | 513 | status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device, |
477 | ACPI_OST_EC_OSPM_EJECT); | 514 | ACPI_OST_EC_OSPM_EJECT); |
478 | if (ACPI_SUCCESS(status)) | 515 | if (ACPI_SUCCESS(status)) |
479 | return count; | 516 | return count; |
@@ -565,6 +602,20 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr, | |||
565 | } | 602 | } |
566 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); | 603 | static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); |
567 | 604 | ||
605 | static ssize_t status_show(struct device *dev, struct device_attribute *attr, | ||
606 | char *buf) { | ||
607 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
608 | acpi_status status; | ||
609 | unsigned long long sta; | ||
610 | |||
611 | status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta); | ||
612 | if (ACPI_FAILURE(status)) | ||
613 | return -ENODEV; | ||
614 | |||
615 | return sprintf(buf, "%llu\n", sta); | ||
616 | } | ||
617 | static DEVICE_ATTR_RO(status); | ||
618 | |||
568 | static int acpi_device_setup_files(struct acpi_device *dev) | 619 | static int acpi_device_setup_files(struct acpi_device *dev) |
569 | { | 620 | { |
570 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 621 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
@@ -620,6 +671,12 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
620 | dev->pnp.sun = (unsigned long)-1; | 671 | dev->pnp.sun = (unsigned long)-1; |
621 | } | 672 | } |
622 | 673 | ||
674 | if (acpi_has_method(dev->handle, "_STA")) { | ||
675 | result = device_create_file(&dev->dev, &dev_attr_status); | ||
676 | if (result) | ||
677 | goto end; | ||
678 | } | ||
679 | |||
623 | /* | 680 | /* |
624 | * If device has _EJ0, 'eject' file is created that is used to trigger | 681 | * If device has _EJ0, 'eject' file is created that is used to trigger |
625 | * hot-removal function from userland. | 682 | * hot-removal function from userland. |
@@ -675,6 +732,8 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
675 | device_remove_file(&dev->dev, &dev_attr_adr); | 732 | device_remove_file(&dev->dev, &dev_attr_adr); |
676 | device_remove_file(&dev->dev, &dev_attr_modalias); | 733 | device_remove_file(&dev->dev, &dev_attr_modalias); |
677 | device_remove_file(&dev->dev, &dev_attr_hid); | 734 | device_remove_file(&dev->dev, &dev_attr_hid); |
735 | if (acpi_has_method(dev->handle, "_STA")) | ||
736 | device_remove_file(&dev->dev, &dev_attr_status); | ||
678 | if (dev->handle) | 737 | if (dev->handle) |
679 | device_remove_file(&dev->dev, &dev_attr_path); | 738 | device_remove_file(&dev->dev, &dev_attr_path); |
680 | } | 739 | } |
@@ -905,9 +964,91 @@ struct bus_type acpi_bus_type = { | |||
905 | .uevent = acpi_device_uevent, | 964 | .uevent = acpi_device_uevent, |
906 | }; | 965 | }; |
907 | 966 | ||
908 | static void acpi_bus_data_handler(acpi_handle handle, void *context) | 967 | static void acpi_device_del(struct acpi_device *device) |
968 | { | ||
969 | mutex_lock(&acpi_device_lock); | ||
970 | if (device->parent) | ||
971 | list_del(&device->node); | ||
972 | |||
973 | list_del(&device->wakeup_list); | ||
974 | mutex_unlock(&acpi_device_lock); | ||
975 | |||
976 | acpi_power_add_remove_device(device, false); | ||
977 | acpi_device_remove_files(device); | ||
978 | if (device->remove) | ||
979 | device->remove(device); | ||
980 | |||
981 | device_del(&device->dev); | ||
982 | } | ||
983 | |||
984 | static LIST_HEAD(acpi_device_del_list); | ||
985 | static DEFINE_MUTEX(acpi_device_del_lock); | ||
986 | |||
987 | static void acpi_device_del_work_fn(struct work_struct *work_not_used) | ||
988 | { | ||
989 | for (;;) { | ||
990 | struct acpi_device *adev; | ||
991 | |||
992 | mutex_lock(&acpi_device_del_lock); | ||
993 | |||
994 | if (list_empty(&acpi_device_del_list)) { | ||
995 | mutex_unlock(&acpi_device_del_lock); | ||
996 | break; | ||
997 | } | ||
998 | adev = list_first_entry(&acpi_device_del_list, | ||
999 | struct acpi_device, del_list); | ||
1000 | list_del(&adev->del_list); | ||
1001 | |||
1002 | mutex_unlock(&acpi_device_del_lock); | ||
1003 | |||
1004 | acpi_device_del(adev); | ||
1005 | /* | ||
1006 | * Drop references to all power resources that might have been | ||
1007 | * used by the device. | ||
1008 | */ | ||
1009 | acpi_power_transition(adev, ACPI_STATE_D3_COLD); | ||
1010 | put_device(&adev->dev); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | /** | ||
1015 | * acpi_scan_drop_device - Drop an ACPI device object. | ||
1016 | * @handle: Handle of an ACPI namespace node, not used. | ||
1017 | * @context: Address of the ACPI device object to drop. | ||
1018 | * | ||
1019 | * This is invoked by acpi_ns_delete_node() during the removal of the ACPI | ||
1020 | * namespace node the device object pointed to by @context is attached to. | ||
1021 | * | ||
1022 | * The unregistration is carried out asynchronously to avoid running | ||
1023 | * acpi_device_del() under the ACPICA's namespace mutex and the list is used to | ||
1024 | * ensure the correct ordering (the device objects must be unregistered in the | ||
1025 | * same order in which the corresponding namespace nodes are deleted). | ||
1026 | */ | ||
1027 | static void acpi_scan_drop_device(acpi_handle handle, void *context) | ||
909 | { | 1028 | { |
910 | /* Intentionally empty. */ | 1029 | static DECLARE_WORK(work, acpi_device_del_work_fn); |
1030 | struct acpi_device *adev = context; | ||
1031 | |||
1032 | mutex_lock(&acpi_device_del_lock); | ||
1033 | |||
1034 | /* | ||
1035 | * Use the ACPI hotplug workqueue which is ordered, so this work item | ||
1036 | * won't run after any hotplug work items submitted subsequently. That | ||
1037 | * prevents attempts to register device objects identical to those being | ||
1038 | * deleted from happening concurrently (such attempts result from | ||
1039 | * hotplug events handled via the ACPI hotplug workqueue). It also will | ||
1040 | * run after all of the work items submitted previosuly, which helps | ||
1041 | * those work items to ensure that they are not accessing stale device | ||
1042 | * objects. | ||
1043 | */ | ||
1044 | if (list_empty(&acpi_device_del_list)) | ||
1045 | acpi_queue_hotplug_work(&work); | ||
1046 | |||
1047 | list_add_tail(&adev->del_list, &acpi_device_del_list); | ||
1048 | /* Make acpi_ns_validate_handle() return NULL for this handle. */ | ||
1049 | adev->handle = INVALID_ACPI_HANDLE; | ||
1050 | |||
1051 | mutex_unlock(&acpi_device_del_lock); | ||
911 | } | 1052 | } |
912 | 1053 | ||
913 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | 1054 | int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) |
@@ -917,7 +1058,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) | |||
917 | if (!device) | 1058 | if (!device) |
918 | return -EINVAL; | 1059 | return -EINVAL; |
919 | 1060 | ||
920 | status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); | 1061 | status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device); |
921 | if (ACPI_FAILURE(status) || !*device) { | 1062 | if (ACPI_FAILURE(status) || !*device) { |
922 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", | 1063 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", |
923 | handle)); | 1064 | handle)); |
@@ -937,7 +1078,7 @@ int acpi_device_add(struct acpi_device *device, | |||
937 | if (device->handle) { | 1078 | if (device->handle) { |
938 | acpi_status status; | 1079 | acpi_status status; |
939 | 1080 | ||
940 | status = acpi_attach_data(device->handle, acpi_bus_data_handler, | 1081 | status = acpi_attach_data(device->handle, acpi_scan_drop_device, |
941 | device); | 1082 | device); |
942 | if (ACPI_FAILURE(status)) { | 1083 | if (ACPI_FAILURE(status)) { |
943 | acpi_handle_err(device->handle, | 1084 | acpi_handle_err(device->handle, |
@@ -955,6 +1096,7 @@ int acpi_device_add(struct acpi_device *device, | |||
955 | INIT_LIST_HEAD(&device->node); | 1096 | INIT_LIST_HEAD(&device->node); |
956 | INIT_LIST_HEAD(&device->wakeup_list); | 1097 | INIT_LIST_HEAD(&device->wakeup_list); |
957 | INIT_LIST_HEAD(&device->physical_node_list); | 1098 | INIT_LIST_HEAD(&device->physical_node_list); |
1099 | INIT_LIST_HEAD(&device->del_list); | ||
958 | mutex_init(&device->physical_node_lock); | 1100 | mutex_init(&device->physical_node_lock); |
959 | 1101 | ||
960 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 1102 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
@@ -1018,37 +1160,10 @@ int acpi_device_add(struct acpi_device *device, | |||
1018 | mutex_unlock(&acpi_device_lock); | 1160 | mutex_unlock(&acpi_device_lock); |
1019 | 1161 | ||
1020 | err_detach: | 1162 | err_detach: |
1021 | acpi_detach_data(device->handle, acpi_bus_data_handler); | 1163 | acpi_detach_data(device->handle, acpi_scan_drop_device); |
1022 | return result; | 1164 | return result; |
1023 | } | 1165 | } |
1024 | 1166 | ||
1025 | static void acpi_device_unregister(struct acpi_device *device) | ||
1026 | { | ||
1027 | mutex_lock(&acpi_device_lock); | ||
1028 | if (device->parent) | ||
1029 | list_del(&device->node); | ||
1030 | |||
1031 | list_del(&device->wakeup_list); | ||
1032 | mutex_unlock(&acpi_device_lock); | ||
1033 | |||
1034 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
1035 | |||
1036 | acpi_power_add_remove_device(device, false); | ||
1037 | acpi_device_remove_files(device); | ||
1038 | if (device->remove) | ||
1039 | device->remove(device); | ||
1040 | |||
1041 | device_del(&device->dev); | ||
1042 | /* | ||
1043 | * Transition the device to D3cold to drop the reference counts of all | ||
1044 | * power resources the device depends on and turn off the ones that have | ||
1045 | * no more references. | ||
1046 | */ | ||
1047 | acpi_device_set_power(device, ACPI_STATE_D3_COLD); | ||
1048 | device->handle = NULL; | ||
1049 | put_device(&device->dev); | ||
1050 | } | ||
1051 | |||
1052 | /* -------------------------------------------------------------------------- | 1167 | /* -------------------------------------------------------------------------- |
1053 | Driver Management | 1168 | Driver Management |
1054 | -------------------------------------------------------------------------- */ | 1169 | -------------------------------------------------------------------------- */ |
@@ -1622,11 +1737,13 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1622 | device->device_type = type; | 1737 | device->device_type = type; |
1623 | device->handle = handle; | 1738 | device->handle = handle; |
1624 | device->parent = acpi_bus_get_parent(handle); | 1739 | device->parent = acpi_bus_get_parent(handle); |
1625 | STRUCT_TO_INT(device->status) = sta; | 1740 | acpi_set_device_status(device, sta); |
1626 | acpi_device_get_busid(device); | 1741 | acpi_device_get_busid(device); |
1627 | acpi_set_pnp_ids(handle, &device->pnp, type); | 1742 | acpi_set_pnp_ids(handle, &device->pnp, type); |
1628 | acpi_bus_get_flags(device); | 1743 | acpi_bus_get_flags(device); |
1629 | device->flags.match_driver = false; | 1744 | device->flags.match_driver = false; |
1745 | device->flags.initialized = true; | ||
1746 | device->flags.visited = false; | ||
1630 | device_initialize(&device->dev); | 1747 | device_initialize(&device->dev); |
1631 | dev_set_uevent_suppress(&device->dev, true); | 1748 | dev_set_uevent_suppress(&device->dev, true); |
1632 | } | 1749 | } |
@@ -1711,6 +1828,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, | |||
1711 | return 0; | 1828 | return 0; |
1712 | } | 1829 | } |
1713 | 1830 | ||
1831 | bool acpi_device_is_present(struct acpi_device *adev) | ||
1832 | { | ||
1833 | if (adev->status.present || adev->status.functional) | ||
1834 | return true; | ||
1835 | |||
1836 | adev->flags.initialized = false; | ||
1837 | return false; | ||
1838 | } | ||
1839 | |||
1714 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, | 1840 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, |
1715 | char *idstr, | 1841 | char *idstr, |
1716 | const struct acpi_device_id **matchid) | 1842 | const struct acpi_device_id **matchid) |
@@ -1770,7 +1896,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type) | |||
1770 | */ | 1896 | */ |
1771 | list_for_each_entry(hwid, &pnp.ids, list) { | 1897 | list_for_each_entry(hwid, &pnp.ids, list) { |
1772 | handler = acpi_scan_match_handler(hwid->id, NULL); | 1898 | handler = acpi_scan_match_handler(hwid->id, NULL); |
1773 | if (handler && !handler->hotplug.ignore) { | 1899 | if (handler) { |
1774 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1900 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1775 | acpi_hotplug_notify_cb, handler); | 1901 | acpi_hotplug_notify_cb, handler); |
1776 | break; | 1902 | break; |
@@ -1804,18 +1930,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1804 | 1930 | ||
1805 | acpi_scan_init_hotplug(handle, type); | 1931 | acpi_scan_init_hotplug(handle, type); |
1806 | 1932 | ||
1807 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && | ||
1808 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { | ||
1809 | struct acpi_device_wakeup wakeup; | ||
1810 | |||
1811 | if (acpi_has_method(handle, "_PRW")) { | ||
1812 | acpi_bus_extract_wakeup_device_power_package(handle, | ||
1813 | &wakeup); | ||
1814 | acpi_power_resources_list_free(&wakeup.resources); | ||
1815 | } | ||
1816 | return AE_CTRL_DEPTH; | ||
1817 | } | ||
1818 | |||
1819 | acpi_add_single_object(&device, handle, type, sta); | 1933 | acpi_add_single_object(&device, handle, type, sta); |
1820 | if (!device) | 1934 | if (!device) |
1821 | return AE_CTRL_DEPTH; | 1935 | return AE_CTRL_DEPTH; |
@@ -1850,36 +1964,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
1850 | return ret; | 1964 | return ret; |
1851 | } | 1965 | } |
1852 | 1966 | ||
1853 | static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | 1967 | static void acpi_bus_attach(struct acpi_device *device) |
1854 | void *not_used, void **ret_not_used) | ||
1855 | { | 1968 | { |
1856 | struct acpi_device *device; | 1969 | struct acpi_device *child; |
1857 | unsigned long long sta_not_used; | ||
1858 | int ret; | 1970 | int ret; |
1859 | 1971 | ||
1860 | /* | 1972 | acpi_bus_get_status(device); |
1861 | * Ignore errors ignored by acpi_bus_check_add() to avoid terminating | 1973 | /* Skip devices that are not present. */ |
1862 | * namespace walks prematurely. | 1974 | if (!acpi_device_is_present(device)) { |
1863 | */ | 1975 | device->flags.visited = false; |
1864 | if (acpi_bus_type_and_status(handle, &ret, &sta_not_used)) | 1976 | return; |
1865 | return AE_OK; | 1977 | } |
1866 | |||
1867 | if (acpi_bus_get_device(handle, &device)) | ||
1868 | return AE_CTRL_DEPTH; | ||
1869 | |||
1870 | if (device->handler) | 1978 | if (device->handler) |
1871 | return AE_OK; | 1979 | goto ok; |
1872 | 1980 | ||
1981 | if (!device->flags.initialized) { | ||
1982 | acpi_bus_update_power(device, NULL); | ||
1983 | device->flags.initialized = true; | ||
1984 | } | ||
1985 | device->flags.visited = false; | ||
1873 | ret = acpi_scan_attach_handler(device); | 1986 | ret = acpi_scan_attach_handler(device); |
1874 | if (ret < 0) | 1987 | if (ret < 0) |
1875 | return AE_CTRL_DEPTH; | 1988 | return; |
1876 | 1989 | ||
1877 | device->flags.match_driver = true; | 1990 | device->flags.match_driver = true; |
1878 | if (ret > 0) | 1991 | if (!ret) { |
1879 | return AE_OK; | 1992 | ret = device_attach(&device->dev); |
1993 | if (ret < 0) | ||
1994 | return; | ||
1995 | } | ||
1996 | device->flags.visited = true; | ||
1880 | 1997 | ||
1881 | ret = device_attach(&device->dev); | 1998 | ok: |
1882 | return ret >= 0 ? AE_OK : AE_CTRL_DEPTH; | 1999 | list_for_each_entry(child, &device->children, node) |
2000 | acpi_bus_attach(child); | ||
1883 | } | 2001 | } |
1884 | 2002 | ||
1885 | /** | 2003 | /** |
@@ -1899,75 +2017,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, | |||
1899 | int acpi_bus_scan(acpi_handle handle) | 2017 | int acpi_bus_scan(acpi_handle handle) |
1900 | { | 2018 | { |
1901 | void *device = NULL; | 2019 | void *device = NULL; |
1902 | int error = 0; | ||
1903 | 2020 | ||
1904 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) | 2021 | if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device))) |
1905 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | 2022 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, |
1906 | acpi_bus_check_add, NULL, NULL, &device); | 2023 | acpi_bus_check_add, NULL, NULL, &device); |
1907 | 2024 | ||
1908 | if (!device) | 2025 | if (device) { |
1909 | error = -ENODEV; | 2026 | acpi_bus_attach(device); |
1910 | else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL))) | 2027 | return 0; |
1911 | acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, | ||
1912 | acpi_bus_device_attach, NULL, NULL, NULL); | ||
1913 | |||
1914 | return error; | ||
1915 | } | ||
1916 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1917 | |||
1918 | static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used, | ||
1919 | void *not_used, void **ret_not_used) | ||
1920 | { | ||
1921 | struct acpi_device *device = NULL; | ||
1922 | |||
1923 | if (!acpi_bus_get_device(handle, &device)) { | ||
1924 | struct acpi_scan_handler *dev_handler = device->handler; | ||
1925 | |||
1926 | if (dev_handler) { | ||
1927 | if (dev_handler->detach) | ||
1928 | dev_handler->detach(device); | ||
1929 | |||
1930 | device->handler = NULL; | ||
1931 | } else { | ||
1932 | device_release_driver(&device->dev); | ||
1933 | } | ||
1934 | } | 2028 | } |
1935 | return AE_OK; | 2029 | return -ENODEV; |
1936 | } | ||
1937 | |||
1938 | static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used, | ||
1939 | void *not_used, void **ret_not_used) | ||
1940 | { | ||
1941 | struct acpi_device *device = NULL; | ||
1942 | |||
1943 | if (!acpi_bus_get_device(handle, &device)) | ||
1944 | acpi_device_unregister(device); | ||
1945 | |||
1946 | return AE_OK; | ||
1947 | } | 2030 | } |
2031 | EXPORT_SYMBOL(acpi_bus_scan); | ||
1948 | 2032 | ||
1949 | /** | 2033 | /** |
1950 | * acpi_bus_trim - Remove ACPI device node and all of its descendants | 2034 | * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects. |
1951 | * @start: Root of the ACPI device nodes subtree to remove. | 2035 | * @adev: Root of the ACPI namespace scope to walk. |
1952 | * | 2036 | * |
1953 | * Must be called under acpi_scan_lock. | 2037 | * Must be called under acpi_scan_lock. |
1954 | */ | 2038 | */ |
1955 | void acpi_bus_trim(struct acpi_device *start) | 2039 | void acpi_bus_trim(struct acpi_device *adev) |
1956 | { | 2040 | { |
2041 | struct acpi_scan_handler *handler = adev->handler; | ||
2042 | struct acpi_device *child; | ||
2043 | |||
2044 | list_for_each_entry_reverse(child, &adev->children, node) | ||
2045 | acpi_bus_trim(child); | ||
2046 | |||
2047 | if (handler) { | ||
2048 | if (handler->detach) | ||
2049 | handler->detach(adev); | ||
2050 | |||
2051 | adev->handler = NULL; | ||
2052 | } else { | ||
2053 | device_release_driver(&adev->dev); | ||
2054 | } | ||
1957 | /* | 2055 | /* |
1958 | * Execute acpi_bus_device_detach() as a post-order callback to detach | 2056 | * Most likely, the device is going away, so put it into D3cold before |
1959 | * all ACPI drivers from the device nodes being removed. | 2057 | * that. |
1960 | */ | ||
1961 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | ||
1962 | acpi_bus_device_detach, NULL, NULL); | ||
1963 | acpi_bus_device_detach(start->handle, 0, NULL, NULL); | ||
1964 | /* | ||
1965 | * Execute acpi_bus_remove() as a post-order callback to remove device | ||
1966 | * nodes in the given namespace scope. | ||
1967 | */ | 2058 | */ |
1968 | acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL, | 2059 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); |
1969 | acpi_bus_remove, NULL, NULL); | 2060 | adev->flags.initialized = false; |
1970 | acpi_bus_remove(start->handle, 0, NULL, NULL); | 2061 | adev->flags.visited = false; |
1971 | } | 2062 | } |
1972 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 2063 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1973 | 2064 | ||
@@ -2045,14 +2136,14 @@ int __init acpi_scan_init(void) | |||
2045 | 2136 | ||
2046 | result = acpi_bus_scan_fixed(); | 2137 | result = acpi_bus_scan_fixed(); |
2047 | if (result) { | 2138 | if (result) { |
2048 | acpi_device_unregister(acpi_root); | 2139 | acpi_detach_data(acpi_root->handle, acpi_scan_drop_device); |
2140 | acpi_device_del(acpi_root); | ||
2141 | put_device(&acpi_root->dev); | ||
2049 | goto out; | 2142 | goto out; |
2050 | } | 2143 | } |
2051 | 2144 | ||
2052 | acpi_update_all_gpes(); | 2145 | acpi_update_all_gpes(); |
2053 | 2146 | ||
2054 | acpi_pci_root_hp_init(); | ||
2055 | |||
2056 | out: | 2147 | out: |
2057 | mutex_unlock(&acpi_scan_lock); | 2148 | mutex_unlock(&acpi_scan_lock); |
2058 | return result; | 2149 | return result; |
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 8e22d9762328..9e69a5308693 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -178,12 +178,12 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { | |||
178 | /* bind acpi handle to pata port */ | 178 | /* bind acpi handle to pata port */ |
179 | void ata_acpi_bind_port(struct ata_port *ap) | 179 | void ata_acpi_bind_port(struct ata_port *ap) |
180 | { | 180 | { |
181 | acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); | 181 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); |
182 | 182 | ||
183 | if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle) | 183 | if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) |
184 | return; | 184 | return; |
185 | 185 | ||
186 | acpi_preset_companion(&ap->tdev, host_handle, ap->port_no); | 186 | acpi_preset_companion(&ap->tdev, host_companion, ap->port_no); |
187 | 187 | ||
188 | if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) | 188 | if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) |
189 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; | 189 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; |
@@ -196,17 +196,17 @@ void ata_acpi_bind_port(struct ata_port *ap) | |||
196 | void ata_acpi_bind_dev(struct ata_device *dev) | 196 | void ata_acpi_bind_dev(struct ata_device *dev) |
197 | { | 197 | { |
198 | struct ata_port *ap = dev->link->ap; | 198 | struct ata_port *ap = dev->link->ap; |
199 | acpi_handle port_handle = ACPI_HANDLE(&ap->tdev); | 199 | struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); |
200 | acpi_handle host_handle = ACPI_HANDLE(ap->host->dev); | 200 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); |
201 | acpi_handle parent_handle; | 201 | struct acpi_device *parent; |
202 | u64 adr; | 202 | u64 adr; |
203 | 203 | ||
204 | /* | 204 | /* |
205 | * For both sata/pata devices, host handle is required. | 205 | * For both sata/pata devices, host companion device is required. |
206 | * For pata device, port handle is also required. | 206 | * For pata device, port companion device is also required. |
207 | */ | 207 | */ |
208 | if (libata_noacpi || !host_handle || | 208 | if (libata_noacpi || !host_companion || |
209 | (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle)) | 209 | (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_companion)) |
210 | return; | 210 | return; |
211 | 211 | ||
212 | if (ap->flags & ATA_FLAG_ACPI_SATA) { | 212 | if (ap->flags & ATA_FLAG_ACPI_SATA) { |
@@ -214,13 +214,13 @@ void ata_acpi_bind_dev(struct ata_device *dev) | |||
214 | adr = SATA_ADR(ap->port_no, NO_PORT_MULT); | 214 | adr = SATA_ADR(ap->port_no, NO_PORT_MULT); |
215 | else | 215 | else |
216 | adr = SATA_ADR(ap->port_no, dev->link->pmp); | 216 | adr = SATA_ADR(ap->port_no, dev->link->pmp); |
217 | parent_handle = host_handle; | 217 | parent = host_companion; |
218 | } else { | 218 | } else { |
219 | adr = dev->devno; | 219 | adr = dev->devno; |
220 | parent_handle = port_handle; | 220 | parent = port_companion; |
221 | } | 221 | } |
222 | 222 | ||
223 | acpi_preset_companion(&dev->tdev, parent_handle, adr); | 223 | acpi_preset_companion(&dev->tdev, parent, adr); |
224 | 224 | ||
225 | register_hotplug_dock_device(ata_dev_acpi_handle(dev), | 225 | register_hotplug_dock_device(ata_dev_acpi_handle(dev), |
226 | &ata_acpi_dev_dock_ops, dev, NULL, NULL); | 226 | &ata_acpi_dev_dock_ops, dev, NULL, NULL); |
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 94e8a80e87f8..d08c9d3b1d37 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -4,7 +4,7 @@ obj-y := core.o bus.o dd.o syscore.o \ | |||
4 | driver.o class.o platform.o \ | 4 | driver.o class.o platform.o \ |
5 | cpu.o firmware.o init.o map.o devres.o \ | 5 | cpu.o firmware.o init.o map.o devres.o \ |
6 | attribute_container.o transport_class.o \ | 6 | attribute_container.o transport_class.o \ |
7 | topology.o | 7 | topology.o container.o |
8 | obj-$(CONFIG_DEVTMPFS) += devtmpfs.o | 8 | obj-$(CONFIG_DEVTMPFS) += devtmpfs.o |
9 | obj-$(CONFIG_DMA_CMA) += dma-contiguous.o | 9 | obj-$(CONFIG_DMA_CMA) += dma-contiguous.o |
10 | obj-y += power/ | 10 | obj-y += power/ |
diff --git a/drivers/base/base.h b/drivers/base/base.h index 2cbc6774f4cd..24f424249d9b 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -100,6 +100,7 @@ static inline int hypervisor_init(void) { return 0; } | |||
100 | #endif | 100 | #endif |
101 | extern int platform_bus_init(void); | 101 | extern int platform_bus_init(void); |
102 | extern void cpu_dev_init(void); | 102 | extern void cpu_dev_init(void); |
103 | extern void container_dev_init(void); | ||
103 | 104 | ||
104 | struct kobject *virtual_device_parent(struct device *dev); | 105 | struct kobject *virtual_device_parent(struct device *dev); |
105 | 106 | ||
diff --git a/drivers/base/container.c b/drivers/base/container.c new file mode 100644 index 000000000000..ecbfbe2e908f --- /dev/null +++ b/drivers/base/container.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * System bus type for containers. | ||
3 | * | ||
4 | * Copyright (C) 2013, Intel Corporation | ||
5 | * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/container.h> | ||
13 | |||
14 | #include "base.h" | ||
15 | |||
16 | #define CONTAINER_BUS_NAME "container" | ||
17 | |||
18 | static int trivial_online(struct device *dev) | ||
19 | { | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | static int container_offline(struct device *dev) | ||
24 | { | ||
25 | struct container_dev *cdev = to_container_dev(dev); | ||
26 | |||
27 | return cdev->offline ? cdev->offline(cdev) : 0; | ||
28 | } | ||
29 | |||
30 | struct bus_type container_subsys = { | ||
31 | .name = CONTAINER_BUS_NAME, | ||
32 | .dev_name = CONTAINER_BUS_NAME, | ||
33 | .online = trivial_online, | ||
34 | .offline = container_offline, | ||
35 | }; | ||
36 | |||
37 | void __init container_dev_init(void) | ||
38 | { | ||
39 | int ret; | ||
40 | |||
41 | ret = subsys_system_register(&container_subsys, NULL); | ||
42 | if (ret) | ||
43 | pr_err("%s() failed: %d\n", __func__, ret); | ||
44 | } | ||
diff --git a/drivers/base/init.c b/drivers/base/init.c index c16f0b808a17..da033d3bab3c 100644 --- a/drivers/base/init.c +++ b/drivers/base/init.c | |||
@@ -33,4 +33,5 @@ void __init driver_init(void) | |||
33 | platform_bus_init(); | 33 | platform_bus_init(); |
34 | cpu_dev_init(); | 34 | cpu_dev_init(); |
35 | memory_dev_init(); | 35 | memory_dev_init(); |
36 | container_dev_init(); | ||
36 | } | 37 | } |
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 333d4053e727..b6940992a6ff 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c | |||
@@ -97,6 +97,17 @@ bool ide_port_acpi(ide_hwif_t *hwif) | |||
97 | return ide_noacpi == 0 && hwif->acpidata; | 97 | return ide_noacpi == 0 && hwif->acpidata; |
98 | } | 98 | } |
99 | 99 | ||
100 | static acpi_handle acpi_get_child(acpi_handle handle, u64 addr) | ||
101 | { | ||
102 | struct acpi_device *adev; | ||
103 | |||
104 | if (!handle || acpi_bus_get_device(handle, &adev)) | ||
105 | return NULL; | ||
106 | |||
107 | adev = acpi_find_child_device(adev, addr, false); | ||
108 | return adev ? adev->handle : NULL; | ||
109 | } | ||
110 | |||
100 | /** | 111 | /** |
101 | * ide_get_dev_handle - finds acpi_handle and PCI device.function | 112 | * ide_get_dev_handle - finds acpi_handle and PCI device.function |
102 | * @dev: device to locate | 113 | * @dev: device to locate |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 157b570ba343..92d1ba8e8153 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
@@ -308,7 +308,7 @@ static void sdio_acpi_set_handle(struct sdio_func *func) | |||
308 | struct mmc_host *host = func->card->host; | 308 | struct mmc_host *host = func->card->host; |
309 | u64 addr = (host->slotno << 16) | func->num; | 309 | u64 addr = (host->slotno << 16) | func->num; |
310 | 310 | ||
311 | acpi_preset_companion(&func->dev, ACPI_HANDLE(host->parent), addr); | 311 | acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr); |
312 | } | 312 | } |
313 | #else | 313 | #else |
314 | static inline void sdio_acpi_set_handle(struct sdio_func *func) {} | 314 | static inline void sdio_acpi_set_handle(struct sdio_func *func) {} |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e86439283a5d..4f0c40d405fc 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -491,7 +491,7 @@ static void acpiphp_bus_add(acpi_handle handle) | |||
491 | 491 | ||
492 | acpi_bus_scan(handle); | 492 | acpi_bus_scan(handle); |
493 | acpi_bus_get_device(handle, &adev); | 493 | acpi_bus_get_device(handle, &adev); |
494 | if (adev) | 494 | if (acpi_device_enumerated(adev)) |
495 | acpi_device_set_power(adev, ACPI_STATE_D0); | 495 | acpi_device_set_power(adev, ACPI_STATE_D0); |
496 | } | 496 | } |
497 | 497 | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 68128d6bd33d..733a8222b13f 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -303,10 +303,10 @@ void acpi_pci_remove_bus(struct pci_bus *bus) | |||
303 | } | 303 | } |
304 | 304 | ||
305 | /* ACPI bus type */ | 305 | /* ACPI bus type */ |
306 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) | 306 | static struct acpi_device *acpi_pci_find_companion(struct device *dev) |
307 | { | 307 | { |
308 | struct pci_dev *pci_dev = to_pci_dev(dev); | 308 | struct pci_dev *pci_dev = to_pci_dev(dev); |
309 | bool is_bridge; | 309 | bool check_children; |
310 | u64 addr; | 310 | u64 addr; |
311 | 311 | ||
312 | /* | 312 | /* |
@@ -314,14 +314,12 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) | |||
314 | * is set only after acpi_pci_find_device() has been called for the | 314 | * is set only after acpi_pci_find_device() has been called for the |
315 | * given device. | 315 | * given device. |
316 | */ | 316 | */ |
317 | is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE | 317 | check_children = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE |
318 | || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; | 318 | || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; |
319 | /* Please ref to ACPI spec for the syntax of _ADR */ | 319 | /* Please ref to ACPI spec for the syntax of _ADR */ |
320 | addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); | 320 | addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); |
321 | *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge); | 321 | return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, |
322 | if (!*handle) | 322 | check_children); |
323 | return -ENODEV; | ||
324 | return 0; | ||
325 | } | 323 | } |
326 | 324 | ||
327 | static void pci_acpi_setup(struct device *dev) | 325 | static void pci_acpi_setup(struct device *dev) |
@@ -364,7 +362,7 @@ static bool pci_acpi_bus_match(struct device *dev) | |||
364 | static struct acpi_bus_type acpi_pci_bus = { | 362 | static struct acpi_bus_type acpi_pci_bus = { |
365 | .name = "PCI", | 363 | .name = "PCI", |
366 | .match = pci_acpi_bus_match, | 364 | .match = pci_acpi_bus_match, |
367 | .find_device = acpi_pci_find_device, | 365 | .find_companion = acpi_pci_find_companion, |
368 | .setup = pci_acpi_setup, | 366 | .setup = pci_acpi_setup, |
369 | .cleanup = pci_acpi_cleanup, | 367 | .cleanup = pci_acpi_cleanup, |
370 | }; | 368 | }; |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index e869ba698ac0..156d14e2587e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -328,20 +328,15 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) | |||
328 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); | 328 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); |
329 | } | 329 | } |
330 | 330 | ||
331 | static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) | 331 | static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev) |
332 | { | 332 | { |
333 | struct device *adev; | 333 | dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev), |
334 | struct acpi_device *acpi; | 334 | acpi_pnp_match); |
335 | 335 | if (!dev) | |
336 | adev = bus_find_device(&acpi_bus_type, NULL, | 336 | return NULL; |
337 | to_pnp_dev(dev), acpi_pnp_match); | ||
338 | if (!adev) | ||
339 | return -ENODEV; | ||
340 | 337 | ||
341 | acpi = to_acpi_device(adev); | 338 | put_device(dev); |
342 | *handle = acpi->handle; | 339 | return to_acpi_device(dev); |
343 | put_device(adev); | ||
344 | return 0; | ||
345 | } | 340 | } |
346 | 341 | ||
347 | /* complete initialization of a PNPACPI device includes having | 342 | /* complete initialization of a PNPACPI device includes having |
@@ -355,7 +350,7 @@ static bool acpi_pnp_bus_match(struct device *dev) | |||
355 | static struct acpi_bus_type __initdata acpi_pnp_bus = { | 350 | static struct acpi_bus_type __initdata acpi_pnp_bus = { |
356 | .name = "PNP", | 351 | .name = "PNP", |
357 | .match = acpi_pnp_bus_match, | 352 | .match = acpi_pnp_bus_match, |
358 | .find_device = acpi_pnp_find_device, | 353 | .find_companion = acpi_pnp_find_companion, |
359 | }; | 354 | }; |
360 | 355 | ||
361 | int pnpacpi_disabled __initdata; | 356 | int pnpacpi_disabled __initdata; |
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 11c656976cb5..f0155a39aaa3 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c | |||
@@ -126,7 +126,7 @@ out: | |||
126 | return ret; | 126 | return ret; |
127 | } | 127 | } |
128 | 128 | ||
129 | static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | 129 | static struct acpi_device *usb_acpi_find_companion(struct device *dev) |
130 | { | 130 | { |
131 | struct usb_device *udev; | 131 | struct usb_device *udev; |
132 | acpi_handle *parent_handle; | 132 | acpi_handle *parent_handle; |
@@ -168,16 +168,15 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
168 | break; | 168 | break; |
169 | } | 169 | } |
170 | 170 | ||
171 | return -ENODEV; | 171 | return NULL; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* root hub's parent is the usb hcd. */ | 174 | /* root hub's parent is the usb hcd. */ |
175 | parent_handle = ACPI_HANDLE(dev->parent); | 175 | return acpi_find_child_device(ACPI_COMPANION(dev->parent), |
176 | *handle = acpi_get_child(parent_handle, udev->portnum); | 176 | udev->portnum, false); |
177 | if (!*handle) | ||
178 | return -ENODEV; | ||
179 | return 0; | ||
180 | } else if (is_usb_port(dev)) { | 177 | } else if (is_usb_port(dev)) { |
178 | struct acpi_device *adev = NULL; | ||
179 | |||
181 | sscanf(dev_name(dev), "port%d", &port_num); | 180 | sscanf(dev_name(dev), "port%d", &port_num); |
182 | /* Get the struct usb_device point of port's hub */ | 181 | /* Get the struct usb_device point of port's hub */ |
183 | udev = to_usb_device(dev->parent->parent); | 182 | udev = to_usb_device(dev->parent->parent); |
@@ -193,26 +192,27 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
193 | 192 | ||
194 | raw_port_num = usb_hcd_find_raw_port_number(hcd, | 193 | raw_port_num = usb_hcd_find_raw_port_number(hcd, |
195 | port_num); | 194 | port_num); |
196 | *handle = acpi_get_child(ACPI_HANDLE(&udev->dev), | 195 | adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), |
197 | raw_port_num); | 196 | raw_port_num, false); |
198 | if (!*handle) | 197 | if (!adev) |
199 | return -ENODEV; | 198 | return NULL; |
200 | } else { | 199 | } else { |
201 | parent_handle = | 200 | parent_handle = |
202 | usb_get_hub_port_acpi_handle(udev->parent, | 201 | usb_get_hub_port_acpi_handle(udev->parent, |
203 | udev->portnum); | 202 | udev->portnum); |
204 | if (!parent_handle) | 203 | if (!parent_handle) |
205 | return -ENODEV; | 204 | return NULL; |
206 | 205 | ||
207 | *handle = acpi_get_child(parent_handle, port_num); | 206 | acpi_bus_get_device(parent_handle, &adev); |
208 | if (!*handle) | 207 | adev = acpi_find_child_device(adev, port_num, false); |
209 | return -ENODEV; | 208 | if (!adev) |
209 | return NULL; | ||
210 | } | 210 | } |
211 | usb_acpi_check_port_connect_type(udev, *handle, port_num); | 211 | usb_acpi_check_port_connect_type(udev, adev->handle, port_num); |
212 | } else | 212 | return adev; |
213 | return -ENODEV; | 213 | } |
214 | 214 | ||
215 | return 0; | 215 | return NULL; |
216 | } | 216 | } |
217 | 217 | ||
218 | static bool usb_acpi_bus_match(struct device *dev) | 218 | static bool usb_acpi_bus_match(struct device *dev) |
@@ -223,7 +223,7 @@ static bool usb_acpi_bus_match(struct device *dev) | |||
223 | static struct acpi_bus_type usb_acpi_bus = { | 223 | static struct acpi_bus_type usb_acpi_bus = { |
224 | .name = "USB", | 224 | .name = "USB", |
225 | .match = usb_acpi_bus_match, | 225 | .match = usb_acpi_bus_match, |
226 | .find_device = usb_acpi_find_device, | 226 | .find_companion = usb_acpi_find_companion, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | int usb_acpi_register(void) | 229 | int usb_acpi_register(void) |
diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index cd5bb0a507a2..80875fb770ed 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c | |||
@@ -266,7 +266,8 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, | |||
266 | if (!is_processor_present(handle)) | 266 | if (!is_processor_present(handle)) |
267 | break; | 267 | break; |
268 | 268 | ||
269 | if (!acpi_bus_get_device(handle, &device)) | 269 | acpi_bus_get_device(handle, &device); |
270 | if (acpi_device_enumerated(device)) | ||
270 | break; | 271 | break; |
271 | 272 | ||
272 | result = acpi_bus_scan(handle); | 273 | result = acpi_bus_scan(handle); |
@@ -274,8 +275,9 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, | |||
274 | pr_err(PREFIX "Unable to add the device\n"); | 275 | pr_err(PREFIX "Unable to add the device\n"); |
275 | break; | 276 | break; |
276 | } | 277 | } |
277 | result = acpi_bus_get_device(handle, &device); | 278 | device = NULL; |
278 | if (result) { | 279 | acpi_bus_get_device(handle, &device); |
280 | if (!acpi_device_enumerated(device)) { | ||
279 | pr_err(PREFIX "Missing device object\n"); | 281 | pr_err(PREFIX "Missing device object\n"); |
280 | break; | 282 | break; |
281 | } | 283 | } |
diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c index f2872a1bb096..f8d18626969a 100644 --- a/drivers/xen/xen-acpi-memhotplug.c +++ b/drivers/xen/xen-acpi-memhotplug.c | |||
@@ -168,7 +168,7 @@ static int acpi_memory_get_device(acpi_handle handle, | |||
168 | acpi_scan_lock_acquire(); | 168 | acpi_scan_lock_acquire(); |
169 | 169 | ||
170 | acpi_bus_get_device(handle, &device); | 170 | acpi_bus_get_device(handle, &device); |
171 | if (device) | 171 | if (acpi_device_enumerated(device)) |
172 | goto end; | 172 | goto end; |
173 | 173 | ||
174 | /* | 174 | /* |
@@ -181,8 +181,9 @@ static int acpi_memory_get_device(acpi_handle handle, | |||
181 | result = -EINVAL; | 181 | result = -EINVAL; |
182 | goto out; | 182 | goto out; |
183 | } | 183 | } |
184 | result = acpi_bus_get_device(handle, &device); | 184 | device = NULL; |
185 | if (result) { | 185 | acpi_bus_get_device(handle, &device); |
186 | if (!acpi_device_enumerated(device)) { | ||
186 | pr_warn(PREFIX "Missing device object\n"); | 187 | pr_warn(PREFIX "Missing device object\n"); |
187 | result = -EINVAL; | 188 | result = -EINVAL; |
188 | goto out; | 189 | goto out; |