diff options
28 files changed, 654 insertions, 629 deletions
diff --git a/Documentation/acpi/namespace.txt b/Documentation/acpi/namespace.txt index 260f6a3661fa..1860cb3865c6 100644 --- a/Documentation/acpi/namespace.txt +++ b/Documentation/acpi/namespace.txt | |||
| @@ -235,10 +235,6 @@ Wysocki <rafael.j.wysocki@intel.com>. | |||
| 235 | named object's type in the second column). In that case the object's | 235 | named object's type in the second column). In that case the object's |
| 236 | directory in sysfs will contain the 'path' attribute whose value is | 236 | directory in sysfs will contain the 'path' attribute whose value is |
| 237 | the full path to the node from the namespace root. | 237 | the full path to the node from the namespace root. |
| 238 | struct acpi_device objects are created for the ACPI namespace nodes | ||
| 239 | whose _STA control methods return PRESENT or FUNCTIONING. The power | ||
| 240 | resource nodes or nodes without _STA are assumed to be both PRESENT | ||
| 241 | and FUNCTIONING. | ||
| 242 | F: | 238 | F: |
| 243 | The struct acpi_device object is created for a fixed hardware | 239 | The struct acpi_device object is created for a fixed hardware |
| 244 | feature (as indicated by the fixed feature flag's name in the second | 240 | feature (as indicated by the fixed feature flag's name in the second |
| @@ -340,7 +336,7 @@ Wysocki <rafael.j.wysocki@intel.com>. | |||
| 340 | | +-------------+-------+----------------+ | 336 | | +-------------+-------+----------------+ |
| 341 | | | | 337 | | | |
| 342 | | | +- - - - - - - +- - - - - - +- - - - - - - -+ | 338 | | | +- - - - - - - +- - - - - - +- - - - - - - -+ |
| 343 | | +-| * PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: | | 339 | | +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: | |
| 344 | | | +- - - - - - - +- - - - - - +- - - - - - - -+ | 340 | | | +- - - - - - - +- - - - - - +- - - - - - - -+ |
| 345 | | | | 341 | | | |
| 346 | | | +------------+------------+-----------------------+ | 342 | | | +------------+------------+-----------------------+ |
| @@ -390,6 +386,3 @@ Wysocki <rafael.j.wysocki@intel.com>. | |||
| 390 | attribute (as described earlier in this document). | 386 | attribute (as described earlier in this document). |
| 391 | NOTE: N/A indicates the device object does not have the 'path' or the | 387 | NOTE: N/A indicates the device object does not have the 'path' or the |
| 392 | 'modalias' attribute. | 388 | 'modalias' attribute. |
| 393 | NOTE: The PNP0C0D device listed above is highlighted (marked by "*") | ||
| 394 | to indicate it will be created only when its _STA methods return | ||
| 395 | PRESENT or FUNCTIONING. | ||
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; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index fa42b45461ad..e4ab7be65637 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -89,17 +89,11 @@ struct acpi_device; | |||
| 89 | * ----------------- | 89 | * ----------------- |
| 90 | */ | 90 | */ |
| 91 | 91 | ||
| 92 | enum acpi_hotplug_mode { | ||
| 93 | AHM_GENERIC = 0, | ||
| 94 | AHM_CONTAINER, | ||
| 95 | AHM_COUNT | ||
| 96 | }; | ||
| 97 | |||
| 98 | struct acpi_hotplug_profile { | 92 | struct acpi_hotplug_profile { |
| 99 | struct kobject kobj; | 93 | struct kobject kobj; |
| 94 | int (*scan_dependent)(struct acpi_device *adev); | ||
| 100 | bool enabled:1; | 95 | bool enabled:1; |
| 101 | bool ignore:1; | 96 | bool demand_offline:1; |
| 102 | enum acpi_hotplug_mode mode; | ||
| 103 | }; | 97 | }; |
| 104 | 98 | ||
| 105 | static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( | 99 | static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile( |
| @@ -167,8 +161,10 @@ struct acpi_device_flags { | |||
| 167 | u32 ejectable:1; | 161 | u32 ejectable:1; |
| 168 | u32 power_manageable:1; | 162 | u32 power_manageable:1; |
| 169 | u32 match_driver:1; | 163 | u32 match_driver:1; |
| 164 | u32 initialized:1; | ||
| 165 | u32 visited:1; | ||
| 170 | u32 no_hotplug:1; | 166 | u32 no_hotplug:1; |
| 171 | u32 reserved:26; | 167 | u32 reserved:24; |
| 172 | }; | 168 | }; |
| 173 | 169 | ||
| 174 | /* File System */ | 170 | /* File System */ |
| @@ -298,6 +294,7 @@ struct acpi_device { | |||
| 298 | struct list_head children; | 294 | struct list_head children; |
| 299 | struct list_head node; | 295 | struct list_head node; |
| 300 | struct list_head wakeup_list; | 296 | struct list_head wakeup_list; |
| 297 | struct list_head del_list; | ||
| 301 | struct acpi_device_status status; | 298 | struct acpi_device_status status; |
| 302 | struct acpi_device_flags flags; | 299 | struct acpi_device_flags flags; |
| 303 | struct acpi_device_pnp pnp; | 300 | struct acpi_device_pnp pnp; |
| @@ -323,6 +320,11 @@ static inline void *acpi_driver_data(struct acpi_device *d) | |||
| 323 | #define to_acpi_device(d) container_of(d, struct acpi_device, dev) | 320 | #define to_acpi_device(d) container_of(d, struct acpi_device, dev) |
| 324 | #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) | 321 | #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) |
| 325 | 322 | ||
| 323 | static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) | ||
| 324 | { | ||
| 325 | *((u32 *)&adev->status) = sta; | ||
| 326 | } | ||
| 327 | |||
| 326 | /* acpi_device.dev.bus == &acpi_bus_type */ | 328 | /* acpi_device.dev.bus == &acpi_bus_type */ |
| 327 | extern struct bus_type acpi_bus_type; | 329 | extern struct bus_type acpi_bus_type; |
| 328 | 330 | ||
| @@ -385,6 +387,11 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
| 385 | int acpi_create_dir(struct acpi_device *); | 387 | int acpi_create_dir(struct acpi_device *); |
| 386 | void acpi_remove_dir(struct acpi_device *); | 388 | void acpi_remove_dir(struct acpi_device *); |
| 387 | 389 | ||
| 390 | static inline bool acpi_device_enumerated(struct acpi_device *adev) | ||
| 391 | { | ||
| 392 | return adev && adev->flags.initialized && adev->flags.visited; | ||
| 393 | } | ||
| 394 | |||
| 388 | typedef void (*acpi_hp_callback)(void *data, u32 src); | 395 | typedef void (*acpi_hp_callback)(void *data, u32 src); |
| 389 | 396 | ||
| 390 | acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); | 397 | acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src); |
| @@ -408,7 +415,7 @@ struct acpi_bus_type { | |||
| 408 | struct list_head list; | 415 | struct list_head list; |
| 409 | const char *name; | 416 | const char *name; |
| 410 | bool (*match)(struct device *dev); | 417 | bool (*match)(struct device *dev); |
| 411 | int (*find_device) (struct device *, acpi_handle *); | 418 | struct acpi_device * (*find_companion)(struct device *); |
| 412 | void (*setup)(struct device *); | 419 | void (*setup)(struct device *); |
| 413 | void (*cleanup)(struct device *); | 420 | void (*cleanup)(struct device *); |
| 414 | }; | 421 | }; |
| @@ -427,12 +434,9 @@ struct acpi_pci_root { | |||
| 427 | }; | 434 | }; |
| 428 | 435 | ||
| 429 | /* helper */ | 436 | /* helper */ |
| 430 | acpi_handle acpi_find_child(acpi_handle, u64, bool); | 437 | |
| 431 | static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr) | 438 | struct acpi_device *acpi_find_child_device(struct acpi_device *parent, |
| 432 | { | 439 | u64 address, bool check_children); |
| 433 | return acpi_find_child(handle, addr, false); | ||
| 434 | } | ||
| 435 | void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr); | ||
| 436 | int acpi_is_root_bridge(acpi_handle); | 440 | int acpi_is_root_bridge(acpi_handle); |
| 437 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); | 441 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); |
| 438 | 442 | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7aaf7315d33d..3e3247d95fd9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -54,6 +54,12 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) | |||
| 54 | #define ACPI_COMPANION_SET(dev, adev) ACPI_COMPANION(dev) = (adev) | 54 | #define ACPI_COMPANION_SET(dev, adev) ACPI_COMPANION(dev) = (adev) |
| 55 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) | 55 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) |
| 56 | 56 | ||
| 57 | static inline void acpi_preset_companion(struct device *dev, | ||
| 58 | struct acpi_device *parent, u64 addr) | ||
| 59 | { | ||
| 60 | ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, NULL)); | ||
| 61 | } | ||
| 62 | |||
| 57 | static inline const char *acpi_dev_name(struct acpi_device *adev) | 63 | static inline const char *acpi_dev_name(struct acpi_device *adev) |
| 58 | { | 64 | { |
| 59 | return dev_name(&adev->dev); | 65 | return dev_name(&adev->dev); |
diff --git a/include/linux/container.h b/include/linux/container.h new file mode 100644 index 000000000000..3c03e6fd2035 --- /dev/null +++ b/include/linux/container.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * Definitions for container bus type. | ||
| 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/device.h> | ||
| 13 | |||
| 14 | /* drivers/base/power/container.c */ | ||
| 15 | extern struct bus_type container_subsys; | ||
| 16 | |||
| 17 | struct container_dev { | ||
| 18 | struct device dev; | ||
| 19 | int (*offline)(struct container_dev *cdev); | ||
| 20 | }; | ||
| 21 | |||
| 22 | static inline struct container_dev *to_container_dev(struct device *dev) | ||
| 23 | { | ||
| 24 | return container_of(dev, struct container_dev, dev); | ||
| 25 | } | ||
