Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/rusty/linux...
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / reboot.c
index 508e982dd072404d14005a90a8c007682e10fb89..27349f92a6d79078bca5bce37cfcf23f490ab84a 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/efi.h>
+#include <linux/dmi.h>
+#include <linux/tboot.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -17,7 +19,6 @@
 #include <asm/cpu.h>
 
 #ifdef CONFIG_X86_32
-# include <linux/dmi.h>
 # include <linux/ctype.h>
 # include <linux/mc146818rtc.h>
 #else
@@ -404,6 +405,46 @@ EXPORT_SYMBOL(machine_real_restart);
 
 #endif /* CONFIG_X86_32 */
 
+/*
+ * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
+ */
+static int __init set_pci_reboot(const struct dmi_system_id *d)
+{
+       if (reboot_type != BOOT_CF9) {
+               reboot_type = BOOT_CF9;
+               printk(KERN_INFO "%s series board detected. "
+                      "Selecting PCI-method for reboots.\n", d->ident);
+       }
+       return 0;
+}
+
+static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
+       {       /* Handle problems with rebooting on Apple MacBook5 */
+               .callback = set_pci_reboot,
+               .ident = "Apple MacBook5",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
+               },
+       },
+       {       /* Handle problems with rebooting on Apple MacBookPro5 */
+               .callback = set_pci_reboot,
+               .ident = "Apple MacBookPro5",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
+               },
+       },
+       { }
+};
+
+static int __init pci_reboot_init(void)
+{
+       dmi_check_system(pci_reboot_dmi_table);
+       return 0;
+}
+core_initcall(pci_reboot_init);
+
 static inline void kb_wait(void)
 {
        int i;
@@ -468,6 +509,8 @@ static void native_machine_emergency_restart(void)
        if (reboot_emergency)
                emergency_vmx_disable_all();
 
+       tboot_shutdown(TB_SHUTDOWN_REBOOT);
+
        /* Tell the BIOS if we want cold or warm reboot */
        *((unsigned short *)__va(0x472)) = reboot_mode;
 
@@ -594,6 +637,8 @@ static void native_machine_halt(void)
        /* stop other cpus and apics */
        machine_shutdown();
 
+       tboot_shutdown(TB_SHUTDOWN_HALT);
+
        /* stop this cpu */
        stop_this_cpu(NULL);
 }
@@ -605,6 +650,8 @@ static void native_machine_power_off(void)
                        machine_shutdown();
                pm_power_off();
        }
+       /* a fallback in case there is no PM info available */
+       tboot_shutdown(TB_SHUTDOWN_HALT);
 }
 
 struct machine_ops machine_ops = {