|
@@ -114,8 +114,8 @@ EXPORT_SYMBOL(machine_real_restart);
|
|
*/
|
|
*/
|
|
static int __init set_pci_reboot(const struct dmi_system_id *d)
|
|
static int __init set_pci_reboot(const struct dmi_system_id *d)
|
|
{
|
|
{
|
|
- if (reboot_type != BOOT_CF9) {
|
|
|
|
- reboot_type = BOOT_CF9;
|
|
|
|
|
|
+ if (reboot_type != BOOT_CF9_FORCE) {
|
|
|
|
+ reboot_type = BOOT_CF9_FORCE;
|
|
pr_info("%s series board detected. Selecting %s-method for reboots.\n",
|
|
pr_info("%s series board detected. Selecting %s-method for reboots.\n",
|
|
d->ident, "PCI");
|
|
d->ident, "PCI");
|
|
}
|
|
}
|
|
@@ -458,20 +458,23 @@ void __attribute__((weak)) mach_reboot_fixups(void)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Windows compatible x86 hardware expects the following on reboot:
|
|
|
|
|
|
+ * To the best of our knowledge Windows compatible x86 hardware expects
|
|
|
|
+ * the following on reboot:
|
|
*
|
|
*
|
|
* 1) If the FADT has the ACPI reboot register flag set, try it
|
|
* 1) If the FADT has the ACPI reboot register flag set, try it
|
|
* 2) If still alive, write to the keyboard controller
|
|
* 2) If still alive, write to the keyboard controller
|
|
* 3) If still alive, write to the ACPI reboot register again
|
|
* 3) If still alive, write to the ACPI reboot register again
|
|
* 4) If still alive, write to the keyboard controller again
|
|
* 4) If still alive, write to the keyboard controller again
|
|
* 5) If still alive, call the EFI runtime service to reboot
|
|
* 5) If still alive, call the EFI runtime service to reboot
|
|
- * 6) If still alive, write to the PCI IO port 0xCF9 to reboot
|
|
|
|
- * 7) If still alive, inform BIOS to do a proper reboot
|
|
|
|
|
|
+ * 6) If no EFI runtime service, call the BIOS to do a reboot
|
|
*
|
|
*
|
|
- * 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 (7) we'll
|
|
|
|
- * try to force a triple fault and then cycle between hitting the keyboard
|
|
|
|
- * controller and doing that
|
|
|
|
|
|
+ * We default to following the same pattern. We also have
|
|
|
|
+ * two other reboot methods: 'triple fault' and 'PCI', which
|
|
|
|
+ * can be triggered via the reboot= kernel boot option or
|
|
|
|
+ * via quirks.
|
|
|
|
+ *
|
|
|
|
+ * This means that this function can never return, it can misbehave
|
|
|
|
+ * by not rebooting properly and hanging.
|
|
*/
|
|
*/
|
|
static void native_machine_emergency_restart(void)
|
|
static void native_machine_emergency_restart(void)
|
|
{
|
|
{
|
|
@@ -492,6 +495,11 @@ static void native_machine_emergency_restart(void)
|
|
for (;;) {
|
|
for (;;) {
|
|
/* Could also try the reset bit in the Hammer NB */
|
|
/* Could also try the reset bit in the Hammer NB */
|
|
switch (reboot_type) {
|
|
switch (reboot_type) {
|
|
|
|
+ case BOOT_ACPI:
|
|
|
|
+ acpi_reboot();
|
|
|
|
+ reboot_type = BOOT_KBD;
|
|
|
|
+ break;
|
|
|
|
+
|
|
case BOOT_KBD:
|
|
case BOOT_KBD:
|
|
mach_reboot_fixups(); /* For board specific fixups */
|
|
mach_reboot_fixups(); /* For board specific fixups */
|
|
|
|
|
|
@@ -509,43 +517,29 @@ static void native_machine_emergency_restart(void)
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
- case BOOT_TRIPLE:
|
|
|
|
- load_idt(&no_idt);
|
|
|
|
- __asm__ __volatile__("int3");
|
|
|
|
-
|
|
|
|
- /* We're probably dead after this, but... */
|
|
|
|
- reboot_type = BOOT_KBD;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case BOOT_BIOS:
|
|
|
|
- machine_real_restart(MRR_BIOS);
|
|
|
|
-
|
|
|
|
- /* We're probably dead after this, but... */
|
|
|
|
- reboot_type = BOOT_TRIPLE;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case BOOT_ACPI:
|
|
|
|
- acpi_reboot();
|
|
|
|
- reboot_type = BOOT_KBD;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
case BOOT_EFI:
|
|
case BOOT_EFI:
|
|
if (efi_enabled(EFI_RUNTIME_SERVICES))
|
|
if (efi_enabled(EFI_RUNTIME_SERVICES))
|
|
efi.reset_system(reboot_mode == REBOOT_WARM ?
|
|
efi.reset_system(reboot_mode == REBOOT_WARM ?
|
|
EFI_RESET_WARM :
|
|
EFI_RESET_WARM :
|
|
EFI_RESET_COLD,
|
|
EFI_RESET_COLD,
|
|
EFI_SUCCESS, 0, NULL);
|
|
EFI_SUCCESS, 0, NULL);
|
|
- reboot_type = BOOT_CF9_COND;
|
|
|
|
|
|
+ reboot_type = BOOT_BIOS;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case BOOT_BIOS:
|
|
|
|
+ machine_real_restart(MRR_BIOS);
|
|
|
|
+
|
|
|
|
+ /* We're probably dead after this, but... */
|
|
|
|
+ reboot_type = BOOT_CF9_SAFE;
|
|
break;
|
|
break;
|
|
|
|
|
|
- case BOOT_CF9:
|
|
|
|
|
|
+ case BOOT_CF9_FORCE:
|
|
port_cf9_safe = true;
|
|
port_cf9_safe = true;
|
|
/* Fall through */
|
|
/* Fall through */
|
|
|
|
|
|
- case BOOT_CF9_COND:
|
|
|
|
|
|
+ case BOOT_CF9_SAFE:
|
|
if (port_cf9_safe) {
|
|
if (port_cf9_safe) {
|
|
- u8 reboot_code = reboot_mode == REBOOT_WARM ?
|
|
|
|
- 0x06 : 0x0E;
|
|
|
|
|
|
+ u8 reboot_code = reboot_mode == REBOOT_WARM ? 0x06 : 0x0E;
|
|
u8 cf9 = inb(0xcf9) & ~reboot_code;
|
|
u8 cf9 = inb(0xcf9) & ~reboot_code;
|
|
outb(cf9|2, 0xcf9); /* Request hard reset */
|
|
outb(cf9|2, 0xcf9); /* Request hard reset */
|
|
udelay(50);
|
|
udelay(50);
|
|
@@ -553,7 +547,15 @@ static void native_machine_emergency_restart(void)
|
|
outb(cf9|reboot_code, 0xcf9);
|
|
outb(cf9|reboot_code, 0xcf9);
|
|
udelay(50);
|
|
udelay(50);
|
|
}
|
|
}
|
|
- reboot_type = BOOT_BIOS;
|
|
|
|
|
|
+ reboot_type = BOOT_TRIPLE;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case BOOT_TRIPLE:
|
|
|
|
+ load_idt(&no_idt);
|
|
|
|
+ __asm__ __volatile__("int3");
|
|
|
|
+
|
|
|
|
+ /* We're probably dead after this, but... */
|
|
|
|
+ reboot_type = BOOT_KBD;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|