From 4963f62045b64f93c45fbcb6f8f0baf1e3e7a127 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 13 Dec 2007 23:50:45 -0500 Subject: cpuidle: create processor.latency_factor tunable Start with default value of 6, so by default, there is no functional change in this patch. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f996d0e3768..26ade1f3f5c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -94,6 +94,9 @@ module_param(bm_history, uint, 0644); static int acpi_processor_set_power_policy(struct acpi_processor *pr); +#else /* CONFIG_CPU_IDLE */ +static unsigned int latency_factor __read_mostly = 6; +module_param(latency_factor, uint, 0644); #endif /* @@ -1576,7 +1579,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); state->exit_latency = cx->latency; - state->target_residency = cx->latency * 6; + state->target_residency = cx->latency * latency_factor; state->power_usage = cx->power; state->flags = 0; -- cgit v1.2.3 From 25de5718356e264820625600a9edca1df5ff26f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 14 Dec 2007 00:24:15 -0500 Subject: cpuidle: default processor.latency_factor=2 More aggressively request deep C-states. Note that the job of the OS is to minimize latency impact to expected break events such as interrupts. It is not the job of the OS to try to calculate if the C-state will reach energy break-even. The platform doesn't give the OS enough information for it to make that calculation. Thus, it is up to the platform to decide if it is worth it to go as deep as the OS requested it to, or if it should internally demote to a more shallow C-state. But the converse is not true. The platform can not promote into a deeper C-state than the OS requested else it may violate latency constraints. So it is important that the OS be aggressive in giving the platform permission to enter deep C-states. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 26ade1f3f5c..bc99b7b9094 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -95,7 +95,7 @@ module_param(bm_history, uint, 0644); static int acpi_processor_set_power_policy(struct acpi_processor *pr); #else /* CONFIG_CPU_IDLE */ -static unsigned int latency_factor __read_mostly = 6; +static unsigned int latency_factor __read_mostly = 2; module_param(latency_factor, uint, 0644); #endif -- cgit v1.2.3 From 2e906655baf1c6f6fccd212fc9e6499dc6928b80 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Thu, 31 Jan 2008 17:35:03 -0800 Subject: ACPI: idle: Fix acpi_safe_halt usages and interrupt enabling/disabling acpi_safe_halt() needs interrupts to be disabled for atomic need_resched check and safe halt. Otherwise we may miss an interrupt and go into halt. acpi_safe_halt() also does not enable interrupts on all return paths. So the callers should handle enable and disable interrupts around it. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 199ea214615..106a22948aa 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -201,6 +201,10 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } +/* + * Callers should disable interrupts before the call and enable + * interrupts after return. + */ static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; @@ -413,6 +417,8 @@ static void acpi_processor_idle(void) pm_idle_save(); else acpi_safe_halt(); + + local_irq_enable(); return; } @@ -521,6 +527,7 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; + local_irq_enable(); break; case ACPI_STATE_C2: @@ -1403,11 +1410,13 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (unlikely(!pr)) return 0; + local_irq_disable(); if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); acpi_safe_halt(); + local_irq_enable(); cx->usage++; return 0; @@ -1517,7 +1526,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (dev->safe_state) { return dev->safe_state->enter(dev, dev->safe_state); } else { + local_irq_disable(); acpi_safe_halt(); + local_irq_enable(); return 0; } } -- cgit v1.2.3 From bc71bec91f9875ef825d12104acf3bf4ca215fa4 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Thu, 31 Jan 2008 17:35:04 -0800 Subject: ACPI: enable MWAIT for C1 idle Add MWAIT idle for C1 state instead of halt, on platforms that support C1 state with MWAIT. Renames cx->space_id to something more appropriate. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 106a22948aa..4ba3a9a473d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -265,7 +265,7 @@ static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) { - if (cstate->space_id == ACPI_CSTATE_FFH) { + if (cstate->entry_method == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cstate); } else { @@ -929,20 +929,20 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address = reg->address; cx.index = current_count + 1; - cx.space_id = ACPI_CSTATE_SYSTEMIO; + cx.entry_method = ACPI_CSTATE_SYSTEMIO; if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { if (acpi_processor_ffh_cstate_probe (pr->id, &cx, reg) == 0) { - cx.space_id = ACPI_CSTATE_FFH; - } else if (cx.type != ACPI_STATE_C1) { + cx.entry_method = ACPI_CSTATE_FFH; + } else if (cx.type == ACPI_STATE_C1) { /* * C1 is a special case where FIXED_HARDWARE * can be handled in non-MWAIT way as well. * In that case, save this _CST entry info. - * That is, we retain space_id of SYSTEM_IO for - * halt based C1. * Otherwise, ignore this info and continue. */ + cx.entry_method = ACPI_CSTATE_HALT; + } else { continue; } } @@ -1376,12 +1376,16 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr, /** * acpi_idle_do_entry - a helper function that does C2 and C3 type entry * @cx: cstate data + * + * Caller disables interrupt before call and enables interrupt after return. */ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) { - if (cx->space_id == ACPI_CSTATE_FFH) { + if (cx->entry_method == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cx); + } else if (cx->entry_method == ACPI_CSTATE_HALT) { + acpi_safe_halt(); } else { int unused; /* IO port based C-state */ @@ -1414,7 +1418,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); - acpi_safe_halt(); + acpi_idle_do_entry(cx); local_irq_enable(); cx->usage++; -- cgit v1.2.3 From 9b12e18cdc1553de62d931e73443c806347cd974 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Thu, 31 Jan 2008 17:35:05 -0800 Subject: ACPI: cpuidle: Support C1 idle time accounting Show C1 idle time in /sysfs cpuidle interface. C1 idle time may not be entirely accurate in all cases. It includes the time spent in the interrupt handler after wakeup with "hlt" based C1. But, it will be accurate with "mwait" based C1. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 4ba3a9a473d..fea71597b40 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1407,8 +1407,10 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_state *state) { + u32 t1, t2; struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); + pr = processors[smp_processor_id()]; if (unlikely(!pr)) @@ -1418,12 +1420,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); + t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); + t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); local_irq_enable(); cx->usage++; - return 0; + return ticks_elapsed_in_us(t1, t2); } /** @@ -1660,6 +1664,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) switch (cx->type) { case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; + state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; -- cgit v1.2.3 From 9a0b841586c3c6c846effdbe75885c2ebc0031b0 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Thu, 31 Jan 2008 17:35:06 -0800 Subject: cpuidle: Add a poll_idle method Add a default poll idle state with 0 latency. Provides an option to users to use poll_idle by using 0 as the latency requirement. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index fea71597b40..32488e6f76a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1628,7 +1628,7 @@ struct cpuidle_driver acpi_idle_driver = { */ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) { - int i, count = 0; + int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_device *dev = &pr->power.dev; @@ -1687,6 +1687,8 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) } count++; + if (count == CPUIDLE_STATE_MAX) + break; } dev->state_count = count; -- cgit v1.2.3