diff options
| -rw-r--r-- | arch/i386/kernel/acpi/Makefile | 4 | ||||
| -rw-r--r-- | arch/i386/kernel/acpi/cstate.c | 103 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/processor_core.c | 37 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 105 | ||||
| -rw-r--r-- | drivers/acpi/processor_perflib.c | 33 | ||||
| -rw-r--r-- | include/acpi/pdc_intel.h | 29 | ||||
| -rw-r--r-- | include/acpi/processor.h | 34 | ||||
| -rw-r--r-- | include/asm-i386/acpi.h | 10 | ||||
| -rw-r--r-- | include/asm-x86_64/acpi.h | 8 |
10 files changed, 284 insertions, 81 deletions
diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile index ee75cb286cfe..5e291a20c03d 100644 --- a/arch/i386/kernel/acpi/Makefile +++ b/arch/i386/kernel/acpi/Makefile | |||
| @@ -2,3 +2,7 @@ obj-$(CONFIG_ACPI_BOOT) := boot.o | |||
| 2 | obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o | 2 | obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o |
| 3 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o | 3 | obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o |
| 4 | 4 | ||
| 5 | ifneq ($(CONFIG_ACPI_PROCESSOR),) | ||
| 6 | obj-y += cstate.o | ||
| 7 | endif | ||
| 8 | |||
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c new file mode 100644 index 000000000000..4c3036ba65df --- /dev/null +++ b/arch/i386/kernel/acpi/cstate.c | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | /* | ||
| 2 | * arch/i386/kernel/acpi/cstate.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Intel Corporation | ||
| 5 | * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | ||
| 6 | * - Added _PDC for SMP C-states on Intel CPUs | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/acpi.h> | ||
| 13 | |||
| 14 | #include <acpi/processor.h> | ||
| 15 | #include <asm/acpi.h> | ||
| 16 | |||
| 17 | static void acpi_processor_power_init_intel_pdc(struct acpi_processor_power | ||
| 18 | *pow) | ||
| 19 | { | ||
| 20 | struct acpi_object_list *obj_list; | ||
| 21 | union acpi_object *obj; | ||
| 22 | u32 *buf; | ||
| 23 | |||
| 24 | /* allocate and initialize pdc. It will be used later. */ | ||
| 25 | obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); | ||
| 26 | if (!obj_list) { | ||
| 27 | printk(KERN_ERR "Memory allocation error\n"); | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); | ||
| 32 | if (!obj) { | ||
| 33 | printk(KERN_ERR "Memory allocation error\n"); | ||
| 34 | kfree(obj_list); | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | |||
| 38 | buf = kmalloc(12, GFP_KERNEL); | ||
| 39 | if (!buf) { | ||
| 40 | printk(KERN_ERR "Memory allocation error\n"); | ||
| 41 | kfree(obj); | ||
| 42 | kfree(obj_list); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | buf[0] = ACPI_PDC_REVISION_ID; | ||
| 47 | buf[1] = 1; | ||
| 48 | buf[2] = ACPI_PDC_C_CAPABILITY_SMP; | ||
| 49 | |||
| 50 | obj->type = ACPI_TYPE_BUFFER; | ||
| 51 | obj->buffer.length = 12; | ||
| 52 | obj->buffer.pointer = (u8 *) buf; | ||
| 53 | obj_list->count = 1; | ||
| 54 | obj_list->pointer = obj; | ||
| 55 | pow->pdc = obj_list; | ||
| 56 | |||
| 57 | return; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Initialize _PDC data based on the CPU vendor */ | ||
| 61 | void acpi_processor_power_init_pdc(struct acpi_processor_power *pow, | ||
| 62 | unsigned int cpu) | ||
| 63 | { | ||
| 64 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
| 65 | |||
| 66 | pow->pdc = NULL; | ||
| 67 | if (c->x86_vendor == X86_VENDOR_INTEL) | ||
| 68 | acpi_processor_power_init_intel_pdc(pow); | ||
| 69 | |||
| 70 | return; | ||
| 71 | } | ||
| 72 | |||
| 73 | EXPORT_SYMBOL(acpi_processor_power_init_pdc); | ||
| 74 | |||
| 75 | /* | ||
| 76 | * Initialize bm_flags based on the CPU cache properties | ||
| 77 | * On SMP it depends on cache configuration | ||
| 78 | * - When cache is not shared among all CPUs, we flush cache | ||
| 79 | * before entering C3. | ||
| 80 | * - When cache is shared among all CPUs, we use bm_check | ||
| 81 | * mechanism as in UP case | ||
| 82 | * | ||
| 83 | * This routine is called only after all the CPUs are online | ||
| 84 | */ | ||
| 85 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | ||
| 86 | unsigned int cpu) | ||
| 87 | { | ||
| 88 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
| 89 | |||
| 90 | flags->bm_check = 0; | ||
| 91 | if (num_online_cpus() == 1) | ||
| 92 | flags->bm_check = 1; | ||
| 93 | else if (c->x86_vendor == X86_VENDOR_INTEL) { | ||
| 94 | /* | ||
| 95 | * Today all CPUs that support C3 share cache. | ||
| 96 | * TBD: This needs to look at cache shared map, once | ||
| 97 | * multi-core detection patch makes to the base. | ||
| 98 | */ | ||
| 99 | flags->bm_check = 1; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | EXPORT_SYMBOL(acpi_processor_power_init_bm_check); | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 7dcbf70fc16f..327a55d4d1c6 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | |||
| @@ -375,7 +375,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) | |||
| 375 | arg0.buffer.pointer = (u8 *) arg0_buf; | 375 | arg0.buffer.pointer = (u8 *) arg0_buf; |
| 376 | arg0_buf[0] = ACPI_PDC_REVISION_ID; | 376 | arg0_buf[0] = ACPI_PDC_REVISION_ID; |
| 377 | arg0_buf[1] = 1; | 377 | arg0_buf[1] = 1; |
| 378 | arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR; | 378 | arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP_MSR; |
| 379 | 379 | ||
| 380 | p.pdc = &arg_list; | 380 | p.pdc = &arg_list; |
| 381 | 381 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index f4778747e889..e421842888b9 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -256,6 +256,43 @@ acpi_processor_errata ( | |||
| 256 | 256 | ||
| 257 | 257 | ||
| 258 | /* -------------------------------------------------------------------------- | 258 | /* -------------------------------------------------------------------------- |
| 259 | Common ACPI processor fucntions | ||
| 260 | -------------------------------------------------------------------------- */ | ||
| 261 | |||
| 262 | /* | ||
| 263 | * _PDC is required for a BIOS-OS handshake for most of the newer | ||
| 264 | * ACPI processor features. | ||
| 265 | */ | ||
| 266 | |||
| 267 | int acpi_processor_set_pdc(struct acpi_processor *pr, | ||
| 268 | struct acpi_object_list *pdc_in) | ||
| 269 | { | ||
| 270 | acpi_status status = AE_OK; | ||
| 271 | u32 arg0_buf[3]; | ||
| 272 | union acpi_object arg0 = {ACPI_TYPE_BUFFER}; | ||
| 273 | struct acpi_object_list no_object = {1, &arg0}; | ||
| 274 | struct acpi_object_list *pdc; | ||
| 275 | |||
| 276 | ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); | ||
| 277 | |||
| 278 | arg0.buffer.length = 12; | ||
| 279 | arg0.buffer.pointer = (u8 *) arg0_buf; | ||
| 280 | arg0_buf[0] = ACPI_PDC_REVISION_ID; | ||
| 281 | arg0_buf[1] = 0; | ||
| 282 | arg0_buf[2] = 0; | ||
| 283 | |||
| 284 | pdc = (pdc_in) ? pdc_in : &no_object; | ||
| 285 | |||
| 286 | status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); | ||
| 287 | |||
| 288 | if ((ACPI_FAILURE(status)) && (pdc_in)) | ||
| 289 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n")); | ||
| 290 | |||
| 291 | return_VALUE(status); | ||
| 292 | } | ||
| 293 | |||
| 294 | |||
| 295 | /* -------------------------------------------------------------------------- | ||
| 259 | FS Interface (/proc) | 296 | FS Interface (/proc) |
| 260 | -------------------------------------------------------------------------- */ | 297 | -------------------------------------------------------------------------- */ |
| 261 | 298 | ||
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 79d5ca3066c6..8f038cd29477 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> | 6 | * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> |
| 7 | * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | 7 | * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> |
| 8 | * - Added processor hotplug support | 8 | * - Added processor hotplug support |
| 9 | * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | ||
| 10 | * - Added support for C3 on SMP | ||
| 9 | * | 11 | * |
| 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 12 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 11 | * | 13 | * |
| @@ -142,7 +144,7 @@ acpi_processor_power_activate ( | |||
| 142 | switch (old->type) { | 144 | switch (old->type) { |
| 143 | case ACPI_STATE_C3: | 145 | case ACPI_STATE_C3: |
| 144 | /* Disable bus master reload */ | 146 | /* Disable bus master reload */ |
| 145 | if (new->type != ACPI_STATE_C3) | 147 | if (new->type != ACPI_STATE_C3 && pr->flags.bm_check) |
| 146 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); | 148 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); |
| 147 | break; | 149 | break; |
| 148 | } | 150 | } |
| @@ -152,7 +154,7 @@ acpi_processor_power_activate ( | |||
| 152 | switch (new->type) { | 154 | switch (new->type) { |
| 153 | case ACPI_STATE_C3: | 155 | case ACPI_STATE_C3: |
| 154 | /* Enable bus master reload */ | 156 | /* Enable bus master reload */ |
| 155 | if (old->type != ACPI_STATE_C3) | 157 | if (old->type != ACPI_STATE_C3 && pr->flags.bm_check) |
| 156 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK); | 158 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK); |
| 157 | break; | 159 | break; |
| 158 | } | 160 | } |
| @@ -163,6 +165,9 @@ acpi_processor_power_activate ( | |||
| 163 | } | 165 | } |
| 164 | 166 | ||
| 165 | 167 | ||
| 168 | static atomic_t c3_cpu_count; | ||
| 169 | |||
| 170 | |||
| 166 | static void acpi_processor_idle (void) | 171 | static void acpi_processor_idle (void) |
| 167 | { | 172 | { |
| 168 | struct acpi_processor *pr = NULL; | 173 | struct acpi_processor *pr = NULL; |
| @@ -297,8 +302,22 @@ static void acpi_processor_idle (void) | |||
| 297 | break; | 302 | break; |
| 298 | 303 | ||
| 299 | case ACPI_STATE_C3: | 304 | case ACPI_STATE_C3: |
| 300 | /* Disable bus master arbitration */ | 305 | |
| 301 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK); | 306 | if (pr->flags.bm_check) { |
| 307 | if (atomic_inc_return(&c3_cpu_count) == | ||
| 308 | num_online_cpus()) { | ||
| 309 | /* | ||
| 310 | * All CPUs are trying to go to C3 | ||
| 311 | * Disable bus master arbitration | ||
| 312 | */ | ||
| 313 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, | ||
| 314 | ACPI_MTX_DO_NOT_LOCK); | ||
| 315 | } | ||
| 316 | } else { | ||
| 317 | /* SMP with no shared cache... Invalidate cache */ | ||
| 318 | ACPI_FLUSH_CPU_CACHE(); | ||
| 319 | } | ||
| 320 | |||
| 302 | /* Get start time (ticks) */ | 321 | /* Get start time (ticks) */ |
| 303 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); | 322 | t1 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 304 | /* Invoke C3 */ | 323 | /* Invoke C3 */ |
| @@ -307,8 +326,12 @@ static void acpi_processor_idle (void) | |||
| 307 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | 326 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 308 | /* Get end time (ticks) */ | 327 | /* Get end time (ticks) */ |
| 309 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | 328 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); |
| 310 | /* Enable bus master arbitration */ | 329 | if (pr->flags.bm_check) { |
| 311 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); | 330 | /* Enable bus master arbitration */ |
| 331 | atomic_dec(&c3_cpu_count); | ||
| 332 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); | ||
| 333 | } | ||
| 334 | |||
| 312 | /* Re-enable interrupts */ | 335 | /* Re-enable interrupts */ |
| 313 | local_irq_enable(); | 336 | local_irq_enable(); |
| 314 | /* Compute time (ticks) that we were actually asleep */ | 337 | /* Compute time (ticks) that we were actually asleep */ |
| @@ -552,9 +575,6 @@ static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) | |||
| 552 | 575 | ||
| 553 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst"); | 576 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst"); |
| 554 | 577 | ||
| 555 | if (errata.smp) | ||
| 556 | return_VALUE(-ENODEV); | ||
| 557 | |||
| 558 | if (nocst) | 578 | if (nocst) |
| 559 | return_VALUE(-ENODEV); | 579 | return_VALUE(-ENODEV); |
| 560 | 580 | ||
| @@ -687,13 +707,6 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | |||
| 687 | return_VOID; | 707 | return_VOID; |
| 688 | } | 708 | } |
| 689 | 709 | ||
| 690 | /* We're (currently) only supporting C2 on UP */ | ||
| 691 | else if (errata.smp) { | ||
| 692 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 693 | "C2 not supported in SMP mode\n")); | ||
| 694 | return_VOID; | ||
| 695 | } | ||
| 696 | |||
| 697 | /* | 710 | /* |
| 698 | * Otherwise we've met all of our C2 requirements. | 711 | * Otherwise we've met all of our C2 requirements. |
| 699 | * Normalize the C2 latency to expidite policy | 712 | * Normalize the C2 latency to expidite policy |
| @@ -709,6 +722,8 @@ static void acpi_processor_power_verify_c3( | |||
| 709 | struct acpi_processor *pr, | 722 | struct acpi_processor *pr, |
| 710 | struct acpi_processor_cx *cx) | 723 | struct acpi_processor_cx *cx) |
| 711 | { | 724 | { |
| 725 | static int bm_check_flag; | ||
| 726 | |||
| 712 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c3"); | 727 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c3"); |
| 713 | 728 | ||
| 714 | if (!cx->address) | 729 | if (!cx->address) |
| @@ -725,20 +740,6 @@ static void acpi_processor_power_verify_c3( | |||
| 725 | return_VOID; | 740 | return_VOID; |
| 726 | } | 741 | } |
| 727 | 742 | ||
| 728 | /* bus mastering control is necessary */ | ||
| 729 | else if (!pr->flags.bm_control) { | ||
| 730 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 731 | "C3 support requires bus mastering control\n")); | ||
| 732 | return_VOID; | ||
| 733 | } | ||
| 734 | |||
| 735 | /* We're (currently) only supporting C2 on UP */ | ||
| 736 | else if (errata.smp) { | ||
| 737 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 738 | "C3 not supported in SMP mode\n")); | ||
| 739 | return_VOID; | ||
| 740 | } | ||
| 741 | |||
| 742 | /* | 743 | /* |
| 743 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) | 744 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) |
| 744 | * DMA transfers are used by any ISA device to avoid livelock. | 745 | * DMA transfers are used by any ISA device to avoid livelock. |
| @@ -752,6 +753,39 @@ static void acpi_processor_power_verify_c3( | |||
| 752 | return_VOID; | 753 | return_VOID; |
| 753 | } | 754 | } |
| 754 | 755 | ||
| 756 | /* All the logic here assumes flags.bm_check is same across all CPUs */ | ||
| 757 | if (!bm_check_flag) { | ||
| 758 | /* Determine whether bm_check is needed based on CPU */ | ||
| 759 | acpi_processor_power_init_bm_check(&(pr->flags), pr->id); | ||
| 760 | bm_check_flag = pr->flags.bm_check; | ||
| 761 | } else { | ||
| 762 | pr->flags.bm_check = bm_check_flag; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (pr->flags.bm_check) { | ||
| 766 | printk("Disabling BM access before entering C3\n"); | ||
| 767 | /* bus mastering control is necessary */ | ||
| 768 | if (!pr->flags.bm_control) { | ||
| 769 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 770 | "C3 support requires bus mastering control\n")); | ||
| 771 | return_VOID; | ||
| 772 | } | ||
| 773 | } else { | ||
| 774 | printk("Invalidating cache before entering C3\n"); | ||
| 775 | /* | ||
| 776 | * WBINVD should be set in fadt, for C3 state to be | ||
| 777 | * supported on when bm_check is not required. | ||
| 778 | */ | ||
| 779 | if (acpi_fadt.wb_invd != 1) { | ||
| 780 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 781 | "Cache invalidation should work properly" | ||
| 782 | " for C3 to be enabled on SMP systems\n")); | ||
| 783 | return_VOID; | ||
| 784 | } | ||
| 785 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, | ||
| 786 | 0, ACPI_MTX_DO_NOT_LOCK); | ||
| 787 | } | ||
| 788 | |||
| 755 | /* | 789 | /* |
| 756 | * Otherwise we've met all of our C3 requirements. | 790 | * Otherwise we've met all of our C3 requirements. |
| 757 | * Normalize the C3 latency to expidite policy. Enable | 791 | * Normalize the C3 latency to expidite policy. Enable |
| @@ -760,7 +794,6 @@ static void acpi_processor_power_verify_c3( | |||
| 760 | */ | 794 | */ |
| 761 | cx->valid = 1; | 795 | cx->valid = 1; |
| 762 | cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); | 796 | cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); |
| 763 | pr->flags.bm_check = 1; | ||
| 764 | 797 | ||
| 765 | return_VOID; | 798 | return_VOID; |
| 766 | } | 799 | } |
| @@ -848,7 +881,7 @@ int acpi_processor_cst_has_changed (struct acpi_processor *pr) | |||
| 848 | if (!pr) | 881 | if (!pr) |
| 849 | return_VALUE(-EINVAL); | 882 | return_VALUE(-EINVAL); |
| 850 | 883 | ||
| 851 | if (errata.smp || nocst) { | 884 | if ( nocst) { |
| 852 | return_VALUE(-ENODEV); | 885 | return_VALUE(-ENODEV); |
| 853 | } | 886 | } |
| 854 | 887 | ||
| @@ -948,7 +981,6 @@ static struct file_operations acpi_processor_power_fops = { | |||
| 948 | .release = single_release, | 981 | .release = single_release, |
| 949 | }; | 982 | }; |
| 950 | 983 | ||
| 951 | |||
| 952 | int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) | 984 | int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) |
| 953 | { | 985 | { |
| 954 | acpi_status status = 0; | 986 | acpi_status status = 0; |
| @@ -965,7 +997,10 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev | |||
| 965 | first_run++; | 997 | first_run++; |
| 966 | } | 998 | } |
| 967 | 999 | ||
| 968 | if (!errata.smp && (pr->id == 0) && acpi_fadt.cst_cnt && !nocst) { | 1000 | if (!pr) |
| 1001 | return_VALUE(-EINVAL); | ||
| 1002 | |||
| 1003 | if (acpi_fadt.cst_cnt && !nocst) { | ||
| 969 | status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8); | 1004 | status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8); |
| 970 | if (ACPI_FAILURE(status)) { | 1005 | if (ACPI_FAILURE(status)) { |
| 971 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1006 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
| @@ -973,6 +1008,8 @@ int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *dev | |||
| 973 | } | 1008 | } |
| 974 | } | 1009 | } |
| 975 | 1010 | ||
| 1011 | acpi_processor_power_init_pdc(&(pr->power), pr->id); | ||
| 1012 | acpi_processor_set_pdc(pr, pr->power.pdc); | ||
| 976 | acpi_processor_get_power_info(pr); | 1013 | acpi_processor_get_power_info(pr); |
| 977 | 1014 | ||
| 978 | /* | 1015 | /* |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index a9a1a8fe3199..1f0d6256302f 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -165,37 +165,6 @@ void acpi_processor_ppc_exit(void) { | |||
| 165 | acpi_processor_ppc_status &= ~PPC_REGISTERED; | 165 | acpi_processor_ppc_status &= ~PPC_REGISTERED; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | /* | ||
| 169 | * when registering a cpufreq driver with this ACPI processor driver, the | ||
| 170 | * _PCT and _PSS structures are read out and written into struct | ||
| 171 | * acpi_processor_performance. | ||
| 172 | */ | ||
| 173 | static int acpi_processor_set_pdc (struct acpi_processor *pr) | ||
| 174 | { | ||
| 175 | acpi_status status = AE_OK; | ||
| 176 | u32 arg0_buf[3]; | ||
| 177 | union acpi_object arg0 = {ACPI_TYPE_BUFFER}; | ||
| 178 | struct acpi_object_list no_object = {1, &arg0}; | ||
| 179 | struct acpi_object_list *pdc; | ||
| 180 | |||
| 181 | ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); | ||
| 182 | |||
| 183 | arg0.buffer.length = 12; | ||
| 184 | arg0.buffer.pointer = (u8 *) arg0_buf; | ||
| 185 | arg0_buf[0] = ACPI_PDC_REVISION_ID; | ||
| 186 | arg0_buf[1] = 0; | ||
| 187 | arg0_buf[2] = 0; | ||
| 188 | |||
| 189 | pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object; | ||
| 190 | |||
| 191 | status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); | ||
| 192 | |||
| 193 | if ((ACPI_FAILURE(status)) && (pr->performance->pdc)) | ||
| 194 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n")); | ||
| 195 | |||
| 196 | return_VALUE(status); | ||
| 197 | } | ||
| 198 | |||
| 199 | 168 | ||
| 200 | static int | 169 | static int |
| 201 | acpi_processor_get_performance_control ( | 170 | acpi_processor_get_performance_control ( |
| @@ -357,7 +326,7 @@ acpi_processor_get_performance_info ( | |||
| 357 | if (!pr || !pr->performance || !pr->handle) | 326 | if (!pr || !pr->performance || !pr->handle) |
| 358 | return_VALUE(-EINVAL); | 327 | return_VALUE(-EINVAL); |
| 359 | 328 | ||
| 360 | acpi_processor_set_pdc(pr); | 329 | acpi_processor_set_pdc(pr, pr->performance->pdc); |
| 361 | 330 | ||
| 362 | status = acpi_get_handle(pr->handle, "_PCT", &handle); | 331 | status = acpi_get_handle(pr->handle, "_PCT", &handle); |
| 363 | if (ACPI_FAILURE(status)) { | 332 | if (ACPI_FAILURE(status)) { |
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h new file mode 100644 index 000000000000..fd6730e4e567 --- /dev/null +++ b/include/acpi/pdc_intel.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | |||
| 2 | /* _PDC bit definition for Intel processors */ | ||
| 3 | |||
| 4 | #ifndef __PDC_INTEL_H__ | ||
| 5 | #define __PDC_INTEL_H__ | ||
| 6 | |||
| 7 | #define ACPI_PDC_P_FFH (0x0001) | ||
| 8 | #define ACPI_PDC_C_C1_HALT (0x0002) | ||
| 9 | #define ACPI_PDC_T_FFH (0x0004) | ||
| 10 | #define ACPI_PDC_SMP_C1PT (0x0008) | ||
| 11 | #define ACPI_PDC_SMP_C2C3 (0x0010) | ||
| 12 | #define ACPI_PDC_SMP_P_SWCOORD (0x0020) | ||
| 13 | #define ACPI_PDC_SMP_C_SWCOORD (0x0040) | ||
| 14 | #define ACPI_PDC_SMP_T_SWCOORD (0x0080) | ||
| 15 | #define ACPI_PDC_C_C1_FFH (0x0100) | ||
| 16 | |||
| 17 | |||
| 18 | #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ | ||
| 19 | ACPI_PDC_C_C1_HALT) | ||
| 20 | |||
| 21 | #define ACPI_PDC_EST_CAPABILITY_SMP_MSR (ACPI_PDC_EST_CAPABILITY_SMP | \ | ||
| 22 | ACPI_PDC_P_FFH) | ||
| 23 | |||
| 24 | #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ | ||
| 25 | ACPI_PDC_SMP_C1PT | \ | ||
| 26 | ACPI_PDC_C_C1_HALT) | ||
| 27 | |||
| 28 | #endif /* __PDC_INTEL_H__ */ | ||
| 29 | |||
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 2f50a5bb0c78..50cfea4ff6ca 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
| 5 | #include <linux/config.h> | 5 | #include <linux/config.h> |
| 6 | 6 | ||
| 7 | #include <asm/acpi.h> | ||
| 8 | |||
| 7 | #define ACPI_PROCESSOR_BUSY_METRIC 10 | 9 | #define ACPI_PROCESSOR_BUSY_METRIC 10 |
| 8 | 10 | ||
| 9 | #define ACPI_PROCESSOR_MAX_POWER 8 | 11 | #define ACPI_PROCESSOR_MAX_POWER 8 |
| @@ -14,6 +16,8 @@ | |||
| 14 | #define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */ | 16 | #define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */ |
| 15 | #define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 | 17 | #define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 |
| 16 | 18 | ||
| 19 | #define ACPI_PDC_REVISION_ID 0x1 | ||
| 20 | |||
| 17 | /* Power Management */ | 21 | /* Power Management */ |
| 18 | 22 | ||
| 19 | struct acpi_processor_cx; | 23 | struct acpi_processor_cx; |
| @@ -59,6 +63,9 @@ struct acpi_processor_power { | |||
| 59 | u32 bm_activity; | 63 | u32 bm_activity; |
| 60 | int count; | 64 | int count; |
| 61 | struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; | 65 | struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; |
| 66 | |||
| 67 | /* the _PDC objects passed by the driver, if any */ | ||
| 68 | struct acpi_object_list *pdc; | ||
| 62 | }; | 69 | }; |
| 63 | 70 | ||
| 64 | /* Performance Management */ | 71 | /* Performance Management */ |
| @@ -82,8 +89,6 @@ struct acpi_processor_px { | |||
| 82 | acpi_integer status; /* success indicator */ | 89 | acpi_integer status; /* success indicator */ |
| 83 | }; | 90 | }; |
| 84 | 91 | ||
| 85 | #define ACPI_PDC_REVISION_ID 0x1 | ||
| 86 | |||
| 87 | struct acpi_processor_performance { | 92 | struct acpi_processor_performance { |
| 88 | unsigned int state; | 93 | unsigned int state; |
| 89 | unsigned int platform_limit; | 94 | unsigned int platform_limit; |
| @@ -179,7 +184,32 @@ int acpi_processor_notify_smm(struct module *calling_module); | |||
| 179 | extern struct acpi_processor *processors[NR_CPUS]; | 184 | extern struct acpi_processor *processors[NR_CPUS]; |
| 180 | extern struct acpi_processor_errata errata; | 185 | extern struct acpi_processor_errata errata; |
| 181 | 186 | ||
| 187 | int acpi_processor_set_pdc(struct acpi_processor *pr, | ||
| 188 | struct acpi_object_list *pdc_in); | ||
| 189 | |||
| 190 | #ifdef ARCH_HAS_POWER_PDC_INIT | ||
| 191 | void acpi_processor_power_init_pdc(struct acpi_processor_power *pow, | ||
| 192 | unsigned int cpu); | ||
| 193 | void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, | ||
| 194 | unsigned int cpu); | ||
| 195 | #else | ||
| 196 | static inline void acpi_processor_power_init_pdc( | ||
| 197 | struct acpi_processor_power *pow, unsigned int cpu) | ||
| 198 | { | ||
| 199 | pow->pdc = NULL; | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | |||
| 203 | static inline void acpi_processor_power_init_bm_check( | ||
| 204 | struct acpi_processor_flags *flags, unsigned int cpu) | ||
| 205 | { | ||
| 206 | flags->bm_check = 1; | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | #endif | ||
| 210 | |||
| 182 | /* in processor_perflib.c */ | 211 | /* in processor_perflib.c */ |
| 212 | |||
| 183 | #ifdef CONFIG_CPU_FREQ | 213 | #ifdef CONFIG_CPU_FREQ |
| 184 | void acpi_processor_ppc_init(void); | 214 | void acpi_processor_ppc_init(void); |
| 185 | void acpi_processor_ppc_exit(void); | 215 | void acpi_processor_ppc_exit(void); |
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h index c976c1dadece..cf828ace13f9 100644 --- a/include/asm-i386/acpi.h +++ b/include/asm-i386/acpi.h | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | 28 | ||
| 29 | #ifdef __KERNEL__ | 29 | #ifdef __KERNEL__ |
| 30 | 30 | ||
| 31 | #include <acpi/pdc_intel.h> | ||
| 32 | |||
| 31 | #include <asm/system.h> /* defines cmpxchg */ | 33 | #include <asm/system.h> /* defines cmpxchg */ |
| 32 | 34 | ||
| 33 | #define COMPILER_DEPENDENT_INT64 long long | 35 | #define COMPILER_DEPENDENT_INT64 long long |
| @@ -101,12 +103,6 @@ __acpi_release_global_lock (unsigned int *lock) | |||
| 101 | :"=r"(n_hi), "=r"(n_lo) \ | 103 | :"=r"(n_hi), "=r"(n_lo) \ |
| 102 | :"0"(n_hi), "1"(n_lo)) | 104 | :"0"(n_hi), "1"(n_lo)) |
| 103 | 105 | ||
| 104 | /* | ||
| 105 | * Refer Intel ACPI _PDC support document for bit definitions | ||
| 106 | */ | ||
| 107 | #define ACPI_PDC_EST_CAPABILITY_SMP 0xa | ||
| 108 | #define ACPI_PDC_EST_CAPABILITY_MSR 0x1 | ||
| 109 | |||
| 110 | #ifdef CONFIG_ACPI_BOOT | 106 | #ifdef CONFIG_ACPI_BOOT |
| 111 | extern int acpi_lapic; | 107 | extern int acpi_lapic; |
| 112 | extern int acpi_ioapic; | 108 | extern int acpi_ioapic; |
| @@ -185,6 +181,8 @@ extern void acpi_reserve_bootmem(void); | |||
| 185 | 181 | ||
| 186 | extern u8 x86_acpiid_to_apicid[]; | 182 | extern u8 x86_acpiid_to_apicid[]; |
| 187 | 183 | ||
| 184 | #define ARCH_HAS_POWER_PDC_INIT 1 | ||
| 185 | |||
| 188 | #endif /*__KERNEL__*/ | 186 | #endif /*__KERNEL__*/ |
| 189 | 187 | ||
| 190 | #endif /*_ASM_ACPI_H*/ | 188 | #endif /*_ASM_ACPI_H*/ |
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h index a6b41b892062..dc8c981af27f 100644 --- a/include/asm-x86_64/acpi.h +++ b/include/asm-x86_64/acpi.h | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | 28 | ||
| 29 | #ifdef __KERNEL__ | 29 | #ifdef __KERNEL__ |
| 30 | 30 | ||
| 31 | #include <acpi/pdc_intel.h> | ||
| 32 | |||
| 31 | #define COMPILER_DEPENDENT_INT64 long long | 33 | #define COMPILER_DEPENDENT_INT64 long long |
| 32 | #define COMPILER_DEPENDENT_UINT64 unsigned long long | 34 | #define COMPILER_DEPENDENT_UINT64 unsigned long long |
| 33 | 35 | ||
| @@ -99,12 +101,6 @@ __acpi_release_global_lock (unsigned int *lock) | |||
| 99 | :"=r"(n_hi), "=r"(n_lo) \ | 101 | :"=r"(n_hi), "=r"(n_lo) \ |
| 100 | :"0"(n_hi), "1"(n_lo)) | 102 | :"0"(n_hi), "1"(n_lo)) |
| 101 | 103 | ||
| 102 | /* | ||
| 103 | * Refer Intel ACPI _PDC support document for bit definitions | ||
| 104 | */ | ||
| 105 | #define ACPI_PDC_EST_CAPABILITY_SMP 0xa | ||
| 106 | #define ACPI_PDC_EST_CAPABILITY_MSR 0x1 | ||
| 107 | |||
| 108 | #ifdef CONFIG_ACPI_BOOT | 104 | #ifdef CONFIG_ACPI_BOOT |
| 109 | extern int acpi_lapic; | 105 | extern int acpi_lapic; |
| 110 | extern int acpi_ioapic; | 106 | extern int acpi_ioapic; |
