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

Reply via email to