Newer laptops with AMD Turion X2 and AMD Athlon X2 mobile processors (which are C1E capable) are overheating and have very degraded battery life due to bugs in /usr/src/linux/drivers/acpi/processor_idle.c (not properly implemented C1 support). C1E replaces C2 and C3 states, so BIOS usually doesn't have definitions for _CST and PBLK in FADT - it is valid according to ACPI specification.
Here is MS info about PPM in Vista: http://download.microsoft.com/download/0/0/b/00bba048-35e6-4e5b-a3dc-36da83cbb0d1/ProcPowerMgmt.docx Below is patch which fixes C1 visibility, but doesn't increase battery life to Vista level. --- cut here -- --- kernels/linux-2.6.27-rc8/drivers/acpi/processor_idle.c 2008-09-30 00:24:02.000000000 +0200 +++ linux/drivers/acpi/processor_idle.c 2008-10-06 00:24:19.000000000 +0200 @@ -501,7 +501,7 @@ * ------ * Invoke the current Cx state to put the processor to sleep. */ - if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { + if (cx->type >= ACPI_STATE_C1) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we @@ -523,12 +523,17 @@ * Use the appropriate idle routine, the one that would * be used without acpi C-states. */ + + t1 = jiffies; + if (pm_idle_save) { pm_idle_save(); /* enables IRQs */ } else { acpi_safe_halt(); local_irq_enable(); } + + t2 = jiffies; /* * TBD: Can't get time duration while in C1, as resumes @@ -538,8 +543,7 @@ * Note: the TSC better not stop in C1, sched_clock() will * skew otherwise. */ - sleep_ticks = 0xFFFFFFFF; - + sleep_ticks = ticks_elapsed(t1, t2); break; case ACPI_STATE_C2: @@ -642,12 +646,13 @@ return; } cx->usage++; - if ((cx->type != ACPI_STATE_C1) && (sleep_ticks > 0)) + if (cx->type != ACPI_STATE_C1 && sleep_ticks > 0) cx->time += sleep_ticks; next_state = pr->power.state; #ifdef CONFIG_HOTPLUG_CPU + /* Don't do promotion/demotion */ if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) && !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) { @@ -811,8 +816,11 @@ if (!pr) return -EINVAL; + /* Newer dual-core CPUs use C1E instead of C2 and C3 and + * usually do not have _CST definitions or PBLK entries. + * ACPI specification allows for that so return zero here */ if (!pr->pblk) - return -ENODEV; + return 0; /* if info is obtained from pblk/fadt, type equals state */ pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; @@ -852,6 +860,11 @@ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; + snprintf(pr->power.states[ACPI_STATE_C1].desc, ACPI_CX_DESC_LEN, "ACPI HLT"); + if (!pr->power.states[ACPI_STATE_C1].latency) + pr->power.states[ACPI_STATE_C1].latency = 1; + if (!pr->power.states[ACPI_STATE_C1].power) + pr->power.states[ACPI_STATE_C1].power = 1000; } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; @@ -1191,12 +1204,11 @@ memset(pr->power.states, 0, sizeof(pr->power.states)); result = acpi_processor_get_power_info_cst(pr); - if (result == -ENODEV) - result = acpi_processor_get_power_info_fadt(pr); - if (result) - return result; + result = acpi_processor_get_power_info_fadt(pr); + /* No valid _CST and FADT, but C1 must be supported, + * so here we go */ acpi_processor_get_power_info_default(pr); pr->power.count = acpi_processor_power_verify(pr); @@ -1216,13 +1228,13 @@ #endif /* - * if one state of type C2 or C3 is available, mark this + * if one state of type C1(e), C2 or C3 is available, mark this * CPU as being "idle manageable" */ for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { if (pr->power.states[i].valid) { pr->power.count = i; - if (pr->power.states[i].type >= ACPI_STATE_C2) + if (pr->power.states[i].type >= ACPI_STATE_C1) pr->flags.power = 1; } } @@ -1455,7 +1467,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_state *state) { - u32 t1, t2; + u32 t1, t2, elapsed; struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); @@ -1482,7 +1494,10 @@ local_irq_enable(); cx->usage++; - + elapsed = ticks_elapsed(t1, t2); + if (elapsed > 0) + cx->time += elapsed; + return ticks_elapsed_in_us(t1, t2); } -- cut here -- -- AMD turion does not have support for c states https://bugs.launchpad.net/bugs/188739 You received this bug notification because you are a member of Ubuntu Bugs, which is subscribed to Ubuntu. -- ubuntu-bugs mailing list ubuntu-bugs@lists.ubuntu.com https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs