Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[safe/jmp/linux-2.6] / drivers / acpi / processor_idle.c
index bbd066e..5939e7f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/acpi.h>
@@ -110,6 +111,14 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = {
          DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
          DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")},
         (void *)2},
+       { set_max_cstate, "Pavilion zv5000", {
+         DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+         DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")},
+        (void *)1},
+       { set_max_cstate, "Asus L8400B", {
+         DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+         DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")},
+        (void *)1},
        {},
 };
 
@@ -164,7 +173,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
                pr->power.timer_broadcast_on_state = state;
 }
 
-static void lapic_timer_propagate_broadcast(void *arg)
+static void __lapic_timer_propagate_broadcast(void *arg)
 {
        struct acpi_processor *pr = (struct acpi_processor *) arg;
        unsigned long reason;
@@ -175,6 +184,12 @@ static void lapic_timer_propagate_broadcast(void *arg)
        clockevents_notify(reason, &pr->id);
 }
 
+static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
+{
+       smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast,
+                                (void *)pr, 1);
+}
+
 /* Power(C) State timer broadcast control */
 static void lapic_timer_state_broadcast(struct acpi_processor *pr,
                                       struct acpi_processor_cx *cx,
@@ -299,6 +314,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
        pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency;
        pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency;
 
+       /*
+        * FADT specified C2 latency must be less than or equal to
+        * 100 microseconds.
+        */
+       if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                       "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency));
+               /* invalidate C2 */
+               pr->power.states[ACPI_STATE_C2].address = 0;
+       }
+
+       /*
+        * FADT supplied C3 latency must be less than or equal to
+        * 1000 microseconds.
+        */
+       if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                       "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency));
+               /* invalidate C3 */
+               pr->power.states[ACPI_STATE_C3].address = 0;
+       }
+
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "lvl2[0x%08x] lvl3[0x%08x]\n",
                          pr->power.states[ACPI_STATE_C2].address,
@@ -324,7 +361,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
 static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 {
        acpi_status status = 0;
-       acpi_integer count;
+       u64 count;
        int current_count;
        int i;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -488,33 +525,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
        return status;
 }
 
-static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
-{
-
-       if (!cx->address)
-               return;
-
-       /*
-        * C2 latency must be less than or equal to 100
-        * microseconds.
-        */
-       else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "latency too large [%d]\n", cx->latency));
-               return;
-       }
-
-       /*
-        * Otherwise we've met all of our C2 requirements.
-        * Normalize the C2 latency to expidite policy
-        */
-       cx->valid = 1;
-
-       cx->latency_ticks = cx->latency;
-
-       return;
-}
-
 static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
                                           struct acpi_processor_cx *cx)
 {
@@ -526,16 +536,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
                return;
 
        /*
-        * C3 latency must be less than or equal to 1000
-        * microseconds.
-        */
-       else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "latency too large [%d]\n", cx->latency));
-               return;
-       }
-
-       /*
         * PIIX4 Erratum #18: We don't support C3 when Type-F (fast)
         * DMA transfers are used by any ISA device to avoid livelock.
         * Note that we could disable Type-F DMA (as recommended by
@@ -623,7 +623,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                        break;
 
                case ACPI_STATE_C2:
-                       acpi_processor_power_verify_c2(cx);
+                       if (!cx->address)
+                               break;
+                       cx->valid = 1; 
+                       cx->latency_ticks = cx->latency; /* Normalize latency */
                        break;
 
                case ACPI_STATE_C3:
@@ -638,8 +641,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                working++;
        }
 
-       smp_call_function_single(pr->id, lapic_timer_propagate_broadcast,
-                                pr, 1);
+       lapic_timer_propagate_broadcast(pr);
 
        return (working);
 }
@@ -879,12 +881,14 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
                return(acpi_idle_enter_c1(dev, state));
 
        local_irq_disable();
-       current_thread_info()->status &= ~TS_POLLING;
-       /*
-        * TS_POLLING-cleared state must be visible before we test
-        * NEED_RESCHED:
-        */
-       smp_mb();
+       if (cx->entry_method != ACPI_CSTATE_FFH) {
+               current_thread_info()->status &= ~TS_POLLING;
+               /*
+                * TS_POLLING-cleared state must be visible before we test
+                * NEED_RESCHED:
+                */
+               smp_mb();
+       }
 
        if (unlikely(need_resched())) {
                current_thread_info()->status |= TS_POLLING;
@@ -964,12 +968,14 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        }
 
        local_irq_disable();
-       current_thread_info()->status &= ~TS_POLLING;
-       /*
-        * TS_POLLING-cleared state must be visible before we test
-        * NEED_RESCHED:
-        */
-       smp_mb();
+       if (cx->entry_method != ACPI_CSTATE_FFH) {
+               current_thread_info()->status &= ~TS_POLLING;
+               /*
+                * TS_POLLING-cleared state must be visible before we test
+                * NEED_RESCHED:
+                */
+               smp_mb();
+       }
 
        if (unlikely(need_resched())) {
                current_thread_info()->status |= TS_POLLING;