diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index dd8748c45529..318acaecb5ca 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -125,6 +126,51 @@ static void __init dtb_setup_hpet(void) #endif } +#if defined(CONFIG_X86_64) && defined(CONFIG_SMP) + +#define WAKEUP_MAILBOX_SIZE 0x1000 +#define WAKEUP_MAILBOX_ALIGN 0x1000 + +/** dtb_wakeup_mailbox_setup() - Parse the wakeup mailbox from the device tree + * + * Look for the presence of a wakeup mailbox in the DeviceTree. The mailbox is + * expected to follow the structure and operation described in the Multiprocessor + * Wakeup Structure of the ACPI specification. + */ +static void __init dtb_wakeup_mailbox_setup(void) +{ + struct device_node *node; + struct resource res; + + node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox"); + if (!node) + return; + + if (of_address_to_resource(node, 0, &res)) + goto done; + + /* The mailbox is a 4KB-aligned region.*/ + if (res.start & (WAKEUP_MAILBOX_ALIGN - 1)) + goto done; + + /* The mailbox has a size of 4KB. */ + if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE) + goto done; + + /* Not supported when the mailbox is used. */ + cpu_hotplug_disable_offlining(); + + acpi_setup_mp_wakeup_mailbox(res.start); +done: + of_node_put(node); +} +#else /* !CONFIG_X86_64 || !CONFIG_SMP */ +static inline int dtb_wakeup_mailbox_setup(void) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_X86_64 && CONFIG_SMP */ + #ifdef CONFIG_X86_LOCAL_APIC static void __init dtb_cpu_setup(void) @@ -287,6 +333,7 @@ static void __init x86_dtb_parse_smp_config(void) dtb_setup_hpet(); dtb_apic_setup(); + dtb_wakeup_mailbox_setup(); } void __init x86_flattree_get_config(void)