* [patch 1/4] ACPI: Fix acpi_safe_halt usages and interrupt enabling/disabling
2008-02-01 1:35 [patch 0/4] ACPI, CPU_IDLE: ACPI processor_idle changes, C1 residency time, etc venkatesh.pallipadi
@ 2008-02-01 1:35 ` venkatesh.pallipadi
2008-02-07 7:21 ` Len Brown
2008-02-01 1:35 ` [patch 2/4] ACPI: Use mwait for C1 idle venkatesh.pallipadi
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: venkatesh.pallipadi @ 2008-02-01 1:35 UTC (permalink / raw)
To: lenb, len.brown; +Cc: linux-acpi, Venkatesh Pallipadi
[-- Attachment #1: acpi_fix_safe_halt.patch --]
[-- Type: text/plain, Size: 1818 bytes --]
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.
There were multiple places where this was not happening. Below is the fix.
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
+++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
@@ -201,6 +201,10 @@ static inline u32 ticks_elapsed_in_us(u3
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;
@@ -393,6 +397,8 @@ static void acpi_processor_idle(void)
pm_idle_save();
else
acpi_safe_halt();
+
+ local_irq_enable();
return;
}
@@ -501,6 +507,7 @@ static void acpi_processor_idle(void)
* skew otherwise.
*/
sleep_ticks = 0xFFFFFFFF;
+ local_irq_enable();
break;
case ACPI_STATE_C2:
@@ -1378,11 +1385,13 @@ static int acpi_idle_enter_c1(struct cpu
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;
@@ -1490,7 +1499,9 @@ static int acpi_idle_enter_bm(struct cpu
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;
}
}
--
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [patch 1/4] ACPI: Fix acpi_safe_halt usages and interrupt enabling/disabling
2008-02-01 1:35 ` [patch 1/4] ACPI: Fix acpi_safe_halt usages and interrupt enabling/disabling venkatesh.pallipadi
@ 2008-02-07 7:21 ` Len Brown
0 siblings, 0 replies; 9+ messages in thread
From: Len Brown @ 2008-02-07 7:21 UTC (permalink / raw)
To: venkatesh.pallipadi; +Cc: linux-acpi
applied.
thanks,
-len
On Thursday 31 January 2008 20:35, venkatesh.pallipadi@intel.com wrote:
> 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.
>
> There were multiple places where this was not happening. Below is the fix.
>
> Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
>
> Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
> ===================================================================
> --- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
> +++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
> @@ -201,6 +201,10 @@ static inline u32 ticks_elapsed_in_us(u3
> 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;
> @@ -393,6 +397,8 @@ static void acpi_processor_idle(void)
> pm_idle_save();
> else
> acpi_safe_halt();
> +
> + local_irq_enable();
> return;
> }
>
> @@ -501,6 +507,7 @@ static void acpi_processor_idle(void)
> * skew otherwise.
> */
> sleep_ticks = 0xFFFFFFFF;
> + local_irq_enable();
> break;
>
> case ACPI_STATE_C2:
> @@ -1378,11 +1385,13 @@ static int acpi_idle_enter_c1(struct cpu
> 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;
> @@ -1490,7 +1499,9 @@ static int acpi_idle_enter_bm(struct cpu
> 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;
> }
> }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 2/4] ACPI: Use mwait for C1 idle
2008-02-01 1:35 [patch 0/4] ACPI, CPU_IDLE: ACPI processor_idle changes, C1 residency time, etc venkatesh.pallipadi
2008-02-01 1:35 ` [patch 1/4] ACPI: Fix acpi_safe_halt usages and interrupt enabling/disabling venkatesh.pallipadi
@ 2008-02-01 1:35 ` venkatesh.pallipadi
2008-02-07 7:38 ` Len Brown
2008-02-01 1:35 ` [patch 3/4] ACPI, CPU_IDLE: Support C1 idle time accounting venkatesh.pallipadi
2008-02-01 1:35 ` [patch 4/4] CPUIDLE: Add a poll_idle method into CPU_IDLE venkatesh.pallipadi
3 siblings, 1 reply; 9+ messages in thread
From: venkatesh.pallipadi @ 2008-02-01 1:35 UTC (permalink / raw)
To: lenb, len.brown; +Cc: linux-acpi, Venkatesh Pallipadi
[-- Attachment #1: acpi_c1_mwait.patch --]
[-- Type: text/plain, Size: 3041 bytes --]
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 <venkatesh.pallipadi@intel.com>
Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
+++ linux-2.6.25-rc/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 {
@@ -904,20 +904,20 @@ static int acpi_processor_get_power_info
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;
}
}
@@ -1351,12 +1351,16 @@ static inline void acpi_idle_update_bm_r
/**
* 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 */
@@ -1389,7 +1393,7 @@ static int acpi_idle_enter_c1(struct cpu
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++;
Index: linux-2.6.25-rc/include/acpi/processor.h
===================================================================
--- linux-2.6.25-rc.orig/include/acpi/processor.h
+++ linux-2.6.25-rc/include/acpi/processor.h
@@ -34,6 +34,7 @@
#define ACPI_CSTATE_SYSTEMIO (0)
#define ACPI_CSTATE_FFH (1)
+#define ACPI_CSTATE_HALT (2)
/* Power Management */
@@ -64,7 +65,7 @@ struct acpi_processor_cx {
u8 valid;
u8 type;
u32 address;
- u8 space_id;
+ u8 entry_method;
u8 index;
u32 latency;
u32 latency_ticks;
--
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [patch 2/4] ACPI: Use mwait for C1 idle
2008-02-01 1:35 ` [patch 2/4] ACPI: Use mwait for C1 idle venkatesh.pallipadi
@ 2008-02-07 7:38 ` Len Brown
0 siblings, 0 replies; 9+ messages in thread
From: Len Brown @ 2008-02-07 7:38 UTC (permalink / raw)
To: venkatesh.pallipadi; +Cc: linux-acpi
applied.
thanks,
-len
On Thursday 31 January 2008 20:35, venkatesh.pallipadi@intel.com wrote:
> 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 <venkatesh.pallipadi@intel.com>
>
> Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
> ===================================================================
> --- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
> +++ linux-2.6.25-rc/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 {
> @@ -904,20 +904,20 @@ static int acpi_processor_get_power_info
> 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;
> }
> }
> @@ -1351,12 +1351,16 @@ static inline void acpi_idle_update_bm_r
> /**
> * 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 */
> @@ -1389,7 +1393,7 @@ static int acpi_idle_enter_c1(struct cpu
> 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++;
> Index: linux-2.6.25-rc/include/acpi/processor.h
> ===================================================================
> --- linux-2.6.25-rc.orig/include/acpi/processor.h
> +++ linux-2.6.25-rc/include/acpi/processor.h
> @@ -34,6 +34,7 @@
>
> #define ACPI_CSTATE_SYSTEMIO (0)
> #define ACPI_CSTATE_FFH (1)
> +#define ACPI_CSTATE_HALT (2)
>
> /* Power Management */
>
> @@ -64,7 +65,7 @@ struct acpi_processor_cx {
> u8 valid;
> u8 type;
> u32 address;
> - u8 space_id;
> + u8 entry_method;
> u8 index;
> u32 latency;
> u32 latency_ticks;
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 3/4] ACPI, CPU_IDLE: Support C1 idle time accounting
2008-02-01 1:35 [patch 0/4] ACPI, CPU_IDLE: ACPI processor_idle changes, C1 residency time, etc venkatesh.pallipadi
2008-02-01 1:35 ` [patch 1/4] ACPI: Fix acpi_safe_halt usages and interrupt enabling/disabling venkatesh.pallipadi
2008-02-01 1:35 ` [patch 2/4] ACPI: Use mwait for C1 idle venkatesh.pallipadi
@ 2008-02-01 1:35 ` venkatesh.pallipadi
2008-02-07 7:38 ` Len Brown
2008-02-01 1:35 ` [patch 4/4] CPUIDLE: Add a poll_idle method into CPU_IDLE venkatesh.pallipadi
3 siblings, 1 reply; 9+ messages in thread
From: venkatesh.pallipadi @ 2008-02-01 1:35 UTC (permalink / raw)
To: lenb, len.brown; +Cc: linux-acpi, Venkatesh Pallipadi
[-- Attachment #1: acpi_cpuidle_c1_resident_time.patch --]
[-- Type: text/plain, Size: 1506 bytes --]
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 <venkatesh.pallipadi@intel.com>
Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
+++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
@@ -1382,8 +1382,10 @@ static inline void acpi_idle_do_entry(st
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))
@@ -1393,12 +1395,14 @@ static int acpi_idle_enter_c1(struct cpu
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);
}
/**
@@ -1632,6 +1636,7 @@ static int acpi_processor_setup_cpuidle(
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;
--
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [patch 3/4] ACPI, CPU_IDLE: Support C1 idle time accounting
2008-02-01 1:35 ` [patch 3/4] ACPI, CPU_IDLE: Support C1 idle time accounting venkatesh.pallipadi
@ 2008-02-07 7:38 ` Len Brown
0 siblings, 0 replies; 9+ messages in thread
From: Len Brown @ 2008-02-07 7:38 UTC (permalink / raw)
To: venkatesh.pallipadi; +Cc: linux-acpi
applied.
thanks,
-len
On Thursday 31 January 2008 20:35, venkatesh.pallipadi@intel.com wrote:
> 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 <venkatesh.pallipadi@intel.com>
>
> Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
> ===================================================================
> --- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
> +++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
> @@ -1382,8 +1382,10 @@ static inline void acpi_idle_do_entry(st
> 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))
> @@ -1393,12 +1395,14 @@ static int acpi_idle_enter_c1(struct cpu
> 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);
> }
>
> /**
> @@ -1632,6 +1636,7 @@ static int acpi_processor_setup_cpuidle(
> 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;
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [patch 4/4] CPUIDLE: Add a poll_idle method into CPU_IDLE
2008-02-01 1:35 [patch 0/4] ACPI, CPU_IDLE: ACPI processor_idle changes, C1 residency time, etc venkatesh.pallipadi
` (2 preceding siblings ...)
2008-02-01 1:35 ` [patch 3/4] ACPI, CPU_IDLE: Support C1 idle time accounting venkatesh.pallipadi
@ 2008-02-01 1:35 ` venkatesh.pallipadi
2008-02-07 7:38 ` Len Brown
3 siblings, 1 reply; 9+ messages in thread
From: venkatesh.pallipadi @ 2008-02-01 1:35 UTC (permalink / raw)
To: lenb, len.brown; +Cc: linux-acpi, Venkatesh Pallipadi
[-- Attachment #1: cpuidle_poll_idle.patch --]
[-- Type: text/plain, Size: 4175 bytes --]
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 <venkatesh.pallipadi@intel.com>
Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
+++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
@@ -1600,7 +1600,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;
@@ -1659,6 +1659,8 @@ static int acpi_processor_setup_cpuidle(
}
count++;
+ if (count == CPUIDLE_STATE_MAX)
+ break;
}
dev->state_count = count;
Index: linux-2.6.25-rc/drivers/cpuidle/cpuidle.c
===================================================================
--- linux-2.6.25-rc.orig/drivers/cpuidle/cpuidle.c
+++ linux-2.6.25-rc/drivers/cpuidle/cpuidle.c
@@ -15,6 +15,7 @@
#include <linux/latency.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
+#include <linux/ktime.h>
#include "cpuidle.h"
@@ -180,6 +181,44 @@ void cpuidle_disable_device(struct cpuid
EXPORT_SYMBOL_GPL(cpuidle_disable_device);
+#ifdef CONFIG_ARCH_HAS_CPU_RELAX
+static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+{
+ ktime_t t1, t2;
+ s64 diff;
+ int ret;
+
+ t1 = ktime_get();
+ local_irq_enable();
+ while (!need_resched()) {
+ cpu_relax();
+ }
+ t2 = ktime_get();
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+
+ ret = (int) diff;
+ return ret;
+}
+
+static void poll_idle_init(struct cpuidle_device *dev)
+{
+ struct cpuidle_state *state = &dev->states[0];
+
+ cpuidle_set_statedata(state, NULL);
+
+ snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)");
+ state->exit_latency = 0;
+ state->target_residency = 0;
+ state->power_usage = -1;
+ state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID;
+ state->enter = poll_idle;
+}
+#else
+static void poll_idle_init(struct cpuidle_device *dev) {}
+#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
+
/**
* cpuidle_register_device - registers a CPU's idle PM feature
* @dev: the cpu
@@ -198,6 +237,8 @@ int cpuidle_register_device(struct cpuid
mutex_lock(&cpuidle_lock);
+ poll_idle_init(dev);
+
per_cpu(cpuidle_devices, dev->cpu) = dev;
list_add(&dev->device_list, &cpuidle_detected_devices);
if ((ret = cpuidle_add_sysfs(sys_dev))) {
Index: linux-2.6.25-rc/include/linux/cpuidle.h
===================================================================
--- linux-2.6.25-rc.orig/include/linux/cpuidle.h
+++ linux-2.6.25-rc/include/linux/cpuidle.h
@@ -46,9 +46,10 @@ struct cpuidle_state {
/* Idle State Flags */
#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
#define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */
-#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */
-#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */
-#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */
+#define CPUIDLE_FLAG_POLL (0x10) /* no latency, no savings */
+#define CPUIDLE_FLAG_SHALLOW (0x20) /* low latency, minimal savings */
+#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */
+#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */
#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
@@ -178,4 +179,10 @@ static inline void cpuidle_unregister_go
#endif
+#ifdef CONFIG_ARCH_HAS_CPU_RELAX
+#define CPUIDLE_DRIVER_STATE_START 1
+#else
+#define CPUIDLE_DRIVER_STATE_START 0
+#endif
+
#endif /* _LINUX_CPUIDLE_H */
Index: linux-2.6.25-rc/arch/x86/Kconfig
===================================================================
--- linux-2.6.25-rc.orig/arch/x86/Kconfig
+++ linux-2.6.25-rc/arch/x86/Kconfig
@@ -112,6 +112,9 @@ config GENERIC_TIME_VSYSCALL
bool
default X86_64
+config ARCH_HAS_CPU_RELAX
+ def_bool y
+
config ARCH_SUPPORTS_OPROFILE
bool
default y
--
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [patch 4/4] CPUIDLE: Add a poll_idle method into CPU_IDLE
2008-02-01 1:35 ` [patch 4/4] CPUIDLE: Add a poll_idle method into CPU_IDLE venkatesh.pallipadi
@ 2008-02-07 7:38 ` Len Brown
0 siblings, 0 replies; 9+ messages in thread
From: Len Brown @ 2008-02-07 7:38 UTC (permalink / raw)
To: venkatesh.pallipadi; +Cc: linux-acpi
applied,
thanks,
-len
On Thursday 31 January 2008 20:35, venkatesh.pallipadi@intel.com wrote:
> 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 <venkatesh.pallipadi@intel.com>
>
> Index: linux-2.6.25-rc/drivers/acpi/processor_idle.c
> ===================================================================
> --- linux-2.6.25-rc.orig/drivers/acpi/processor_idle.c
> +++ linux-2.6.25-rc/drivers/acpi/processor_idle.c
> @@ -1600,7 +1600,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;
> @@ -1659,6 +1659,8 @@ static int acpi_processor_setup_cpuidle(
> }
>
> count++;
> + if (count == CPUIDLE_STATE_MAX)
> + break;
> }
>
> dev->state_count = count;
> Index: linux-2.6.25-rc/drivers/cpuidle/cpuidle.c
> ===================================================================
> --- linux-2.6.25-rc.orig/drivers/cpuidle/cpuidle.c
> +++ linux-2.6.25-rc/drivers/cpuidle/cpuidle.c
> @@ -15,6 +15,7 @@
> #include <linux/latency.h>
> #include <linux/cpu.h>
> #include <linux/cpuidle.h>
> +#include <linux/ktime.h>
>
> #include "cpuidle.h"
>
> @@ -180,6 +181,44 @@ void cpuidle_disable_device(struct cpuid
>
> EXPORT_SYMBOL_GPL(cpuidle_disable_device);
>
> +#ifdef CONFIG_ARCH_HAS_CPU_RELAX
> +static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
> +{
> + ktime_t t1, t2;
> + s64 diff;
> + int ret;
> +
> + t1 = ktime_get();
> + local_irq_enable();
> + while (!need_resched()) {
> + cpu_relax();
> + }
> + t2 = ktime_get();
> + diff = ktime_to_us(ktime_sub(t2, t1));
> + if (diff > INT_MAX)
> + diff = INT_MAX;
> +
> + ret = (int) diff;
> + return ret;
> +}
> +
> +static void poll_idle_init(struct cpuidle_device *dev)
> +{
> + struct cpuidle_state *state = &dev->states[0];
> +
> + cpuidle_set_statedata(state, NULL);
> +
> + snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)");
> + state->exit_latency = 0;
> + state->target_residency = 0;
> + state->power_usage = -1;
> + state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID;
> + state->enter = poll_idle;
> +}
> +#else
> +static void poll_idle_init(struct cpuidle_device *dev) {}
> +#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
> +
> /**
> * cpuidle_register_device - registers a CPU's idle PM feature
> * @dev: the cpu
> @@ -198,6 +237,8 @@ int cpuidle_register_device(struct cpuid
>
> mutex_lock(&cpuidle_lock);
>
> + poll_idle_init(dev);
> +
> per_cpu(cpuidle_devices, dev->cpu) = dev;
> list_add(&dev->device_list, &cpuidle_detected_devices);
> if ((ret = cpuidle_add_sysfs(sys_dev))) {
> Index: linux-2.6.25-rc/include/linux/cpuidle.h
> ===================================================================
> --- linux-2.6.25-rc.orig/include/linux/cpuidle.h
> +++ linux-2.6.25-rc/include/linux/cpuidle.h
> @@ -46,9 +46,10 @@ struct cpuidle_state {
> /* Idle State Flags */
> #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
> #define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */
> -#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */
> -#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */
> -#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */
> +#define CPUIDLE_FLAG_POLL (0x10) /* no latency, no savings */
> +#define CPUIDLE_FLAG_SHALLOW (0x20) /* low latency, minimal savings */
> +#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */
> +#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */
>
> #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
>
> @@ -178,4 +179,10 @@ static inline void cpuidle_unregister_go
>
> #endif
>
> +#ifdef CONFIG_ARCH_HAS_CPU_RELAX
> +#define CPUIDLE_DRIVER_STATE_START 1
> +#else
> +#define CPUIDLE_DRIVER_STATE_START 0
> +#endif
> +
> #endif /* _LINUX_CPUIDLE_H */
> Index: linux-2.6.25-rc/arch/x86/Kconfig
> ===================================================================
> --- linux-2.6.25-rc.orig/arch/x86/Kconfig
> +++ linux-2.6.25-rc/arch/x86/Kconfig
> @@ -112,6 +112,9 @@ config GENERIC_TIME_VSYSCALL
> bool
> default X86_64
>
> +config ARCH_HAS_CPU_RELAX
> + def_bool y
> +
> config ARCH_SUPPORTS_OPROFILE
> bool
> default y
>
^ permalink raw reply [flat|nested] 9+ messages in thread