diff options
| -rw-r--r-- | arch/x86/include/asm/emergency-restart.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/reboot.c | 34 | ||||
| -rw-r--r-- | arch/x86/pci/direct.c | 4 | ||||
| -rw-r--r-- | arch/x86/pci/pci.h | 1 |
4 files changed, 34 insertions, 9 deletions
diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h index 94826cf87455..cc70c1c78ca4 100644 --- a/arch/x86/include/asm/emergency-restart.h +++ b/arch/x86/include/asm/emergency-restart.h | |||
| @@ -8,7 +8,9 @@ enum reboot_type { | |||
| 8 | BOOT_BIOS = 'b', | 8 | BOOT_BIOS = 'b', |
| 9 | #endif | 9 | #endif |
| 10 | BOOT_ACPI = 'a', | 10 | BOOT_ACPI = 'a', |
| 11 | BOOT_EFI = 'e' | 11 | BOOT_EFI = 'e', |
| 12 | BOOT_CF9 = 'p', | ||
| 13 | BOOT_CF9_COND = 'q', | ||
| 12 | }; | 14 | }; |
| 13 | 15 | ||
| 14 | extern enum reboot_type reboot_type; | 16 | extern enum reboot_type reboot_type; |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 34f8d37ae3c5..ddc93891cdcd 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
| @@ -29,14 +29,17 @@ EXPORT_SYMBOL(pm_power_off); | |||
| 29 | 29 | ||
| 30 | static const struct desc_ptr no_idt = {}; | 30 | static const struct desc_ptr no_idt = {}; |
| 31 | static int reboot_mode; | 31 | static int reboot_mode; |
| 32 | enum reboot_type reboot_type = BOOT_KBD; | 32 | enum reboot_type reboot_type = BOOT_CF9_COND; |
| 33 | int reboot_force; | 33 | int reboot_force; |
| 34 | 34 | ||
| 35 | #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) | 35 | #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) |
| 36 | static int reboot_cpu = -1; | 36 | static int reboot_cpu = -1; |
| 37 | #endif | 37 | #endif |
| 38 | 38 | ||
| 39 | /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | 39 | /* This is set by the PCI code if either type 1 or type 2 PCI is detected */ |
| 40 | bool port_cf9_safe = false; | ||
| 41 | |||
| 42 | /* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci] | ||
| 40 | warm Don't set the cold reboot flag | 43 | warm Don't set the cold reboot flag |
| 41 | cold Set the cold reboot flag | 44 | cold Set the cold reboot flag |
| 42 | bios Reboot by jumping through the BIOS (only for X86_32) | 45 | bios Reboot by jumping through the BIOS (only for X86_32) |
| @@ -45,6 +48,7 @@ static int reboot_cpu = -1; | |||
| 45 | kbd Use the keyboard controller. cold reset (default) | 48 | kbd Use the keyboard controller. cold reset (default) |
| 46 | acpi Use the RESET_REG in the FADT | 49 | acpi Use the RESET_REG in the FADT |
| 47 | efi Use efi reset_system runtime service | 50 | efi Use efi reset_system runtime service |
| 51 | pci Use the so-called "PCI reset register", CF9 | ||
| 48 | force Avoid anything that could hang. | 52 | force Avoid anything that could hang. |
| 49 | */ | 53 | */ |
| 50 | static int __init reboot_setup(char *str) | 54 | static int __init reboot_setup(char *str) |
| @@ -79,6 +83,7 @@ static int __init reboot_setup(char *str) | |||
| 79 | case 'k': | 83 | case 'k': |
| 80 | case 't': | 84 | case 't': |
| 81 | case 'e': | 85 | case 'e': |
| 86 | case 'p': | ||
| 82 | reboot_type = *str; | 87 | reboot_type = *str; |
| 83 | break; | 88 | break; |
| 84 | 89 | ||
| @@ -379,28 +384,43 @@ static void native_machine_emergency_restart(void) | |||
| 379 | load_idt(&no_idt); | 384 | load_idt(&no_idt); |
| 380 | __asm__ __volatile__("int3"); | 385 | __asm__ __volatile__("int3"); |
| 381 | 386 | ||
| 382 | reboot_type = BOOT_KBD; | 387 | reboot_type = BOOT_CF9_COND; |
| 383 | break; | 388 | break; |
| 384 | 389 | ||
| 385 | #ifdef CONFIG_X86_32 | 390 | #ifdef CONFIG_X86_32 |
| 386 | case BOOT_BIOS: | 391 | case BOOT_BIOS: |
| 387 | machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); | 392 | machine_real_restart(jump_to_bios, sizeof(jump_to_bios)); |
| 388 | 393 | ||
| 389 | reboot_type = BOOT_KBD; | 394 | reboot_type = BOOT_CF9_COND; |
| 390 | break; | 395 | break; |
| 391 | #endif | 396 | #endif |
| 392 | 397 | ||
| 393 | case BOOT_ACPI: | 398 | case BOOT_ACPI: |
| 394 | acpi_reboot(); | 399 | acpi_reboot(); |
| 395 | reboot_type = BOOT_KBD; | 400 | reboot_type = BOOT_CF9_COND; |
| 396 | break; | 401 | break; |
| 397 | 402 | ||
| 398 | |||
| 399 | case BOOT_EFI: | 403 | case BOOT_EFI: |
| 400 | if (efi_enabled) | 404 | if (efi_enabled) |
| 401 | efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, | 405 | efi.reset_system(reboot_mode ? |
| 406 | EFI_RESET_WARM : | ||
| 407 | EFI_RESET_COLD, | ||
| 402 | EFI_SUCCESS, 0, NULL); | 408 | EFI_SUCCESS, 0, NULL); |
| 409 | reboot_type = BOOT_CF9_COND; | ||
| 410 | break; | ||
| 411 | |||
| 412 | case BOOT_CF9: | ||
| 413 | port_cf9_safe = true; | ||
| 414 | /* fall through */ | ||
| 403 | 415 | ||
| 416 | case BOOT_CF9_COND: | ||
| 417 | if (port_cf9_safe) { | ||
| 418 | u8 cf9 = inb(0xcf9) & ~6; | ||
| 419 | outb(cf9|2, 0xcf9); /* Request hard reset */ | ||
| 420 | udelay(50); | ||
| 421 | outb(cf9|6, 0xcf9); /* Actually do the reset */ | ||
| 422 | udelay(50); | ||
| 423 | } | ||
| 404 | reboot_type = BOOT_KBD; | 424 | reboot_type = BOOT_KBD; |
| 405 | break; | 425 | break; |
| 406 | } | 426 | } |
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c index 9915293500fb..9a5af6c8fbe9 100644 --- a/arch/x86/pci/direct.c +++ b/arch/x86/pci/direct.c | |||
| @@ -173,7 +173,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus, | |||
| 173 | 173 | ||
| 174 | #undef PCI_CONF2_ADDRESS | 174 | #undef PCI_CONF2_ADDRESS |
| 175 | 175 | ||
| 176 | static struct pci_raw_ops pci_direct_conf2 = { | 176 | struct pci_raw_ops pci_direct_conf2 = { |
| 177 | .read = pci_conf2_read, | 177 | .read = pci_conf2_read, |
| 178 | .write = pci_conf2_write, | 178 | .write = pci_conf2_write, |
| 179 | }; | 179 | }; |
| @@ -289,6 +289,7 @@ int __init pci_direct_probe(void) | |||
| 289 | 289 | ||
| 290 | if (pci_check_type1()) { | 290 | if (pci_check_type1()) { |
| 291 | raw_pci_ops = &pci_direct_conf1; | 291 | raw_pci_ops = &pci_direct_conf1; |
| 292 | port_cf9_safe = true; | ||
| 292 | return 1; | 293 | return 1; |
| 293 | } | 294 | } |
| 294 | release_resource(region); | 295 | release_resource(region); |
| @@ -305,6 +306,7 @@ int __init pci_direct_probe(void) | |||
| 305 | 306 | ||
| 306 | if (pci_check_type2()) { | 307 | if (pci_check_type2()) { |
| 307 | raw_pci_ops = &pci_direct_conf2; | 308 | raw_pci_ops = &pci_direct_conf2; |
| 309 | port_cf9_safe = true; | ||
| 308 | return 2; | 310 | return 2; |
| 309 | } | 311 | } |
| 310 | 312 | ||
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 15b9cf6be729..1959018aac02 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h | |||
| @@ -96,6 +96,7 @@ extern struct pci_raw_ops *raw_pci_ops; | |||
| 96 | extern struct pci_raw_ops *raw_pci_ext_ops; | 96 | extern struct pci_raw_ops *raw_pci_ext_ops; |
| 97 | 97 | ||
| 98 | extern struct pci_raw_ops pci_direct_conf1; | 98 | extern struct pci_raw_ops pci_direct_conf1; |
| 99 | extern bool port_cf9_safe; | ||
| 99 | 100 | ||
| 100 | /* arch_initcall level */ | 101 | /* arch_initcall level */ |
| 101 | extern int pci_direct_probe(void); | 102 | extern int pci_direct_probe(void); |
