aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>2006-09-25 19:28:13 -0400
committerLen Brown <len.brown@intel.com>2006-10-14 00:35:39 -0400
commit991528d7348667924176f3e29addea0675298944 (patch)
treeed8552bd4c696700a95ae37b26c4197923207ae7 /drivers
parentb4bd8c66435a8cdf8c90334fb3b517a23ff2ab95 (diff)
ACPI: Processor native C-states using MWAIT
Intel processors starting with the Core Duo support support processor native C-state using the MWAIT instruction. Refer: Intel Architecture Software Developer's Manual http://www.intel.com/design/Pentium4/manuals/253668.htm Platform firmware exports the support for Native C-state to OS using ACPI _PDC and _CST methods. Refer: Intel Processor Vendor-Specific ACPI: Interface Specification http://www.intel.com/technology/iapc/acpi/downloads/302223.htm With Processor Native C-state, we use 'MWAIT' instruction on the processor to enter different C-states (C1, C2, C3). We won't use the special IO ports to enter C-state and no SMM mode etc required to enter C-state. Overall this will mean better C-state support. One major advantage of using MWAIT for all C-states is, with this and "treat interrupt as break event" feature of MWAIT, we can now get accurate timing for the time spent in C1, C2, .. states. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_idle.c101
1 files changed, 63 insertions, 38 deletions
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
220static atomic_t c3_cpu_count; 220static atomic_t c3_cpu_count;
221 221
222/* Common C-state entry for C2, C3, .. */
223static 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
222static void acpi_processor_idle(void) 239static 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
631static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) 642static 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 /*