summaryrefslogtreecommitdiffstats
path: root/acpi_reboot.patch
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2010-12-16 15:37:54 -0500
committerMatthew Garrett <mjg@redhat.com>2010-12-16 15:37:54 -0500
commit0988eed04e7237fdab524413e9c69bbf54cdf400 (patch)
treee1569adddcfa427a763349941643e770d67f6341 /acpi_reboot.patch
parentc6781123e5747130611e984918856076200f6395 (diff)
downloadkernel-0988eed04e7237fdab524413e9c69bbf54cdf400.tar.gz
kernel-0988eed04e7237fdab524413e9c69bbf54cdf400.tar.xz
kernel-0988eed04e7237fdab524413e9c69bbf54cdf400.zip
- applesmc_update.patch: Make the driver more generic. Should help Apples.
- apple_backlight.patch: Make sure that this loads on all hardware. - efifb_update.patch: Fixes for the 11 inch Macbook Air - acpi_reboot.patch: Should make reboot work better on most hardware - efi_default_physical.patch: Some machines dislike EFI virtual mode
Diffstat (limited to 'acpi_reboot.patch')
-rw-r--r--acpi_reboot.patch102
1 files changed, 102 insertions, 0 deletions
diff --git a/acpi_reboot.patch b/acpi_reboot.patch
new file mode 100644
index 000000000..e9fdef35b
--- /dev/null
+++ b/acpi_reboot.patch
@@ -0,0 +1,102 @@
+Improve our reboot handling for compatibility with Windows. Upstream in .38?
+
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index c495aa8..c770e66 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -34,7 +34,7 @@ EXPORT_SYMBOL(pm_power_off);
+
+ static const struct desc_ptr no_idt = {};
+ static int reboot_mode;
+-enum reboot_type reboot_type = BOOT_KBD;
++enum reboot_type reboot_type = BOOT_ACPI;
+ int reboot_force;
+
+ #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
+@@ -538,9 +538,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
+ {
+ }
+
++/*
++ * Windows does the following on reboot:
++ * 1) If the FADT has the ACPI reboot register flag set, try it
++ * 2) If still alive, write to the keyboard controller
++ * 3) If still alive, write to the ACPI reboot register again
++ * 4) Ig still alive, write to the keyboard controller again
++ *
++ * If the machine is still alive at this stage, it gives up. We default to
++ * following the same pattern, except that if we're still alive after (4) we'll
++ * try to force a triple fault and then cycle between hitting the keyboard
++ * controller and doing that
++ */
+ static void native_machine_emergency_restart(void)
+ {
+ int i;
++ int attempt = 0;
++ int orig_reboot_type = reboot_type;
+
+ if (reboot_emergency)
+ emergency_vmx_disable_all();
+@@ -562,6 +576,13 @@ static void native_machine_emergency_restart(void)
+ outb(0xfe, 0x64); /* pulse reset low */
+ udelay(50);
+ }
++ if (attempt == 0 && orig_reboot_type == BOOT_ACPI) {
++ attempt = 1;
++ reboot_type = BOOT_ACPI;
++ } else {
++ reboot_type = BOOT_TRIPLE;
++ }
++ break;
+
+ case BOOT_TRIPLE:
+ load_idt(&no_idt);
+diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
+index 50cc3be..c6a4e63 100644
+--- a/drivers/acpi/acpica/hwxface.c
++++ b/drivers/acpi/acpica/hwxface.c
+@@ -82,12 +82,11 @@ acpi_status acpi_reset(void)
+ /*
+ * For I/O space, write directly to the OSL. This bypasses the port
+ * validation mechanism, which may block a valid write to the reset
+- * register.
++ * register. Spec section 4.7.3.6 requires register width to be 8.
+ */
+ status =
+ acpi_os_write_port((acpi_io_address) reset_reg->address,
+- acpi_gbl_FADT.reset_value,
+- reset_reg->bit_width);
++ acpi_gbl_FADT.reset_value, 8)
+ } else {
+ /* Write the reset value to the reset register */
+
+diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
+index 93f9114..a6c77e8b 100644
+--- a/drivers/acpi/reboot.c
++++ b/drivers/acpi/reboot.c
+@@ -15,9 +15,15 @@ void acpi_reboot(void)
+
+ rr = &acpi_gbl_FADT.reset_register;
+
+- /* Is the reset register supported? */
+- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+- rr->bit_width != 8 || rr->bit_offset != 0)
++ /* ACPI reset register was only introduced with v2 of the FADT */
++
++ if (acpi_gbl_FADT.header.revision < 2)
++ return;
++
++ /* Is the reset register supported? The spec says we should be
++ * checking the bit width and bit offset, but Windows ignores
++ * these fields */
++ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
+ return;
+
+ reset_value = acpi_gbl_FADT.reset_value;
+@@ -45,6 +51,4 @@ void acpi_reboot(void)
+ acpi_reset();
+ break;
+ }
+- /* Wait ten seconds */
+- acpi_os_stall(10000000);
+ }