Make the current "state" in struct acpi_processor_power a pointer. If it doesn't exist, simply use C1 type sleep... Signed-off-by: Dominik Brodowski drivers/acpi/processor_idle.c | 48 +++++++++++++++++++++++++++--------------- include/acpi/processor.h | 2 - 2 files changed, 32 insertions(+), 18 deletions(-) diff -ruN linux-original/drivers/acpi/processor_idle.c linux/drivers/acpi/processor_idle.c --- linux-original/drivers/acpi/processor_idle.c 2004-11-27 20:25:24.336644968 +0100 +++ linux/drivers/acpi/processor_idle.c 2004-11-27 20:25:29.620841648 +0100 @@ -102,19 +102,22 @@ if (!pr) return; - old = &pr->power.states[pr->power.state]; + old = pr->power.state; new = &pr->power.states[state]; - old->promotion.count = 0; + if (old) + old->promotion.count = 0; new->demotion.count = 0; /* Cleanup from old state. */ - switch (old->type) { - case ACPI_STATE_C3: - /* Disable bus master reload */ - if (new->type != ACPI_STATE_C3) - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); - break; + if (old) { + switch (old->type) { + case ACPI_STATE_C3: + /* Disable bus master reload */ + if (new->type != ACPI_STATE_C3) + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); + break; + } } /* Prepare to use new state. */ @@ -126,7 +129,7 @@ break; } - pr->power.state = state; + pr->power.state = new; return; } @@ -150,7 +153,9 @@ */ local_irq_disable(); - cx = &(pr->power.states[pr->power.state]); + cx = pr->power.state; + if (!cx) + goto easy_out; /* * Check BM Activity @@ -265,7 +270,7 @@ return; } - next_state = pr->power.state; + next_state = pr->power.state - pr->power.states; /* * Promotion? @@ -315,8 +320,9 @@ /* * Demote if current state exceeds acpi_cstate_limit */ - if (pr->power.state > acpi_cstate_limit) { - next_state = acpi_cstate_limit; + if (pr->power.state->type > acpi_cstate_limit) { + if (cx->demotion.state) + next_state = cx->demotion.state; } /* @@ -325,10 +331,18 @@ * If we're going to start using a new Cx state we must clean up * from the previous and prepare to use the new. */ - if (next_state != pr->power.state) + if (&pr->power.states[next_state] != pr->power.state) acpi_processor_power_activate(pr, next_state); return; + + easy_out: + /* do C1 instead of busy loop */ + if (pm_idle_save) + pm_idle_save(); + else + safe_halt(); + return; } @@ -354,7 +368,7 @@ * C0/C1 * ----- */ - pr->power.state = ACPI_STATE_C1; + pr->power.state = &pr->power.states[ACPI_STATE_C1]; /* * C1/C2 @@ -637,14 +651,14 @@ seq_printf(seq, "active state: %d\n" "bus master activity: %08x\n", - pr->power.state, + pr->power.state ? pr->power.state - pr->power.states : 0, pr->power.bm_activity); seq_puts(seq, "states:\n"); for (i = 1; i < ACPI_C_STATE_COUNT; i++) { seq_printf(seq, " %c%d: ", - (i == pr->power.state?'*':' '), i); + (&pr->power.states[i] == pr->power.state?'*':' '), i); if (!pr->power.states[i].valid) { seq_puts(seq, "\n"); diff -ruN linux-original/include/acpi/processor.h linux/include/acpi/processor.h --- linux-original/include/acpi/processor.h 2004-11-27 20:25:24.337644816 +0100 +++ linux/include/acpi/processor.h 2004-11-27 20:25:42.399898936 +0100 @@ -40,7 +40,7 @@ }; struct acpi_processor_power { - int state; + struct acpi_processor_cx *state; u32 bm_activity; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; };