]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'suspend' into test
authorLen Brown <len.brown@intel.com>
Thu, 23 Oct 2008 03:28:46 +0000 (23:28 -0400)
committerLen Brown <len.brown@intel.com>
Thu, 23 Oct 2008 03:28:46 +0000 (23:28 -0400)
drivers/acpi/hardware/hwsleep.c
drivers/acpi/sleep/main.c

index dba3cfbe8cba9e3235970e7b972e7f54da24c4af..25dccdf179b9e4814ca52669f268f4409b34ce6b 100644 (file)
@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
                return_ACPI_STATUS(status);
        }
 
-       /* Set the vector */
+       /*
+        * According to the ACPI specification 2.0c and later, the 64-bit
+        * waking vector should be cleared and the 32-bit waking vector should
+        * be used, unless we want the wake-up code to be called by the BIOS in
+        * Protected Mode.  Some systems (for example HP dv5-1004nr) are known
+        * to fail to resume if the 64-bit vector is used.
+        */
+       if (facs->version >= 1)
+               facs->xfirmware_waking_vector = 0;
 
-       if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
-               /*
-                * ACPI 1.0 FACS or short table or optional X_ field is zero
-                */
-               facs->firmware_waking_vector = (u32) physical_address;
-       } else {
-               /*
-                * ACPI 2.0 FACS with valid X_ field
-                */
-               facs->xfirmware_waking_vector = physical_address;
-       }
+       facs->firmware_waking_vector = (u32)physical_address;
 
        return_ACPI_STATUS(AE_OK);
 }
@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
        }
 
        /* Get the vector */
-
-       if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
-               /*
-                * ACPI 1.0 FACS or short table or optional X_ field is zero
-                */
-               *physical_address =
-                   (acpi_physical_address) facs->firmware_waking_vector;
-       } else {
-               /*
-                * ACPI 2.0 FACS with valid X_ field
-                */
-               *physical_address =
-                   (acpi_physical_address) facs->xfirmware_waking_vector;
-       }
+       *physical_address = (acpi_physical_address)facs->firmware_waking_vector;
 
        return_ACPI_STATUS(AE_OK);
 }
@@ -627,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
        }
        /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
 
+       /*
+        * Some BIOSes assume that WAK_STS will be cleared on resume and use
+        * it to determine whether the system is rebooting or resuming. Clear
+        * it for compatibility.
+        */
+       acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
+
        acpi_gbl_system_awake_and_running = TRUE;
 
        /* Enable power button */
index 4c21480b58207c0132af414bb3c361204c3e0806..cc344d4252c94d4da031480a4f8ee88448b75458 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dmi.h>
 #include <linux/device.h>
 #include <linux/suspend.h>
+#include <linux/reboot.h>
 
 #include <asm/io.h>
 
 u8 sleep_states[ACPI_S_STATE_COUNT];
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
 
+static void acpi_sleep_tts_switch(u32 acpi_state)
+{
+       union acpi_object in_arg = { ACPI_TYPE_INTEGER };
+       struct acpi_object_list arg_list = { 1, &in_arg };
+       acpi_status status = AE_OK;
+
+       in_arg.integer.value = acpi_state;
+       status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL);
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+               /*
+                * OS can't evaluate the _TTS object correctly. Some warning
+                * message will be printed. But it won't break anything.
+                */
+               printk(KERN_NOTICE "Failure in evaluating _TTS object\n");
+       }
+}
+
+static int tts_notify_reboot(struct notifier_block *this,
+                       unsigned long code, void *x)
+{
+       acpi_sleep_tts_switch(ACPI_STATE_S5);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block tts_notifier = {
+       .notifier_call  = tts_notify_reboot,
+       .next           = NULL,
+       .priority       = 0,
+};
+
 static int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
@@ -130,6 +161,7 @@ static void acpi_pm_end(void)
         * failing transition to a sleep state.
         */
        acpi_target_sleep_state = ACPI_STATE_S0;
+       acpi_sleep_tts_switch(acpi_target_sleep_state);
 }
 #endif /* CONFIG_ACPI_SLEEP */
 
@@ -154,6 +186,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
 
        if (sleep_states[acpi_state]) {
                acpi_target_sleep_state = acpi_state;
+               acpi_sleep_tts_switch(acpi_target_sleep_state);
        } else {
                printk(KERN_ERR "ACPI does not support this state: %d\n",
                        pm_state);
@@ -199,6 +232,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
                break;
        }
 
+       /* If ACPI is not enabled by the BIOS, we need to enable it here. */
+       acpi_enable();
        /* Reprogram control registers and execute _BFS */
        acpi_leave_sleep_state_prep(acpi_state);
 
@@ -295,6 +330,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
                },
        },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "HP xw4600 Workstation",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
@@ -312,6 +355,7 @@ void __init acpi_no_s4_hw_signature(void)
 static int acpi_hibernation_begin(void)
 {
        acpi_target_sleep_state = ACPI_STATE_S4;
+       acpi_sleep_tts_switch(acpi_target_sleep_state);
        return 0;
 }
 
@@ -375,7 +419,15 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
  */
 static int acpi_hibernation_begin_old(void)
 {
-       int error = acpi_sleep_prepare(ACPI_STATE_S4);
+       int error;
+       /*
+        * The _TTS object should always be evaluated before the _PTS object.
+        * When the old_suspended_ordering is true, the _PTS object is
+        * evaluated in the acpi_sleep_prepare.
+        */
+       acpi_sleep_tts_switch(ACPI_STATE_S4);
+
+       error = acpi_sleep_prepare(ACPI_STATE_S4);
 
        if (!error)
                acpi_target_sleep_state = ACPI_STATE_S4;
@@ -595,5 +647,10 @@ int __init acpi_sleep_init(void)
                pm_power_off = acpi_power_off;
        }
        printk(")\n");
+       /*
+        * Register the tts_notifier to reboot notifier list so that the _TTS
+        * object can also be evaluated when the system enters S5.
+        */
+       register_reboot_notifier(&tts_notifier);
        return 0;
 }