ACPI C-States [Was: Re: [PATCH] i386 No Idle HZ aka dynticks 051217]

From: Dominik Brodowski
Date: Sun Dec 18 2005 - 19:19:06 EST


A few improvements and bugfixes to the ACPI C-States management based on
what's already in your dyn-tick patchset:
- last_sleep needs to be per-CPU
- cx->time for C1-type sleep is meaningless, remove support for it.
- Add a fast-path demotion: if dynticks are enabled, we can relax a bit
and use a more responsive sleep type if we're going to sleep only
for a short period of time (<1 tick), as long as we get back to deep
sleep soon (quick_promotion).

Signed-off-by: Dominik Brodowski <linux@xxxxxxxxxxxxxxxxxxxx>

Index: working-tree/drivers/acpi/processor_idle.c
===================================================================
--- working-tree.orig/drivers/acpi/processor_idle.c
+++ working-tree/drivers/acpi/processor_idle.c
@@ -180,7 +180,6 @@ static void acpi_safe_halt(void)
}

static atomic_t c3_cpu_count;
-static int last_sleep = 0;

static void acpi_processor_idle(void)
{
@@ -277,28 +276,55 @@ static void acpi_processor_idle(void)
next_state = cx->demotion.state;
if (dyn_tick_enabled())
dyn_early_reprogram(BM_JIFFIES);
- last_sleep = 0; /* do not promote in fast-path */
+ /* do not promote in fast-path */
+ pr->power.last_sleep = 0;
goto end;
}
}

/*
- * Fast-path promotion: if we slept for more than 2 jiffies the last
- * time, and we're intended to sleep for more than 2 jiffies now,
- * promote. Note that the processor won't enter a low-power state
- * during this call (to this funciton) but should upon the next.
+ * Some special policy tweaks for dynamic ticks
*/
if (dyn_tick_enabled()) {
+ /*
+ * Fast-path promotion: if we slept for more than 2 jiffies the
+ * last time, and we're intended to sleep for more than 2
+ * jiffies now, promote. Note that the processor won't enter a
+ * low-power state during this call (to this funciton) but
+ * should upon the next.
+ */
if (cx->promotion.state && cx->promotion.count &&
- (last_sleep > BM_JIFFIES) &&
+ (dyn_tick->next_tick > jiffies) &&
+ ((pr->power.last_sleep >
+ (BM_JIFFIES * cx->promotion.threshold.ticks)) ||
+ (pr->power.quick_promotion == 1)) &&
(dyn_tick->skip > BM_JIFFIES)) {
local_irq_enable();
next_state = cx->promotion.state;
goto end;
}
+
+
+ /*
+ * Fast-path demotion: if we're going to sleep for only one
+ * jiffy, and we'd enter C3-type sleep, and the wakeup latency
+ * is high, don't use C3-type sleep but (temporarily) C2.
+ */
+ if (cx->demotion.state && cx->demotion.threshold.bm &&
+ (dyn_tick->next_tick < (jiffies + 1))
+ && (cx->latency > 150)) {
+ local_irq_enable();
+ next_state = cx->demotion.state;
+
+ /* don't do a fast-path promotion next time... */
+ pr->power.last_sleep = 0;
+ /* ... but thereafter. */
+ pr->power.quick_promotion = 2;
+ goto end;
+ }
}

- last_sleep = 0;
+ pr->power.last_sleep = 0;

#ifdef CONFIG_HOTPLUG_CPU
/*
@@ -411,19 +437,18 @@ static void acpi_processor_idle(void)
if (cx->type != ACPI_STATE_C1) {
if (sleep_ticks > 0)
cx->time += sleep_ticks;
- } else {
- /* for C1, where we don't know the exact value, assume 0.5 of
- * a jiffy */
- cx->time += (PM_TIMER_FREQUENCY / (2 * HZ));
}

- last_sleep = sleep_ticks / (PM_TIMER_FREQUENCY / HZ);
+ pr->power.last_sleep = sleep_ticks / (PM_TIMER_FREQUENCY / HZ);

if (pr->flags.bm_check)
- pr->power.bm_check_timestamp += last_sleep;
+ pr->power.bm_check_timestamp += pr->power.last_sleep;

next_state = pr->power.state;

+ if (pr->power.quick_promotion)
+ pr->power.quick_promotion--;
+
/*
* Promotion?
* ----------
Index: working-tree/include/acpi/processor.h
===================================================================
--- working-tree.orig/include/acpi/processor.h
+++ working-tree/include/acpi/processor.h
@@ -61,6 +61,8 @@ struct acpi_processor_power {
unsigned long bm_check_timestamp;
u32 default_state;
u32 bm_activity;
+ u16 last_sleep;
+ u16 quick_promotion;
int count;
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/