diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
| -rw-r--r-- | drivers/acpi/processor_idle.c | 114 |
1 files changed, 60 insertions, 54 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index bbd066e7f854..5939e7f7d8e9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 34 | #include <linux/cpufreq.h> | 34 | #include <linux/cpufreq.h> |
| 35 | #include <linux/slab.h> | ||
| 35 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
| 36 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
| 37 | #include <linux/acpi.h> | 38 | #include <linux/acpi.h> |
| @@ -110,6 +111,14 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { | |||
| 110 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), | 111 | DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), |
| 111 | DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, | 112 | DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, |
| 112 | (void *)2}, | 113 | (void *)2}, |
| 114 | { set_max_cstate, "Pavilion zv5000", { | ||
| 115 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 116 | DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")}, | ||
| 117 | (void *)1}, | ||
| 118 | { set_max_cstate, "Asus L8400B", { | ||
| 119 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), | ||
| 120 | DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, | ||
| 121 | (void *)1}, | ||
| 113 | {}, | 122 | {}, |
| 114 | }; | 123 | }; |
| 115 | 124 | ||
| @@ -164,7 +173,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr, | |||
| 164 | pr->power.timer_broadcast_on_state = state; | 173 | pr->power.timer_broadcast_on_state = state; |
| 165 | } | 174 | } |
| 166 | 175 | ||
| 167 | static void lapic_timer_propagate_broadcast(void *arg) | 176 | static void __lapic_timer_propagate_broadcast(void *arg) |
| 168 | { | 177 | { |
| 169 | struct acpi_processor *pr = (struct acpi_processor *) arg; | 178 | struct acpi_processor *pr = (struct acpi_processor *) arg; |
| 170 | unsigned long reason; | 179 | unsigned long reason; |
| @@ -175,6 +184,12 @@ static void lapic_timer_propagate_broadcast(void *arg) | |||
| 175 | clockevents_notify(reason, &pr->id); | 184 | clockevents_notify(reason, &pr->id); |
| 176 | } | 185 | } |
| 177 | 186 | ||
| 187 | static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) | ||
| 188 | { | ||
| 189 | smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, | ||
| 190 | (void *)pr, 1); | ||
| 191 | } | ||
| 192 | |||
| 178 | /* Power(C) State timer broadcast control */ | 193 | /* Power(C) State timer broadcast control */ |
| 179 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, | 194 | static void lapic_timer_state_broadcast(struct acpi_processor *pr, |
| 180 | struct acpi_processor_cx *cx, | 195 | struct acpi_processor_cx *cx, |
| @@ -299,6 +314,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
| 299 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; | 314 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; |
| 300 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; | 315 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; |
| 301 | 316 | ||
| 317 | /* | ||
| 318 | * FADT specified C2 latency must be less than or equal to | ||
| 319 | * 100 microseconds. | ||
| 320 | */ | ||
| 321 | if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
| 322 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 323 | "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); | ||
| 324 | /* invalidate C2 */ | ||
| 325 | pr->power.states[ACPI_STATE_C2].address = 0; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* | ||
| 329 | * FADT supplied C3 latency must be less than or equal to | ||
| 330 | * 1000 microseconds. | ||
| 331 | */ | ||
| 332 | if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
| 333 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 334 | "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); | ||
| 335 | /* invalidate C3 */ | ||
| 336 | pr->power.states[ACPI_STATE_C3].address = 0; | ||
| 337 | } | ||
| 338 | |||
| 302 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 339 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 303 | "lvl2[0x%08x] lvl3[0x%08x]\n", | 340 | "lvl2[0x%08x] lvl3[0x%08x]\n", |
| 304 | pr->power.states[ACPI_STATE_C2].address, | 341 | pr->power.states[ACPI_STATE_C2].address, |
| @@ -324,7 +361,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) | |||
| 324 | static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | 361 | static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) |
| 325 | { | 362 | { |
| 326 | acpi_status status = 0; | 363 | acpi_status status = 0; |
| 327 | acpi_integer count; | 364 | u64 count; |
| 328 | int current_count; | 365 | int current_count; |
| 329 | int i; | 366 | int i; |
| 330 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 367 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| @@ -488,33 +525,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
| 488 | return status; | 525 | return status; |
| 489 | } | 526 | } |
| 490 | 527 | ||
| 491 | static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | ||
| 492 | { | ||
| 493 | |||
| 494 | if (!cx->address) | ||
| 495 | return; | ||
| 496 | |||
| 497 | /* | ||
| 498 | * C2 latency must be less than or equal to 100 | ||
| 499 | * microseconds. | ||
| 500 | */ | ||
| 501 | else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
| 502 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 503 | "latency too large [%d]\n", cx->latency)); | ||
| 504 | return; | ||
| 505 | } | ||
| 506 | |||
| 507 | /* | ||
| 508 | * Otherwise we've met all of our C2 requirements. | ||
| 509 | * Normalize the C2 latency to expidite policy | ||
| 510 | */ | ||
| 511 | cx->valid = 1; | ||
| 512 | |||
| 513 | cx->latency_ticks = cx->latency; | ||
| 514 | |||
| 515 | return; | ||
| 516 | } | ||
| 517 | |||
| 518 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 528 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, |
| 519 | struct acpi_processor_cx *cx) | 529 | struct acpi_processor_cx *cx) |
| 520 | { | 530 | { |
| @@ -526,16 +536,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
| 526 | return; | 536 | return; |
| 527 | 537 | ||
| 528 | /* | 538 | /* |
| 529 | * C3 latency must be less than or equal to 1000 | ||
| 530 | * microseconds. | ||
| 531 | */ | ||
| 532 | else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
| 533 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 534 | "latency too large [%d]\n", cx->latency)); | ||
| 535 | return; | ||
| 536 | } | ||
| 537 | |||
| 538 | /* | ||
| 539 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) | 539 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) |
| 540 | * DMA transfers are used by any ISA device to avoid livelock. | 540 | * DMA transfers are used by any ISA device to avoid livelock. |
| 541 | * Note that we could disable Type-F DMA (as recommended by | 541 | * Note that we could disable Type-F DMA (as recommended by |
| @@ -623,7 +623,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 623 | break; | 623 | break; |
| 624 | 624 | ||
| 625 | case ACPI_STATE_C2: | 625 | case ACPI_STATE_C2: |
| 626 | acpi_processor_power_verify_c2(cx); | 626 | if (!cx->address) |
| 627 | break; | ||
| 628 | cx->valid = 1; | ||
| 629 | cx->latency_ticks = cx->latency; /* Normalize latency */ | ||
| 627 | break; | 630 | break; |
| 628 | 631 | ||
| 629 | case ACPI_STATE_C3: | 632 | case ACPI_STATE_C3: |
| @@ -638,8 +641,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 638 | working++; | 641 | working++; |
| 639 | } | 642 | } |
| 640 | 643 | ||
| 641 | smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, | 644 | lapic_timer_propagate_broadcast(pr); |
| 642 | pr, 1); | ||
| 643 | 645 | ||
| 644 | return (working); | 646 | return (working); |
| 645 | } | 647 | } |
| @@ -879,12 +881,14 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
| 879 | return(acpi_idle_enter_c1(dev, state)); | 881 | return(acpi_idle_enter_c1(dev, state)); |
| 880 | 882 | ||
| 881 | local_irq_disable(); | 883 | local_irq_disable(); |
| 882 | current_thread_info()->status &= ~TS_POLLING; | 884 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
| 883 | /* | 885 | current_thread_info()->status &= ~TS_POLLING; |
| 884 | * TS_POLLING-cleared state must be visible before we test | 886 | /* |
| 885 | * NEED_RESCHED: | 887 | * TS_POLLING-cleared state must be visible before we test |
| 886 | */ | 888 | * NEED_RESCHED: |
| 887 | smp_mb(); | 889 | */ |
| 890 | smp_mb(); | ||
| 891 | } | ||
| 888 | 892 | ||
| 889 | if (unlikely(need_resched())) { | 893 | if (unlikely(need_resched())) { |
| 890 | current_thread_info()->status |= TS_POLLING; | 894 | current_thread_info()->status |= TS_POLLING; |
| @@ -964,12 +968,14 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
| 964 | } | 968 | } |
| 965 | 969 | ||
| 966 | local_irq_disable(); | 970 | local_irq_disable(); |
| 967 | current_thread_info()->status &= ~TS_POLLING; | 971 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
| 968 | /* | 972 | current_thread_info()->status &= ~TS_POLLING; |
| 969 | * TS_POLLING-cleared state must be visible before we test | 973 | /* |
| 970 | * NEED_RESCHED: | 974 | * TS_POLLING-cleared state must be visible before we test |
| 971 | */ | 975 | * NEED_RESCHED: |
| 972 | smp_mb(); | 976 | */ |
| 977 | smp_mb(); | ||
| 978 | } | ||
| 973 | 979 | ||
| 974 | if (unlikely(need_resched())) { | 980 | if (unlikely(need_resched())) { |
| 975 | current_thread_info()->status |= TS_POLLING; | 981 | current_thread_info()->status |= TS_POLLING; |
