@@ -17,6 +17,7 @@
#include <linux/pci.h>
#include <linux/of_pci.h>
#include <linux/initrd.h>
+#include <linux/smp.h>
#include <asm/irqdomain.h>
#include <asm/hpet.h>
@@ -128,7 +129,59 @@ static void __init dtb_setup_hpet(void)
#ifdef CONFIG_X86_LOCAL_APIC
#ifdef CONFIG_SMP
-static const char *dtb_supported_enable_methods[] __initconst = { };
+
+#ifdef CONFIG_X86_64
+
+#define WAKEUP_MAILBOX_SIZE 0x1000
+#define WAKEUP_MAILBOX_ALIGN 0x1000
+
+static int __init dtb_parse_wakeup_mailbox(const char *enable_method)
+{
+ struct device_node *node;
+ struct resource res;
+ int ret = 0;
+
+ if (strcmp(enable_method, "intel,wakeup-mailbox"))
+ return -EINVAL;
+
+ node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox");
+ if (!node)
+ return -ENODEV;
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret)
+ goto done;
+
+ /* The mailbox is a 4KB-aligned region.*/
+ if (res.start & (WAKEUP_MAILBOX_ALIGN - 1)) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* The mailbox has a size of 4KB. */
+ if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ /* Not supported when the mailbox is used. */
+ cpu_hotplug_disable_offlining();
+
+ setup_mp_wakeup_mailbox(res.start);
+done:
+ of_node_put(node);
+ return ret;
+}
+#else /* !CONFIG_X86_64 */
+static inline int dtb_parse_wakeup_mailbox(const char *enable_method)
+{
+ return -ENOTSUPP;
+}
+#endif /* CONFIG_X86_64 */
+
+static const char *dtb_supported_enable_methods[] __initconst = {
+ "intel,wakeup-mailbox"
+};
static bool __init dtb_enable_method_is_valid(const char *enable_method_a,
const char *enable_method_b)
@@ -155,7 +208,7 @@ static int __init dtb_configure_enable_method(const char *enable_method)
if (!enable_method || IS_ERR(enable_method))
return 0;
- return -ENOTSUPP;
+ return dtb_parse_wakeup_mailbox(enable_method);
}
#else /* !CONFIG_SMP */
static inline bool dtb_enable_method_is_valid(const char *enable_method_a,
The Wakeup Mailbox is a mechanism to boot secondary CPUs used on systems that do not want or cannot use the INIT + StartUp IPI messages. Add `intel,wakeup-mailbox` to the set of supported enable methods. Also add functionality to find and parse the parameters of the mailbox from the DeviceTree from the platform firmware. The operation and structure of the Wakeup Mailbox are described in the corresponding DeviceTree schema that accompanies the documentation of the Linux kernel. The Wakeup Mailbox is compatible with the Multiprocessor Wakeup Mailbox Structure described in the ACPI specification. Reuse the existing functionality to set the memory location of the mailbox and update the wakeup_secondary_cpu_64() APIC callback. do_boot_cpu() uses wakeup_secondary_cpu_64() when set. If a wakeup mailbox is found (enumerated via an ACPI table or a DeviceTree node) it will be used unconditionally. For cases in which this behavior is not desired, this APIC callback can be updated later during boot using platform-specific hooks. Originally-by: Yunhong Jiang <yunhong.jiang@linux.intel.com> Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> --- Changes since v2: - Added extra sanity checks when parsing the mailbox node. - Probe the mailbox using its `compatible` property - Setup the Wakeup Mailbox if the `enable-method` is found in the CPU nodes. - Cleaned up unneeded ifdeffery. - Clarified the mechanisms used to override the wakeup_secondary_64() callback to not use the mailbox when not desired. (Michael) - Edited the commit message for clarity. Changes since v1: - Disabled CPU offlining. - Modified dtb_parse_mp_wake() to return the address of the mailbox. --- arch/x86/kernel/devicetree.c | 57 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-)