diff options
author | Matthew Garrett <mjg@redhat.com> | 2010-12-16 15:37:54 -0500 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-12-16 15:37:54 -0500 |
commit | 0988eed04e7237fdab524413e9c69bbf54cdf400 (patch) | |
tree | e1569adddcfa427a763349941643e770d67f6341 /acpi_reboot.patch | |
parent | c6781123e5747130611e984918856076200f6395 (diff) | |
download | kernel-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.patch | 102 |
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); + } |