diff options
Diffstat (limited to 'drivers/acpi')
| -rw-r--r-- | drivers/acpi/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/acpi/bgrt.c | 1 | ||||
| -rw-r--r-- | drivers/acpi/bus.c | 92 | ||||
| -rw-r--r-- | drivers/acpi/glue.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/pci_link.c | 12 | ||||
| -rw-r--r-- | drivers/acpi/power.c | 11 | ||||
| -rw-r--r-- | drivers/acpi/processor_perflib.c | 30 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 5 | ||||
| -rw-r--r-- | drivers/acpi/sleep.c | 63 | ||||
| -rw-r--r-- | drivers/acpi/utils.c | 30 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 33 |
11 files changed, 211 insertions, 70 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 47768ff87343..80998958cf45 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -208,7 +208,7 @@ config ACPI_IPMI | |||
| 208 | 208 | ||
| 209 | config ACPI_HOTPLUG_CPU | 209 | config ACPI_HOTPLUG_CPU |
| 210 | bool | 210 | bool |
| 211 | depends on ACPI_PROCESSOR && HOTPLUG_CPU | 211 | depends on EXPERIMENTAL && ACPI_PROCESSOR && HOTPLUG_CPU |
| 212 | select ACPI_CONTAINER | 212 | select ACPI_CONTAINER |
| 213 | default y | 213 | default y |
| 214 | 214 | ||
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 8cf6c46e99fb..6680df36b963 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 13 | #include <linux/sysfs.h> | 13 | #include <linux/sysfs.h> |
| 14 | #include <linux/io.h> | ||
| 14 | #include <acpi/acpi.h> | 15 | #include <acpi/acpi.h> |
| 15 | #include <acpi/acpi_bus.h> | 16 | #include <acpi/acpi_bus.h> |
| 16 | 17 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 3263b68cdfa3..adceafda9c17 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -182,41 +182,66 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); | |||
| 182 | Power Management | 182 | Power Management |
| 183 | -------------------------------------------------------------------------- */ | 183 | -------------------------------------------------------------------------- */ |
| 184 | 184 | ||
| 185 | static const char *state_string(int state) | ||
| 186 | { | ||
| 187 | switch (state) { | ||
| 188 | case ACPI_STATE_D0: | ||
| 189 | return "D0"; | ||
| 190 | case ACPI_STATE_D1: | ||
| 191 | return "D1"; | ||
| 192 | case ACPI_STATE_D2: | ||
| 193 | return "D2"; | ||
| 194 | case ACPI_STATE_D3_HOT: | ||
| 195 | return "D3hot"; | ||
| 196 | case ACPI_STATE_D3_COLD: | ||
| 197 | return "D3"; | ||
| 198 | default: | ||
| 199 | return "(unknown)"; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 185 | static int __acpi_bus_get_power(struct acpi_device *device, int *state) | 203 | static int __acpi_bus_get_power(struct acpi_device *device, int *state) |
| 186 | { | 204 | { |
| 187 | int result = 0; | 205 | int result = ACPI_STATE_UNKNOWN; |
| 188 | acpi_status status = 0; | ||
| 189 | unsigned long long psc = 0; | ||
| 190 | 206 | ||
| 191 | if (!device || !state) | 207 | if (!device || !state) |
| 192 | return -EINVAL; | 208 | return -EINVAL; |
| 193 | 209 | ||
| 194 | *state = ACPI_STATE_UNKNOWN; | 210 | if (!device->flags.power_manageable) { |
| 195 | |||
| 196 | if (device->flags.power_manageable) { | ||
| 197 | /* | ||
| 198 | * Get the device's power state either directly (via _PSC) or | ||
| 199 | * indirectly (via power resources). | ||
| 200 | */ | ||
| 201 | if (device->power.flags.power_resources) { | ||
| 202 | result = acpi_power_get_inferred_state(device, state); | ||
| 203 | if (result) | ||
| 204 | return result; | ||
| 205 | } else if (device->power.flags.explicit_get) { | ||
| 206 | status = acpi_evaluate_integer(device->handle, "_PSC", | ||
| 207 | NULL, &psc); | ||
| 208 | if (ACPI_FAILURE(status)) | ||
| 209 | return -ENODEV; | ||
| 210 | *state = (int)psc; | ||
| 211 | } | ||
| 212 | } else { | ||
| 213 | /* TBD: Non-recursive algorithm for walking up hierarchy. */ | 211 | /* TBD: Non-recursive algorithm for walking up hierarchy. */ |
| 214 | *state = device->parent ? | 212 | *state = device->parent ? |
| 215 | device->parent->power.state : ACPI_STATE_D0; | 213 | device->parent->power.state : ACPI_STATE_D0; |
| 214 | goto out; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Get the device's power state either directly (via _PSC) or | ||
| 219 | * indirectly (via power resources). | ||
| 220 | */ | ||
| 221 | if (device->power.flags.explicit_get) { | ||
| 222 | unsigned long long psc; | ||
| 223 | acpi_status status = acpi_evaluate_integer(device->handle, | ||
| 224 | "_PSC", NULL, &psc); | ||
| 225 | if (ACPI_FAILURE(status)) | ||
| 226 | return -ENODEV; | ||
| 227 | |||
| 228 | result = psc; | ||
| 216 | } | 229 | } |
| 230 | /* The test below covers ACPI_STATE_UNKNOWN too. */ | ||
| 231 | if (result <= ACPI_STATE_D2) { | ||
| 232 | ; /* Do nothing. */ | ||
| 233 | } else if (device->power.flags.power_resources) { | ||
| 234 | int error = acpi_power_get_inferred_state(device, &result); | ||
| 235 | if (error) | ||
| 236 | return error; | ||
| 237 | } else if (result == ACPI_STATE_D3_HOT) { | ||
| 238 | result = ACPI_STATE_D3; | ||
| 239 | } | ||
| 240 | *state = result; | ||
| 217 | 241 | ||
| 218 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", | 242 | out: |
| 219 | device->pnp.bus_id, *state)); | 243 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", |
| 244 | device->pnp.bus_id, state_string(*state))); | ||
| 220 | 245 | ||
| 221 | return 0; | 246 | return 0; |
| 222 | } | 247 | } |
| @@ -234,13 +259,14 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) | |||
| 234 | /* Make sure this is a valid target state */ | 259 | /* Make sure this is a valid target state */ |
| 235 | 260 | ||
| 236 | if (state == device->power.state) { | 261 | if (state == device->power.state) { |
| 237 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", | 262 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", |
| 238 | state)); | 263 | state_string(state))); |
| 239 | return 0; | 264 | return 0; |
| 240 | } | 265 | } |
| 241 | 266 | ||
| 242 | if (!device->power.states[state].flags.valid) { | 267 | if (!device->power.states[state].flags.valid) { |
| 243 | printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); | 268 | printk(KERN_WARNING PREFIX "Device does not support %s\n", |
| 269 | state_string(state)); | ||
| 244 | return -ENODEV; | 270 | return -ENODEV; |
| 245 | } | 271 | } |
| 246 | if (device->parent && (state < device->parent->power.state)) { | 272 | if (device->parent && (state < device->parent->power.state)) { |
| @@ -250,6 +276,10 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) | |||
| 250 | return -ENODEV; | 276 | return -ENODEV; |
| 251 | } | 277 | } |
| 252 | 278 | ||
| 279 | /* For D3cold we should execute _PS3, not _PS4. */ | ||
| 280 | if (state == ACPI_STATE_D3_COLD) | ||
| 281 | object_name[3] = '3'; | ||
| 282 | |||
| 253 | /* | 283 | /* |
| 254 | * Transition Power | 284 | * Transition Power |
| 255 | * ---------------- | 285 | * ---------------- |
| @@ -290,13 +320,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) | |||
| 290 | end: | 320 | end: |
| 291 | if (result) | 321 | if (result) |
| 292 | printk(KERN_WARNING PREFIX | 322 | printk(KERN_WARNING PREFIX |
| 293 | "Device [%s] failed to transition to D%d\n", | 323 | "Device [%s] failed to transition to %s\n", |
| 294 | device->pnp.bus_id, state); | 324 | device->pnp.bus_id, state_string(state)); |
| 295 | else { | 325 | else { |
| 296 | device->power.state = state; | 326 | device->power.state = state; |
| 297 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 327 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 298 | "Device [%s] transitioned to D%d\n", | 328 | "Device [%s] transitioned to %s\n", |
| 299 | device->pnp.bus_id, state)); | 329 | device->pnp.bus_id, state_string(state))); |
| 300 | } | 330 | } |
| 301 | 331 | ||
| 302 | return result; | 332 | return result; |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 29a4a5c8ee00..1564e0927c21 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -69,6 +69,7 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | |||
| 69 | up_read(&bus_type_sem); | 69 | up_read(&bus_type_sem); |
| 70 | return ret; | 70 | return ret; |
| 71 | } | 71 | } |
| 72 | EXPORT_SYMBOL_GPL(register_acpi_bus_type); | ||
| 72 | 73 | ||
| 73 | static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) | 74 | static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) |
| 74 | { | 75 | { |
| @@ -85,6 +86,7 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) | |||
| 85 | up_read(&bus_type_sem); | 86 | up_read(&bus_type_sem); |
| 86 | return ret; | 87 | return ret; |
| 87 | } | 88 | } |
| 89 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); | ||
| 88 | 90 | ||
| 89 | /* Get device's handler per its address under its parent */ | 91 | /* Get device's handler per its address under its parent */ |
| 90 | struct acpi_find_child { | 92 | struct acpi_find_child { |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 4a29763b8eb4..a12808259dfb 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -720,21 +720,21 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
| 720 | acpi_device_bid(device)); | 720 | acpi_device_bid(device)); |
| 721 | for (i = 0; i < link->irq.possible_count; i++) { | 721 | for (i = 0; i < link->irq.possible_count; i++) { |
| 722 | if (link->irq.active == link->irq.possible[i]) { | 722 | if (link->irq.active == link->irq.possible[i]) { |
| 723 | printk(" *%d", link->irq.possible[i]); | 723 | printk(KERN_CONT " *%d", link->irq.possible[i]); |
| 724 | found = 1; | 724 | found = 1; |
| 725 | } else | 725 | } else |
| 726 | printk(" %d", link->irq.possible[i]); | 726 | printk(KERN_CONT " %d", link->irq.possible[i]); |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | printk(")"); | 729 | printk(KERN_CONT ")"); |
| 730 | 730 | ||
| 731 | if (!found) | 731 | if (!found) |
| 732 | printk(" *%d", link->irq.active); | 732 | printk(KERN_CONT " *%d", link->irq.active); |
| 733 | 733 | ||
| 734 | if (!link->device->status.enabled) | 734 | if (!link->device->status.enabled) |
| 735 | printk(", disabled."); | 735 | printk(KERN_CONT ", disabled."); |
| 736 | 736 | ||
| 737 | printk("\n"); | 737 | printk(KERN_CONT "\n"); |
| 738 | 738 | ||
| 739 | list_add_tail(&link->list, &acpi_link_list); | 739 | list_add_tail(&link->list, &acpi_link_list); |
| 740 | 740 | ||
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 330bb4d75852..dd6d6a3c6780 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -631,7 +631,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) | |||
| 631 | * We know a device's inferred power state when all the resources | 631 | * We know a device's inferred power state when all the resources |
| 632 | * required for a given D-state are 'on'. | 632 | * required for a given D-state are 'on'. |
| 633 | */ | 633 | */ |
| 634 | for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) { | 634 | for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { |
| 635 | list = &device->power.states[i].resources; | 635 | list = &device->power.states[i].resources; |
| 636 | if (list->count < 1) | 636 | if (list->count < 1) |
| 637 | continue; | 637 | continue; |
| @@ -660,7 +660,7 @@ int acpi_power_on_resources(struct acpi_device *device, int state) | |||
| 660 | 660 | ||
| 661 | int acpi_power_transition(struct acpi_device *device, int state) | 661 | int acpi_power_transition(struct acpi_device *device, int state) |
| 662 | { | 662 | { |
| 663 | int result; | 663 | int result = 0; |
| 664 | 664 | ||
| 665 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) | 665 | if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) |
| 666 | return -EINVAL; | 666 | return -EINVAL; |
| @@ -679,8 +679,11 @@ int acpi_power_transition(struct acpi_device *device, int state) | |||
| 679 | * (e.g. so the device doesn't lose power while transitioning). Then, | 679 | * (e.g. so the device doesn't lose power while transitioning). Then, |
| 680 | * we dereference all power resources used in the current list. | 680 | * we dereference all power resources used in the current list. |
| 681 | */ | 681 | */ |
| 682 | result = acpi_power_on_list(&device->power.states[state].resources); | 682 | if (state < ACPI_STATE_D3_COLD) |
| 683 | if (!result) | 683 | result = acpi_power_on_list( |
| 684 | &device->power.states[state].resources); | ||
| 685 | |||
| 686 | if (!result && device->power.state < ACPI_STATE_D3_COLD) | ||
| 684 | acpi_power_off_list( | 687 | acpi_power_off_list( |
| 685 | &device->power.states[device->power.state].resources); | 688 | &device->power.states[device->power.state].resources); |
| 686 | 689 | ||
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 0af48a8554cd..a093dc163a42 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -333,6 +333,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) | |||
| 333 | struct acpi_buffer state = { 0, NULL }; | 333 | struct acpi_buffer state = { 0, NULL }; |
| 334 | union acpi_object *pss = NULL; | 334 | union acpi_object *pss = NULL; |
| 335 | int i; | 335 | int i; |
| 336 | int last_invalid = -1; | ||
| 336 | 337 | ||
| 337 | 338 | ||
| 338 | status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); | 339 | status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); |
| @@ -394,14 +395,33 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) | |||
| 394 | ((u32)(px->core_frequency * 1000) != | 395 | ((u32)(px->core_frequency * 1000) != |
| 395 | (px->core_frequency * 1000))) { | 396 | (px->core_frequency * 1000))) { |
| 396 | printk(KERN_ERR FW_BUG PREFIX | 397 | printk(KERN_ERR FW_BUG PREFIX |
| 397 | "Invalid BIOS _PSS frequency: 0x%llx MHz\n", | 398 | "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n", |
| 398 | px->core_frequency); | 399 | pr->id, px->core_frequency); |
| 399 | result = -EFAULT; | 400 | if (last_invalid == -1) |
| 400 | kfree(pr->performance->states); | 401 | last_invalid = i; |
| 401 | goto end; | 402 | } else { |
| 403 | if (last_invalid != -1) { | ||
| 404 | /* | ||
| 405 | * Copy this valid entry over last_invalid entry | ||
| 406 | */ | ||
| 407 | memcpy(&(pr->performance->states[last_invalid]), | ||
| 408 | px, sizeof(struct acpi_processor_px)); | ||
| 409 | ++last_invalid; | ||
| 410 | } | ||
| 402 | } | 411 | } |
| 403 | } | 412 | } |
| 404 | 413 | ||
| 414 | if (last_invalid == 0) { | ||
| 415 | printk(KERN_ERR FW_BUG PREFIX | ||
| 416 | "No valid BIOS _PSS frequency found for processor %d\n", pr->id); | ||
| 417 | result = -EFAULT; | ||
| 418 | kfree(pr->performance->states); | ||
| 419 | pr->performance->states = NULL; | ||
| 420 | } | ||
| 421 | |||
| 422 | if (last_invalid > 0) | ||
| 423 | pr->performance->state_count = last_invalid; | ||
| 424 | |||
| 405 | end: | 425 | end: |
| 406 | kfree(buffer.pointer); | 426 | kfree(buffer.pointer); |
| 407 | 427 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7417267e88fa..c8a1f3b68110 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -908,6 +908,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
| 908 | device->power.states[ACPI_STATE_D3].flags.valid = 1; | 908 | device->power.states[ACPI_STATE_D3].flags.valid = 1; |
| 909 | device->power.states[ACPI_STATE_D3].power = 0; | 909 | device->power.states[ACPI_STATE_D3].power = 0; |
| 910 | 910 | ||
| 911 | /* Set D3cold's explicit_set flag if _PS3 exists. */ | ||
| 912 | if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set) | ||
| 913 | device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1; | ||
| 914 | |||
| 911 | acpi_bus_init_power(device); | 915 | acpi_bus_init_power(device); |
| 912 | 916 | ||
| 913 | return 0; | 917 | return 0; |
| @@ -1563,6 +1567,7 @@ static int acpi_bus_scan_fixed(void) | |||
| 1563 | ACPI_BUS_TYPE_POWER_BUTTON, | 1567 | ACPI_BUS_TYPE_POWER_BUTTON, |
| 1564 | ACPI_STA_DEFAULT, | 1568 | ACPI_STA_DEFAULT, |
| 1565 | &ops); | 1569 | &ops); |
| 1570 | device_init_wakeup(&device->dev, true); | ||
| 1566 | } | 1571 | } |
| 1567 | 1572 | ||
| 1568 | if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { | 1573 | if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index eb6fd233764b..88561029cca8 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -57,6 +57,7 @@ MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); | |||
| 57 | MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); | 57 | MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); |
| 58 | 58 | ||
| 59 | static u8 sleep_states[ACPI_S_STATE_COUNT]; | 59 | static u8 sleep_states[ACPI_S_STATE_COUNT]; |
| 60 | static bool pwr_btn_event_pending; | ||
| 60 | 61 | ||
| 61 | static void acpi_sleep_tts_switch(u32 acpi_state) | 62 | static void acpi_sleep_tts_switch(u32 acpi_state) |
| 62 | { | 63 | { |
| @@ -93,11 +94,9 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
| 93 | #ifdef CONFIG_ACPI_SLEEP | 94 | #ifdef CONFIG_ACPI_SLEEP |
| 94 | /* do we have a wakeup address for S2 and S3? */ | 95 | /* do we have a wakeup address for S2 and S3? */ |
| 95 | if (acpi_state == ACPI_STATE_S3) { | 96 | if (acpi_state == ACPI_STATE_S3) { |
| 96 | if (!acpi_wakeup_address) { | 97 | if (!acpi_wakeup_address) |
| 97 | return -EFAULT; | 98 | return -EFAULT; |
| 98 | } | 99 | acpi_set_firmware_waking_vector(acpi_wakeup_address); |
| 99 | acpi_set_firmware_waking_vector( | ||
| 100 | (acpi_physical_address)acpi_wakeup_address); | ||
| 101 | 100 | ||
| 102 | } | 101 | } |
| 103 | ACPI_FLUSH_CPU_CACHE(); | 102 | ACPI_FLUSH_CPU_CACHE(); |
| @@ -186,6 +185,14 @@ static int acpi_pm_prepare(void) | |||
| 186 | return error; | 185 | return error; |
| 187 | } | 186 | } |
| 188 | 187 | ||
| 188 | static int find_powerf_dev(struct device *dev, void *data) | ||
| 189 | { | ||
| 190 | struct acpi_device *device = to_acpi_device(dev); | ||
| 191 | const char *hid = acpi_device_hid(device); | ||
| 192 | |||
| 193 | return !strcmp(hid, ACPI_BUTTON_HID_POWERF); | ||
| 194 | } | ||
| 195 | |||
| 189 | /** | 196 | /** |
| 190 | * acpi_pm_finish - Instruct the platform to leave a sleep state. | 197 | * acpi_pm_finish - Instruct the platform to leave a sleep state. |
| 191 | * | 198 | * |
| @@ -194,6 +201,7 @@ static int acpi_pm_prepare(void) | |||
| 194 | */ | 201 | */ |
| 195 | static void acpi_pm_finish(void) | 202 | static void acpi_pm_finish(void) |
| 196 | { | 203 | { |
| 204 | struct device *pwr_btn_dev; | ||
| 197 | u32 acpi_state = acpi_target_sleep_state; | 205 | u32 acpi_state = acpi_target_sleep_state; |
| 198 | 206 | ||
| 199 | acpi_ec_unblock_transactions(); | 207 | acpi_ec_unblock_transactions(); |
| @@ -211,6 +219,23 @@ static void acpi_pm_finish(void) | |||
| 211 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 219 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
| 212 | 220 | ||
| 213 | acpi_target_sleep_state = ACPI_STATE_S0; | 221 | acpi_target_sleep_state = ACPI_STATE_S0; |
| 222 | |||
| 223 | /* If we were woken with the fixed power button, provide a small | ||
| 224 | * hint to userspace in the form of a wakeup event on the fixed power | ||
| 225 | * button device (if it can be found). | ||
| 226 | * | ||
| 227 | * We delay the event generation til now, as the PM layer requires | ||
| 228 | * timekeeping to be running before we generate events. */ | ||
| 229 | if (!pwr_btn_event_pending) | ||
| 230 | return; | ||
| 231 | |||
| 232 | pwr_btn_event_pending = false; | ||
| 233 | pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL, | ||
| 234 | find_powerf_dev); | ||
| 235 | if (pwr_btn_dev) { | ||
| 236 | pm_wakeup_event(pwr_btn_dev, 0); | ||
| 237 | put_device(pwr_btn_dev); | ||
| 238 | } | ||
| 214 | } | 239 | } |
| 215 | 240 | ||
| 216 | /** | 241 | /** |
| @@ -300,9 +325,23 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
| 300 | /* ACPI 3.0 specs (P62) says that it's the responsibility | 325 | /* ACPI 3.0 specs (P62) says that it's the responsibility |
| 301 | * of the OSPM to clear the status bit [ implying that the | 326 | * of the OSPM to clear the status bit [ implying that the |
| 302 | * POWER_BUTTON event should not reach userspace ] | 327 | * POWER_BUTTON event should not reach userspace ] |
| 328 | * | ||
| 329 | * However, we do generate a small hint for userspace in the form of | ||
| 330 | * a wakeup event. We flag this condition for now and generate the | ||
| 331 | * event later, as we're currently too early in resume to be able to | ||
| 332 | * generate wakeup events. | ||
| 303 | */ | 333 | */ |
| 304 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) | 334 | if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) { |
| 305 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); | 335 | acpi_event_status pwr_btn_status; |
| 336 | |||
| 337 | acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); | ||
| 338 | |||
| 339 | if (pwr_btn_status & ACPI_EVENT_FLAG_SET) { | ||
| 340 | acpi_clear_event(ACPI_EVENT_POWER_BUTTON); | ||
| 341 | /* Flag for later */ | ||
| 342 | pwr_btn_event_pending = true; | ||
| 343 | } | ||
| 344 | } | ||
| 306 | 345 | ||
| 307 | /* | 346 | /* |
| 308 | * Disable and clear GPE status before interrupt is enabled. Some GPEs | 347 | * Disable and clear GPE status before interrupt is enabled. Some GPEs |
| @@ -732,8 +771,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
| 732 | * can wake the system. _S0W may be valid, too. | 771 | * can wake the system. _S0W may be valid, too. |
| 733 | */ | 772 | */ |
| 734 | if (acpi_target_sleep_state == ACPI_STATE_S0 || | 773 | if (acpi_target_sleep_state == ACPI_STATE_S0 || |
| 735 | (device_may_wakeup(dev) && | 774 | (device_may_wakeup(dev) && adev->wakeup.flags.valid && |
| 736 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { | 775 | adev->wakeup.sleep_state >= acpi_target_sleep_state)) { |
| 737 | acpi_status status; | 776 | acpi_status status; |
| 738 | 777 | ||
| 739 | acpi_method[3] = 'W'; | 778 | acpi_method[3] = 'W'; |
| @@ -887,7 +926,7 @@ int __init acpi_sleep_init(void) | |||
| 887 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 926 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
| 888 | if (ACPI_SUCCESS(status)) { | 927 | if (ACPI_SUCCESS(status)) { |
| 889 | sleep_states[i] = 1; | 928 | sleep_states[i] = 1; |
| 890 | printk(" S%d", i); | 929 | printk(KERN_CONT " S%d", i); |
| 891 | } | 930 | } |
| 892 | } | 931 | } |
| 893 | 932 | ||
| @@ -901,7 +940,7 @@ int __init acpi_sleep_init(void) | |||
| 901 | hibernation_set_ops(old_suspend_ordering ? | 940 | hibernation_set_ops(old_suspend_ordering ? |
| 902 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 941 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
| 903 | sleep_states[ACPI_STATE_S4] = 1; | 942 | sleep_states[ACPI_STATE_S4] = 1; |
| 904 | printk(" S4"); | 943 | printk(KERN_CONT " S4"); |
| 905 | if (!nosigcheck) { | 944 | if (!nosigcheck) { |
| 906 | acpi_get_table(ACPI_SIG_FACS, 1, | 945 | acpi_get_table(ACPI_SIG_FACS, 1, |
| 907 | (struct acpi_table_header **)&facs); | 946 | (struct acpi_table_header **)&facs); |
| @@ -914,11 +953,11 @@ int __init acpi_sleep_init(void) | |||
| 914 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 953 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
| 915 | if (ACPI_SUCCESS(status)) { | 954 | if (ACPI_SUCCESS(status)) { |
| 916 | sleep_states[ACPI_STATE_S5] = 1; | 955 | sleep_states[ACPI_STATE_S5] = 1; |
| 917 | printk(" S5"); | 956 | printk(KERN_CONT " S5"); |
| 918 | pm_power_off_prepare = acpi_power_off_prepare; | 957 | pm_power_off_prepare = acpi_power_off_prepare; |
| 919 | pm_power_off = acpi_power_off; | 958 | pm_power_off = acpi_power_off; |
| 920 | } | 959 | } |
| 921 | printk(")\n"); | 960 | printk(KERN_CONT ")\n"); |
| 922 | /* | 961 | /* |
| 923 | * Register the tts_notifier to reboot notifier list so that the _TTS | 962 | * Register the tts_notifier to reboot notifier list so that the _TTS |
| 924 | * object can also be evaluated when the system enters S5. | 963 | * object can also be evaluated when the system enters S5. |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index b002a471c5d4..adbbc1c80a26 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
| @@ -382,3 +382,33 @@ acpi_evaluate_reference(acpi_handle handle, | |||
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | EXPORT_SYMBOL(acpi_evaluate_reference); | 384 | EXPORT_SYMBOL(acpi_evaluate_reference); |
| 385 | |||
| 386 | acpi_status | ||
| 387 | acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld) | ||
| 388 | { | ||
| 389 | acpi_status status; | ||
| 390 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 391 | union acpi_object *output; | ||
| 392 | |||
| 393 | status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer); | ||
| 394 | |||
| 395 | if (ACPI_FAILURE(status)) | ||
| 396 | return status; | ||
| 397 | |||
| 398 | output = buffer.pointer; | ||
| 399 | |||
| 400 | if (!output || output->type != ACPI_TYPE_PACKAGE | ||
| 401 | || !output->package.count | ||
| 402 | || output->package.elements[0].type != ACPI_TYPE_BUFFER | ||
| 403 | || output->package.elements[0].buffer.length > sizeof(*pld)) { | ||
| 404 | status = AE_TYPE; | ||
| 405 | goto out; | ||
| 406 | } | ||
| 407 | |||
| 408 | memcpy(pld, output->package.elements[0].buffer.pointer, | ||
| 409 | output->package.elements[0].buffer.length); | ||
| 410 | out: | ||
| 411 | kfree(buffer.pointer); | ||
| 412 | return status; | ||
| 413 | } | ||
| 414 | EXPORT_SYMBOL(acpi_get_physical_device_location); | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9577b6fa2650..a576575617d7 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -1687,10 +1687,6 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1687 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | 1687 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); |
| 1688 | set_bit(KEY_DISPLAY_OFF, input->keybit); | 1688 | set_bit(KEY_DISPLAY_OFF, input->keybit); |
| 1689 | 1689 | ||
| 1690 | error = input_register_device(input); | ||
| 1691 | if (error) | ||
| 1692 | goto err_stop_video; | ||
| 1693 | |||
| 1694 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1690 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
| 1695 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1691 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
| 1696 | video->flags.multihead ? "yes" : "no", | 1692 | video->flags.multihead ? "yes" : "no", |
| @@ -1701,12 +1697,16 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1701 | video->pm_nb.priority = 0; | 1697 | video->pm_nb.priority = 0; |
| 1702 | error = register_pm_notifier(&video->pm_nb); | 1698 | error = register_pm_notifier(&video->pm_nb); |
| 1703 | if (error) | 1699 | if (error) |
| 1704 | goto err_unregister_input_dev; | 1700 | goto err_stop_video; |
| 1701 | |||
| 1702 | error = input_register_device(input); | ||
| 1703 | if (error) | ||
| 1704 | goto err_unregister_pm_notifier; | ||
| 1705 | 1705 | ||
| 1706 | return 0; | 1706 | return 0; |
| 1707 | 1707 | ||
| 1708 | err_unregister_input_dev: | 1708 | err_unregister_pm_notifier: |
| 1709 | input_unregister_device(input); | 1709 | unregister_pm_notifier(&video->pm_nb); |
| 1710 | err_stop_video: | 1710 | err_stop_video: |
| 1711 | acpi_video_bus_stop_devices(video); | 1711 | acpi_video_bus_stop_devices(video); |
| 1712 | err_free_input_dev: | 1712 | err_free_input_dev: |
| @@ -1743,9 +1743,18 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
| 1743 | return 0; | 1743 | return 0; |
| 1744 | } | 1744 | } |
| 1745 | 1745 | ||
| 1746 | static int __init is_i740(struct pci_dev *dev) | ||
| 1747 | { | ||
| 1748 | if (dev->device == 0x00D1) | ||
| 1749 | return 1; | ||
| 1750 | if (dev->device == 0x7000) | ||
| 1751 | return 1; | ||
| 1752 | return 0; | ||
| 1753 | } | ||
| 1754 | |||
| 1746 | static int __init intel_opregion_present(void) | 1755 | static int __init intel_opregion_present(void) |
| 1747 | { | 1756 | { |
| 1748 | #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) | 1757 | int opregion = 0; |
| 1749 | struct pci_dev *dev = NULL; | 1758 | struct pci_dev *dev = NULL; |
| 1750 | u32 address; | 1759 | u32 address; |
| 1751 | 1760 | ||
| @@ -1754,13 +1763,15 @@ static int __init intel_opregion_present(void) | |||
| 1754 | continue; | 1763 | continue; |
| 1755 | if (dev->vendor != PCI_VENDOR_ID_INTEL) | 1764 | if (dev->vendor != PCI_VENDOR_ID_INTEL) |
| 1756 | continue; | 1765 | continue; |
| 1766 | /* We don't want to poke around undefined i740 registers */ | ||
| 1767 | if (is_i740(dev)) | ||
| 1768 | continue; | ||
| 1757 | pci_read_config_dword(dev, 0xfc, &address); | 1769 | pci_read_config_dword(dev, 0xfc, &address); |
| 1758 | if (!address) | 1770 | if (!address) |
| 1759 | continue; | 1771 | continue; |
| 1760 | return 1; | 1772 | opregion = 1; |
| 1761 | } | 1773 | } |
| 1762 | #endif | 1774 | return opregion; |
| 1763 | return 0; | ||
| 1764 | } | 1775 | } |
| 1765 | 1776 | ||
| 1766 | int acpi_video_register(void) | 1777 | int acpi_video_register(void) |
