diff options
| author | Len Brown <len.brown@intel.com> | 2006-10-14 02:25:59 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2006-10-14 02:25:59 -0400 |
| commit | d7321ad2936c48a95af5187d4d676118cb59aa5f (patch) | |
| tree | 238e1ca71ca6cc148204d00335f16cff329d7903 | |
| parent | 1d5b30fc339fe2865599c70486abccc18200317d (diff) | |
| parent | 991528d7348667924176f3e29addea0675298944 (diff) | |
Pull mwait into test branch
| -rw-r--r-- | arch/i386/kernel/acpi/cstate.c | 122 | ||||
| -rw-r--r-- | arch/i386/kernel/process.c | 22 | ||||
| -rw-r--r-- | arch/x86_64/kernel/process.c | 22 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 101 | ||||
| -rw-r--r-- | include/acpi/pdc_intel.h | 9 | ||||
| -rw-r--r-- | include/acpi/processor.h | 18 | ||||
| -rw-r--r-- | include/asm-i386/processor.h | 2 | ||||
| -rw-r--r-- | include/asm-x86_64/processor.h | 2 |
8 files changed, 242 insertions, 56 deletions
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c index 25db49ef1770..20563e52c622 100644 --- a/arch/i386/kernel/acpi/cstate.c +++ b/arch/i386/kernel/acpi/cstate.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/acpi.h> | 12 | #include <linux/acpi.h> |
| 13 | #include <linux/cpu.h> | ||
| 13 | 14 | ||
| 14 | #include <acpi/processor.h> | 15 | #include <acpi/processor.h> |
| 15 | #include <asm/acpi.h> | 16 | #include <asm/acpi.h> |
| @@ -41,5 +42,124 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | |||
| 41 | flags->bm_check = 1; | 42 | flags->bm_check = 1; |
| 42 | } | 43 | } |
| 43 | } | 44 | } |
| 44 | |||
| 45 | EXPORT_SYMBOL(acpi_processor_power_init_bm_check); | 45 | EXPORT_SYMBOL(acpi_processor_power_init_bm_check); |
| 46 | |||
| 47 | /* The code below handles cstate entry with monitor-mwait pair on Intel*/ | ||
| 48 | |||
| 49 | struct cstate_entry_s { | ||
| 50 | struct { | ||
| 51 | unsigned int eax; | ||
| 52 | unsigned int ecx; | ||
| 53 | } states[ACPI_PROCESSOR_MAX_POWER]; | ||
| 54 | }; | ||
| 55 | static struct cstate_entry_s *cpu_cstate_entry; /* per CPU ptr */ | ||
| 56 | |||
| 57 | static short mwait_supported[ACPI_PROCESSOR_MAX_POWER]; | ||
| 58 | |||
| 59 | #define MWAIT_SUBSTATE_MASK (0xf) | ||
| 60 | #define MWAIT_SUBSTATE_SIZE (4) | ||
| 61 | |||
| 62 | #define CPUID_MWAIT_LEAF (5) | ||
| 63 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | ||
| 64 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | ||
| 65 | |||
| 66 | #define MWAIT_ECX_INTERRUPT_BREAK (0x1) | ||
| 67 | |||
| 68 | #define NATIVE_CSTATE_BEYOND_HALT (2) | ||
| 69 | |||
| 70 | int acpi_processor_ffh_cstate_probe(unsigned int cpu, | ||
| 71 | struct acpi_processor_cx *cx, struct acpi_power_register *reg) | ||
| 72 | { | ||
| 73 | struct cstate_entry_s *percpu_entry; | ||
| 74 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
| 75 | |||
| 76 | cpumask_t saved_mask; | ||
| 77 | int retval; | ||
| 78 | unsigned int eax, ebx, ecx, edx; | ||
| 79 | unsigned int edx_part; | ||
| 80 | unsigned int cstate_type; /* C-state type and not ACPI C-state type */ | ||
| 81 | unsigned int num_cstate_subtype; | ||
| 82 | |||
| 83 | if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF ) | ||
| 84 | return -1; | ||
| 85 | |||
| 86 | if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT) | ||
| 87 | return -1; | ||
| 88 | |||
| 89 | percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu); | ||
| 90 | percpu_entry->states[cx->index].eax = 0; | ||
| 91 | percpu_entry->states[cx->index].ecx = 0; | ||
| 92 | |||
| 93 | /* Make sure we are running on right CPU */ | ||
| 94 | saved_mask = current->cpus_allowed; | ||
| 95 | retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); | ||
| 96 | if (retval) | ||
| 97 | return -1; | ||
| 98 | |||
| 99 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); | ||
| 100 | |||
| 101 | /* Check whether this particular cx_type (in CST) is supported or not */ | ||
| 102 | cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1; | ||
| 103 | edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE); | ||
| 104 | num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK; | ||
| 105 | |||
| 106 | retval = 0; | ||
| 107 | if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) { | ||
| 108 | retval = -1; | ||
| 109 | goto out; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */ | ||
| 113 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || | ||
| 114 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) { | ||
| 115 | retval = -1; | ||
| 116 | goto out; | ||
| 117 | } | ||
| 118 | percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK; | ||
| 119 | |||
| 120 | /* Use the hint in CST */ | ||
| 121 | percpu_entry->states[cx->index].eax = cx->address; | ||
| 122 | |||
| 123 | if (!mwait_supported[cstate_type]) { | ||
| 124 | mwait_supported[cstate_type] = 1; | ||
| 125 | printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d " | ||
| 126 | "state\n", cx->type); | ||
| 127 | } | ||
| 128 | |||
| 129 | out: | ||
| 130 | set_cpus_allowed(current, saved_mask); | ||
| 131 | return retval; | ||
| 132 | } | ||
| 133 | EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe); | ||
| 134 | |||
| 135 | void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) | ||
| 136 | { | ||
| 137 | unsigned int cpu = smp_processor_id(); | ||
| 138 | struct cstate_entry_s *percpu_entry; | ||
| 139 | |||
| 140 | percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu); | ||
| 141 | mwait_idle_with_hints(percpu_entry->states[cx->index].eax, | ||
| 142 | percpu_entry->states[cx->index].ecx); | ||
| 143 | } | ||
| 144 | EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter); | ||
| 145 | |||
| 146 | static int __init ffh_cstate_init(void) | ||
| 147 | { | ||
| 148 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 149 | if (c->x86_vendor != X86_VENDOR_INTEL) | ||
| 150 | return -1; | ||
| 151 | |||
| 152 | cpu_cstate_entry = alloc_percpu(struct cstate_entry_s); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static void __exit ffh_cstate_exit(void) | ||
| 157 | { | ||
| 158 | if (cpu_cstate_entry) { | ||
| 159 | free_percpu(cpu_cstate_entry); | ||
| 160 | cpu_cstate_entry = NULL; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | arch_initcall(ffh_cstate_init); | ||
| 165 | __exitcall(ffh_cstate_exit); | ||
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index b0a07801d9df..57d375900afb 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
| @@ -236,20 +236,28 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait); | |||
| 236 | * We execute MONITOR against need_resched and enter optimized wait state | 236 | * We execute MONITOR against need_resched and enter optimized wait state |
| 237 | * through MWAIT. Whenever someone changes need_resched, we would be woken | 237 | * through MWAIT. Whenever someone changes need_resched, we would be woken |
| 238 | * up from MWAIT (without an IPI). | 238 | * up from MWAIT (without an IPI). |
| 239 | * | ||
| 240 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
| 241 | * capability. | ||
| 239 | */ | 242 | */ |
| 240 | static void mwait_idle(void) | 243 | void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) |
| 241 | { | 244 | { |
| 242 | local_irq_enable(); | 245 | if (!need_resched()) { |
| 243 | |||
| 244 | while (!need_resched()) { | ||
| 245 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 246 | __monitor((void *)¤t_thread_info()->flags, 0, 0); |
| 246 | smp_mb(); | 247 | smp_mb(); |
| 247 | if (need_resched()) | 248 | if (!need_resched()) |
| 248 | break; | 249 | __mwait(eax, ecx); |
| 249 | __mwait(0, 0); | ||
| 250 | } | 250 | } |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 254 | static void mwait_idle(void) | ||
| 255 | { | ||
| 256 | local_irq_enable(); | ||
| 257 | while (!need_resched()) | ||
| 258 | mwait_idle_with_hints(0, 0); | ||
| 259 | } | ||
| 260 | |||
| 253 | void __devinit select_idle_routine(const struct cpuinfo_x86 *c) | 261 | void __devinit select_idle_routine(const struct cpuinfo_x86 *c) |
| 254 | { | 262 | { |
| 255 | if (cpu_has(c, X86_FEATURE_MWAIT)) { | 263 | if (cpu_has(c, X86_FEATURE_MWAIT)) { |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 5e95b257ee26..49f7fac6229e 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
| @@ -238,20 +238,28 @@ void cpu_idle (void) | |||
| 238 | * We execute MONITOR against need_resched and enter optimized wait state | 238 | * We execute MONITOR against need_resched and enter optimized wait state |
| 239 | * through MWAIT. Whenever someone changes need_resched, we would be woken | 239 | * through MWAIT. Whenever someone changes need_resched, we would be woken |
| 240 | * up from MWAIT (without an IPI). | 240 | * up from MWAIT (without an IPI). |
| 241 | * | ||
| 242 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
| 243 | * capability. | ||
| 241 | */ | 244 | */ |
| 242 | static void mwait_idle(void) | 245 | void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) |
| 243 | { | 246 | { |
| 244 | local_irq_enable(); | 247 | if (!need_resched()) { |
| 245 | |||
| 246 | while (!need_resched()) { | ||
| 247 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 248 | __monitor((void *)¤t_thread_info()->flags, 0, 0); |
| 248 | smp_mb(); | 249 | smp_mb(); |
| 249 | if (need_resched()) | 250 | if (!need_resched()) |
| 250 | break; | 251 | __mwait(eax, ecx); |
| 251 | __mwait(0, 0); | ||
| 252 | } | 252 | } |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 256 | static void mwait_idle(void) | ||
| 257 | { | ||
| 258 | local_irq_enable(); | ||
| 259 | while (!need_resched()) | ||
| 260 | mwait_idle_with_hints(0,0); | ||
| 261 | } | ||
| 262 | |||
| 255 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | 263 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) |
| 256 | { | 264 | { |
| 257 | static int printed; | 265 | static int printed; |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0a395fca843b..429a39dbd75d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -219,6 +219,23 @@ static void acpi_safe_halt(void) | |||
| 219 | 219 | ||
| 220 | static atomic_t c3_cpu_count; | 220 | static atomic_t c3_cpu_count; |
| 221 | 221 | ||
| 222 | /* Common C-state entry for C2, C3, .. */ | ||
| 223 | static void acpi_cstate_enter(struct acpi_processor_cx *cstate) | ||
| 224 | { | ||
| 225 | if (cstate->space_id == ACPI_CSTATE_FFH) { | ||
| 226 | /* Call into architectural FFH based C-state */ | ||
| 227 | acpi_processor_ffh_cstate_enter(cstate); | ||
| 228 | } else { | ||
| 229 | int unused; | ||
| 230 | /* IO port based C-state */ | ||
| 231 | inb(cstate->address); | ||
| 232 | /* Dummy wait op - must do something useless after P_LVL2 read | ||
| 233 | because chipsets cannot guarantee that STPCLK# signal | ||
| 234 | gets asserted in time to freeze execution properly. */ | ||
| 235 | unused = inl(acpi_fadt.xpm_tmr_blk.address); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 222 | static void acpi_processor_idle(void) | 239 | static void acpi_processor_idle(void) |
| 223 | { | 240 | { |
| 224 | struct acpi_processor *pr = NULL; | 241 | struct acpi_processor *pr = NULL; |
| @@ -361,11 +378,7 @@ static void acpi_processor_idle(void) | |||
| 361 | /* Get start time (ticks) */ | 378 | /* Get start time (ticks) */ |
| 362 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); | 379 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 363 | /* Invoke C2 */ | 380 | /* Invoke C2 */ |
| 364 | inb(cx->address); | 381 | acpi_cstate_enter(cx); |
| 365 | /* Dummy wait op - must do something useless after P_LVL2 read | ||
| 366 | because chipsets cannot guarantee that STPCLK# signal | ||
| 367 | gets asserted in time to freeze execution properly. */ | ||
| 368 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | ||
| 369 | /* Get end time (ticks) */ | 382 | /* Get end time (ticks) */ |
| 370 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | 383 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 371 | 384 | ||
| @@ -401,9 +414,7 @@ static void acpi_processor_idle(void) | |||
| 401 | /* Get start time (ticks) */ | 414 | /* Get start time (ticks) */ |
| 402 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); | 415 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 403 | /* Invoke C3 */ | 416 | /* Invoke C3 */ |
| 404 | inb(cx->address); | 417 | acpi_cstate_enter(cx); |
| 405 | /* Dummy wait op (see above) */ | ||
| 406 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | ||
| 407 | /* Get end time (ticks) */ | 418 | /* Get end time (ticks) */ |
| 408 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | 419 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 409 | if (pr->flags.bm_check) { | 420 | if (pr->flags.bm_check) { |
| @@ -628,20 +639,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
| 628 | return 0; | 639 | return 0; |
| 629 | } | 640 | } |
| 630 | 641 | ||
| 631 | static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) | 642 | static int acpi_processor_get_power_info_default(struct acpi_processor *pr) |
| 632 | { | 643 | { |
| 633 | 644 | if (!pr->power.states[ACPI_STATE_C1].valid) { | |
| 634 | /* Zero initialize all the C-states info. */ | 645 | /* set the first C-State to C1 */ |
| 635 | memset(pr->power.states, 0, sizeof(pr->power.states)); | 646 | /* all processors need to support C1 */ |
| 636 | 647 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | |
| 637 | /* set the first C-State to C1 */ | 648 | pr->power.states[ACPI_STATE_C1].valid = 1; |
| 638 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | 649 | } |
| 639 | 650 | /* the C0 state only exists as a filler in our array */ | |
| 640 | /* the C0 state only exists as a filler in our array, | ||
| 641 | * and all processors need to support C1 */ | ||
| 642 | pr->power.states[ACPI_STATE_C0].valid = 1; | 651 | pr->power.states[ACPI_STATE_C0].valid = 1; |
| 643 | pr->power.states[ACPI_STATE_C1].valid = 1; | ||
| 644 | |||
| 645 | return 0; | 652 | return 0; |
| 646 | } | 653 | } |
| 647 | 654 | ||
| @@ -658,12 +665,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
| 658 | if (nocst) | 665 | if (nocst) |
| 659 | return -ENODEV; | 666 | return -ENODEV; |
| 660 | 667 | ||
| 661 | current_count = 1; | 668 | current_count = 0; |
| 662 | |||
| 663 | /* Zero initialize C2 onwards and prepare for fresh CST lookup */ | ||
| 664 | for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++) | ||
| 665 | memset(&(pr->power.states[i]), 0, | ||
| 666 | sizeof(struct acpi_processor_cx)); | ||
| 667 | 669 | ||
| 668 | status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); | 670 | status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); |
| 669 | if (ACPI_FAILURE(status)) { | 671 | if (ACPI_FAILURE(status)) { |
| @@ -718,22 +720,39 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
| 718 | (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) | 720 | (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) |
| 719 | continue; | 721 | continue; |
| 720 | 722 | ||
| 721 | cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ? | ||
| 722 | 0 : reg->address; | ||
| 723 | |||
| 724 | /* There should be an easy way to extract an integer... */ | 723 | /* There should be an easy way to extract an integer... */ |
| 725 | obj = (union acpi_object *)&(element->package.elements[1]); | 724 | obj = (union acpi_object *)&(element->package.elements[1]); |
| 726 | if (obj->type != ACPI_TYPE_INTEGER) | 725 | if (obj->type != ACPI_TYPE_INTEGER) |
| 727 | continue; | 726 | continue; |
| 728 | 727 | ||
| 729 | cx.type = obj->integer.value; | 728 | cx.type = obj->integer.value; |
| 730 | 729 | /* | |
| 731 | if ((cx.type != ACPI_STATE_C1) && | 730 | * Some buggy BIOSes won't list C1 in _CST - |
| 732 | (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) | 731 | * Let acpi_processor_get_power_info_default() handle them later |
| 733 | continue; | 732 | */ |
| 734 | 733 | if (i == 1 && cx.type != ACPI_STATE_C1) | |
| 735 | if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) | 734 | current_count++; |
| 736 | continue; | 735 | |
| 736 | cx.address = reg->address; | ||
| 737 | cx.index = current_count + 1; | ||
| 738 | |||
| 739 | cx.space_id = ACPI_CSTATE_SYSTEMIO; | ||
| 740 | if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { | ||
| 741 | if (acpi_processor_ffh_cstate_probe | ||
| 742 | (pr->id, &cx, reg) == 0) { | ||
| 743 | cx.space_id = ACPI_CSTATE_FFH; | ||
| 744 | } else if (cx.type != ACPI_STATE_C1) { | ||
| 745 | /* | ||
| 746 | * C1 is a special case where FIXED_HARDWARE | ||
| 747 | * can be handled in non-MWAIT way as well. | ||
| 748 | * In that case, save this _CST entry info. | ||
| 749 | * That is, we retain space_id of SYSTEM_IO for | ||
| 750 | * halt based C1. | ||
| 751 | * Otherwise, ignore this info and continue. | ||
| 752 | */ | ||
| 753 | continue; | ||
| 754 | } | ||
| 755 | } | ||
| 737 | 756 | ||
| 738 | obj = (union acpi_object *)&(element->package.elements[2]); | 757 | obj = (union acpi_object *)&(element->package.elements[2]); |
| 739 | if (obj->type != ACPI_TYPE_INTEGER) | 758 | if (obj->type != ACPI_TYPE_INTEGER) |
| @@ -938,12 +957,18 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) | |||
| 938 | /* NOTE: the idle thread may not be running while calling | 957 | /* NOTE: the idle thread may not be running while calling |
| 939 | * this function */ | 958 | * this function */ |
| 940 | 959 | ||
| 941 | /* Adding C1 state */ | 960 | /* Zero initialize all the C-states info. */ |
| 942 | acpi_processor_get_power_info_default_c1(pr); | 961 | memset(pr->power.states, 0, sizeof(pr->power.states)); |
| 962 | |||
| 943 | result = acpi_processor_get_power_info_cst(pr); | 963 | result = acpi_processor_get_power_info_cst(pr); |
| 944 | if (result == -ENODEV) | 964 | if (result == -ENODEV) |
| 945 | acpi_processor_get_power_info_fadt(pr); | 965 | acpi_processor_get_power_info_fadt(pr); |
| 946 | 966 | ||
| 967 | if (result) | ||
| 968 | return result; | ||
| 969 | |||
| 970 | acpi_processor_get_power_info_default(pr); | ||
| 971 | |||
| 947 | pr->power.count = acpi_processor_power_verify(pr); | 972 | pr->power.count = acpi_processor_power_verify(pr); |
| 948 | 973 | ||
| 949 | /* | 974 | /* |
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h index c5472be6f3a2..e72bfdd887f9 100644 --- a/include/acpi/pdc_intel.h +++ b/include/acpi/pdc_intel.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #define ACPI_PDC_SMP_C_SWCOORD (0x0040) | 13 | #define ACPI_PDC_SMP_C_SWCOORD (0x0040) |
| 14 | #define ACPI_PDC_SMP_T_SWCOORD (0x0080) | 14 | #define ACPI_PDC_SMP_T_SWCOORD (0x0080) |
| 15 | #define ACPI_PDC_C_C1_FFH (0x0100) | 15 | #define ACPI_PDC_C_C1_FFH (0x0100) |
| 16 | #define ACPI_PDC_C_C2C3_FFH (0x0200) | ||
| 16 | 17 | ||
| 17 | #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ | 18 | #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ |
| 18 | ACPI_PDC_C_C1_HALT | \ | 19 | ACPI_PDC_C_C1_HALT | \ |
| @@ -23,8 +24,10 @@ | |||
| 23 | ACPI_PDC_SMP_P_SWCOORD | \ | 24 | ACPI_PDC_SMP_P_SWCOORD | \ |
| 24 | ACPI_PDC_P_FFH) | 25 | ACPI_PDC_P_FFH) |
| 25 | 26 | ||
| 26 | #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ | 27 | #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ |
| 27 | ACPI_PDC_SMP_C1PT | \ | 28 | ACPI_PDC_SMP_C1PT | \ |
| 28 | ACPI_PDC_C_C1_HALT) | 29 | ACPI_PDC_C_C1_HALT | \ |
| 30 | ACPI_PDC_C_C1_FFH | \ | ||
| 31 | ACPI_PDC_C_C2C3_FFH) | ||
| 29 | 32 | ||
| 30 | #endif /* __PDC_INTEL_H__ */ | 33 | #endif /* __PDC_INTEL_H__ */ |
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 9dd5b75961f8..7798d2a9f793 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
| @@ -29,6 +29,9 @@ | |||
| 29 | #define DOMAIN_COORD_TYPE_SW_ANY 0xfd | 29 | #define DOMAIN_COORD_TYPE_SW_ANY 0xfd |
| 30 | #define DOMAIN_COORD_TYPE_HW_ALL 0xfe | 30 | #define DOMAIN_COORD_TYPE_HW_ALL 0xfe |
| 31 | 31 | ||
| 32 | #define ACPI_CSTATE_SYSTEMIO (0) | ||
| 33 | #define ACPI_CSTATE_FFH (1) | ||
| 34 | |||
| 32 | /* Power Management */ | 35 | /* Power Management */ |
| 33 | 36 | ||
| 34 | struct acpi_processor_cx; | 37 | struct acpi_processor_cx; |
| @@ -58,6 +61,8 @@ struct acpi_processor_cx { | |||
| 58 | u8 valid; | 61 | u8 valid; |
| 59 | u8 type; | 62 | u8 type; |
| 60 | u32 address; | 63 | u32 address; |
| 64 | u8 space_id; | ||
| 65 | u8 index; | ||
| 61 | u32 latency; | 66 | u32 latency; |
| 62 | u32 latency_ticks; | 67 | u32 latency_ticks; |
| 63 | u32 power; | 68 | u32 power; |
| @@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr); | |||
| 206 | #ifdef ARCH_HAS_POWER_INIT | 211 | #ifdef ARCH_HAS_POWER_INIT |
| 207 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | 212 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, |
| 208 | unsigned int cpu); | 213 | unsigned int cpu); |
| 214 | int acpi_processor_ffh_cstate_probe(unsigned int cpu, | ||
| 215 | struct acpi_processor_cx *cx, struct acpi_power_register *reg); | ||
| 216 | void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cstate); | ||
| 209 | #else | 217 | #else |
| 210 | static inline void acpi_processor_power_init_bm_check(struct | 218 | static inline void acpi_processor_power_init_bm_check(struct |
| 211 | acpi_processor_flags | 219 | acpi_processor_flags |
| @@ -214,6 +222,16 @@ static inline void acpi_processor_power_init_bm_check(struct | |||
| 214 | flags->bm_check = 1; | 222 | flags->bm_check = 1; |
| 215 | return; | 223 | return; |
| 216 | } | 224 | } |
| 225 | static inline int acpi_processor_ffh_cstate_probe(unsigned int cpu, | ||
| 226 | struct acpi_processor_cx *cx, struct acpi_power_register *reg) | ||
| 227 | { | ||
| 228 | return -1; | ||
| 229 | } | ||
| 230 | static inline void acpi_processor_ffh_cstate_enter( | ||
| 231 | struct acpi_processor_cx *cstate) | ||
| 232 | { | ||
| 233 | return; | ||
| 234 | } | ||
| 217 | #endif | 235 | #endif |
| 218 | 236 | ||
| 219 | /* in processor_perflib.c */ | 237 | /* in processor_perflib.c */ |
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 2277127696d2..e0ddca94d50c 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
| @@ -306,6 +306,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) | |||
| 306 | : :"a" (eax), "c" (ecx)); | 306 | : :"a" (eax), "c" (ecx)); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); | ||
| 310 | |||
| 309 | /* from system description table in BIOS. Mostly for MCA use, but | 311 | /* from system description table in BIOS. Mostly for MCA use, but |
| 310 | others may find it useful. */ | 312 | others may find it useful. */ |
| 311 | extern unsigned int machine_id; | 313 | extern unsigned int machine_id; |
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index de9c3147ee4c..cef17e0f828c 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h | |||
| @@ -475,6 +475,8 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) | |||
| 475 | : :"a" (eax), "c" (ecx)); | 475 | : :"a" (eax), "c" (ecx)); |
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); | ||
| 479 | |||
| 478 | #define stack_current() \ | 480 | #define stack_current() \ |
| 479 | ({ \ | 481 | ({ \ |
| 480 | struct thread_info *ti; \ | 482 | struct thread_info *ti; \ |
