diff options
author | Keir Fraser <keir@xen.org> | 2010-12-15 10:31:08 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-12-15 10:31:08 +0000 |
commit | 508a7e32395683585aa4e4c5cddb78c106c1dd66 (patch) | |
tree | f885d3e76b312d14e56fd5ae9d9a6eac69dd6f69 | |
parent | c0ba4702f351003bd1e7bd695751bcab0d8f71f2 (diff) | |
download | xen-508a7e32395683585aa4e4c5cddb78c106c1dd66.tar.gz xen-508a7e32395683585aa4e4c5cddb78c106c1dd66.tar.bz2 xen-508a7e32395683585aa4e4c5cddb78c106c1dd66.zip |
x86 acpi: Follow Windows behaviour more closely during reset.
This follows some changes proposed for upstream Linux:
1. Do not check the FADT reset register size/offset
2. Try ACPI poking twice during our reset attempt sequence
Hopefully this will help us reset reliably on a wider range of
platforms.
Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 22482:91e0556f4d46
xen-unstable date: Fri Dec 10 11:32:19 2010 +0000
x86: acpi: Fix reboot attempt sequence.
Signed-off-by: Keir Fraser <keir@xen.org>
xen-unstable changeset: 22483:901c118b363e
xen-unstable date: Fri Dec 10 16:40:05 2010 +0000
-rw-r--r-- | xen/arch/x86/shutdown.c | 21 | ||||
-rw-r--r-- | xen/drivers/acpi/reboot.c | 7 |
2 files changed, 20 insertions, 8 deletions
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c index 43a008849f..135e6ebc63 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -301,7 +301,8 @@ static void __machine_restart(void *pdelay) void machine_restart(unsigned int delay_millisecs) { - int i; + unsigned int i, attempt; + enum reboot_type orig_reboot_type = reboot_type; watchdog_disable(); console_start_sync(); @@ -336,7 +337,7 @@ void machine_restart(unsigned int delay_millisecs) /* Rebooting needs to touch the page at absolute address 0. */ *((unsigned short *)__va(0x472)) = reboot_mode; - for ( ; ; ) + for ( attempt = 0; ; attempt++ ) { switch ( reboot_type ) { @@ -349,19 +350,29 @@ void machine_restart(unsigned int delay_millisecs) outb(0xfe,0x64); /* pulse reset low */ udelay(50); } - /* fall through */ + /* + * If this platform supports ACPI reset, we follow a Windows-style + * reboot attempt sequence: + * ACPI -> KBD -> ACPI -> KBD + * After this we revert to our usual sequence: + * KBD -> TRIPLE -> KBD -> TRIPLE -> KBD -> ... + */ + reboot_type = (((attempt == 1) && (orig_reboot_type == BOOT_ACPI)) + ? BOOT_ACPI : BOOT_TRIPLE); + break; case BOOT_TRIPLE: asm volatile ( "lidt %0 ; int3" : "=m" (no_idt) ); + reboot_type = BOOT_KBD; break; case BOOT_BIOS: machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); + reboot_type = BOOT_KBD; break; case BOOT_ACPI: acpi_reboot(); + reboot_type = BOOT_KBD; break; } - - reboot_type = BOOT_KBD; } } diff --git a/xen/drivers/acpi/reboot.c b/xen/drivers/acpi/reboot.c index 69ea8afeea..744c500a76 100644 --- a/xen/drivers/acpi/reboot.c +++ b/xen/drivers/acpi/reboot.c @@ -10,9 +10,10 @@ 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)) + /* 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; |