[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] CPUIDLE: Support C1 FFH entry
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1225373620 0 # Node ID 112e81ae5824e213b181a65f944b729ba270d658 # Parent 1137464400a81bbfe7a5093a07102b2ded7a4684 CPUIDLE: Support C1 FFH entry Add support for C1 FFH (mwait) entry. Meanwhile add timing for C1. The timing for C1 should be accurate for FFH case, but may not for halt case. Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx> --- xen/arch/x86/acpi/cpu_idle.c | 84 ++++++++++++++++++--------------------- xen/arch/x86/acpi/cpuidle_menu.c | 14 ------ xen/include/xen/cpuidle.h | 7 ++- 3 files changed, 48 insertions(+), 57 deletions(-) diff -r 1137464400a8 -r 112e81ae5824 xen/arch/x86/acpi/cpu_idle.c --- a/xen/arch/x86/acpi/cpu_idle.c Thu Oct 30 13:33:17 2008 +0000 +++ b/xen/arch/x86/acpi/cpu_idle.c Thu Oct 30 13:33:40 2008 +0000 @@ -140,20 +140,26 @@ static void acpi_processor_ffh_cstate_en static void acpi_idle_do_entry(struct acpi_processor_cx *cx) { - if ( cx->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE ) - { + int unused; + + switch ( cx->entry_method ) + { + case ACPI_CSTATE_EM_FFH: /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cx); - } - else - { - int unused; + return; + case ACPI_CSTATE_EM_SYSIO: /* IO port based C-state */ inb(cx->address); /* Dummy wait op - must do something useless after P_LVL2 read because chipsets cannot guarantee that STPCLK# signal gets asserted in time to freeze execution properly. */ unused = inl(pmtmr_ioport); + return; + case ACPI_CSTATE_EM_HALT: + acpi_safe_halt(); + local_irq_disable(); + return; } } @@ -253,35 +259,11 @@ static void acpi_processor_idle(void) switch ( cx->type ) { case ACPI_STATE_C1: - /* Trace cpu idle entry */ - TRACE_1D(TRC_PM_IDLE_ENTRY, 1); - - /* - * Invoke C1. - * Use the appropriate idle routine, the one that would - * be used without acpi C-states. - */ - if ( pm_idle_save ) - pm_idle_save(); - else - acpi_safe_halt(); - - /* Trace cpu idle exit */ - TRACE_1D(TRC_PM_IDLE_EXIT, 1); - - /* - * TBD: Can't get time duration while in C1, as resumes - * go to an ISR rather than here. Need to instrument - * base interrupt handler. - */ - sleep_ticks = 0xFFFFFFFF; - break; - case ACPI_STATE_C2: - if ( local_apic_timer_c2_ok ) + if ( cx->type == ACPI_STATE_C1 || local_apic_timer_c2_ok ) { /* Trace cpu idle entry */ - TRACE_1D(TRC_PM_IDLE_ENTRY, 2); + TRACE_1D(TRC_PM_IDLE_ENTRY, cx->idx); /* Get start time (ticks) */ t1 = inl(pmtmr_ioport); /* Invoke C2 */ @@ -289,7 +271,7 @@ static void acpi_processor_idle(void) /* Get end time (ticks) */ t2 = inl(pmtmr_ioport); /* Trace cpu idle exit */ - TRACE_1D(TRC_PM_IDLE_EXIT, 2); + TRACE_1D(TRC_PM_IDLE_EXIT, cx->idx); /* Re-enable interrupts */ local_irq_enable(); @@ -396,6 +378,7 @@ static int init_cx_pminfo(struct acpi_pr acpi_power->states[i].idx = i; acpi_power->states[ACPI_STATE_C1].type = ACPI_STATE_C1; + acpi_power->states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_EM_HALT; acpi_power->states[ACPI_STATE_C0].valid = 1; acpi_power->states[ACPI_STATE_C1].valid = 1; @@ -492,16 +475,13 @@ static int check_cx(struct acpi_processo break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - if ( cx->type > ACPI_STATE_C1 ) - { - if ( cx->reg.bit_width != VENDOR_INTEL || - cx->reg.bit_offset != NATIVE_CSTATE_BEYOND_HALT ) - return -EINVAL; - - /* assume all logical cpu has the same support for mwait */ - if ( acpi_processor_ffh_cstate_probe(cx) ) - return -EINVAL; - } + if ( cx->reg.bit_width != VENDOR_INTEL || + cx->reg.bit_offset != NATIVE_CSTATE_BEYOND_HALT ) + return -EINVAL; + + /* assume all logical cpu has the same support for mwait */ + if ( acpi_processor_ffh_cstate_probe(cx) ) + return -EINVAL; break; default: @@ -605,7 +585,23 @@ static void set_cx( cx->valid = 1; cx->type = xen_cx->type; cx->address = xen_cx->reg.address; - cx->space_id = xen_cx->reg.space_id; + + switch ( xen_cx->reg.space_id ) + { + case ACPI_ADR_SPACE_FIXED_HARDWARE: + if ( xen_cx->reg.bit_width == VENDOR_INTEL && + xen_cx->reg.bit_offset == NATIVE_CSTATE_BEYOND_HALT ) + cx->entry_method = ACPI_CSTATE_EM_FFH; + else + cx->entry_method = ACPI_CSTATE_EM_HALT; + break; + case ACPI_ADR_SPACE_SYSTEM_IO: + cx->entry_method = ACPI_CSTATE_EM_SYSIO; + break; + default: + cx->entry_method = ACPI_CSTATE_EM_NONE; + } + cx->latency = xen_cx->latency; cx->power = xen_cx->power; diff -r 1137464400a8 -r 112e81ae5824 xen/arch/x86/acpi/cpuidle_menu.c --- a/xen/arch/x86/acpi/cpuidle_menu.c Thu Oct 30 13:33:17 2008 +0000 +++ b/xen/arch/x86/acpi/cpuidle_menu.c Thu Oct 30 13:33:40 2008 +0000 @@ -59,7 +59,7 @@ static int menu_select(struct acpi_proce data->expected_us = (u32) get_sleep_length_ns() / 1000; /* find the deepest idle state that satisfies our constraints */ - for ( i = 1; i < power->count; i++ ) + for ( i = 2; i < power->count; i++ ) { struct acpi_processor_cx *s = &power->states[i]; @@ -81,17 +81,7 @@ static void menu_reflect(struct acpi_pro unsigned int last_residency; unsigned int measured_us; - /* - * Ugh, this idle state doesn't support residency measurements, so we - * are basically lost in the dark. As a compromise, assume we slept - * for one full standard timer tick. However, be aware that this - * could potentially result in a suboptimal state transition. - */ - if ( target->type == ACPI_STATE_C1 ) - last_residency = USEC_PER_SEC / HZ; - else - last_residency = power->last_residency; - + last_residency = power->last_residency; measured_us = last_residency + data->elapsed_us; /* if wrapping, set to max uint (-1) */ diff -r 1137464400a8 -r 112e81ae5824 xen/include/xen/cpuidle.h --- a/xen/include/xen/cpuidle.h Thu Oct 30 13:33:17 2008 +0000 +++ b/xen/include/xen/cpuidle.h Thu Oct 30 13:33:40 2008 +0000 @@ -30,13 +30,18 @@ #define ACPI_PROCESSOR_MAX_POWER 8 #define CPUIDLE_NAME_LEN 16 +#define ACPI_CSTATE_EM_NONE 0 +#define ACPI_CSTATE_EM_SYSIO 1 +#define ACPI_CSTATE_EM_FFH 2 +#define ACPI_CSTATE_EM_HALT 3 + struct acpi_processor_cx { u8 idx; u8 valid; u8 type; u32 address; - u8 space_id; + u8 entry_method; /* ACPI_CSTATE_EM_xxx */ u32 latency; u32 latency_ticks; u32 power; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |