Per the request of Hanjun, and due to my involvement in the discussion regarding adding /chosen node properties to the EFI stub<->kernel interface, here is a patch that implements the policy that we discussed, i.e., to enable ACPI explicitly if acpi=force is set, and to enable it implicitly if the device tree has no nodes at depth 1 other than the /chosen node (in which case the device tree is considered to be empty). We did not discuss the acpi=off case, but this patch changes its handling from 'enable ACPI implicitly if the EFI stub generated the DTB' (which is what Hanjun implemented) to 'ACPI is disabled period' (which is arguably more appropriate)
This patch replaces the following two patches ARM64 / ACPI: Introduce early_param for "acpi" and pass acpi=force to enable ACPI dt / chosen: Add linux,uefi-stub-generated-dtb property
-------------->8------------------ This implements the following policy to decide whether ACPI should be used to boot the system: - acpi=off: ACPI will not be used to boot the system, even if there is no alternative available (e.g., device tree is empty) - acpi=force: only ACPI will be used to boot the system; if that fails, there will be no fallback to alternative methods (such as device tree) - otherwise, ACPI will be used as a fallback if the device tree turns out to lack a platform description; the heuristic to decide this is whether /chosen is the only node present at depth 1
CC: Catalin Marinas catalin.marinas@arm.com CC: Will Deacon will.deacon@arm.com CC: Rafael J. Wysocki rjw@rjwysocki.net Signed-off-by: Al Stone al.stone@linaro.org Signed-off-by: Graeme Gregory graeme.gregory@linaro.org Signed-off-by: Hanjun Guo hanjun.guo@linaro.org Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- Documentation/kernel-parameters.txt | 3 ++- arch/arm64/kernel/acpi.c | 54 +++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 176d4fe4f076..d6a952ec4433 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -165,7 +165,7 @@ multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30 bytes respectively. Such letter suffixes can also be entirely omitted.
- acpi= [HW,ACPI,X86] + acpi= [HW,ACPI,X86,ARM64] Advanced Configuration and Power Interface Format: { force | off | strict | noirq | rsdt } force -- enable ACPI if default was off @@ -175,6 +175,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. strictly ACPI specification compliant. rsdt -- prefer RSDT over (default) XSDT copy_dsdt -- copy DSDT to memory + For ARM64, ONLY "acpi=off" or "acpi=force" are available
See also Documentation/power/runtime_pm.txt, pci=noacpi
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 7f67c011261b..732ad0d075f5 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -20,15 +20,49 @@ #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/memblock.h> +#include <linux/of_fdt.h> #include <linux/smp.h>
-int acpi_noirq; /* skip ACPI IRQ initialization */ -int acpi_disabled; +int acpi_noirq = 1; /* skip ACPI IRQ initialization */ +int acpi_disabled = 1; EXPORT_SYMBOL(acpi_disabled);
-int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ +int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled);
+static bool __initdata param_acpi_off; +static bool __initdata param_acpi_force; + +static int __init parse_acpi(char *arg) +{ + if (!arg) + return -EINVAL; + + /* "acpi=off" disables both ACPI table parsing and interpreter */ + if (strcmp(arg, "off") == 0) + param_acpi_off = true; + else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ + param_acpi_force = true; + else + return -EINVAL; /* Core will print when we return error */ + + return 0; +} +early_param("acpi", parse_acpi); + +static int __init dt_scan_depth1_nodes(unsigned long node, + const char *uname, int depth, + void *data) +{ + /* + * Return 1 as soon as we encounter a node at depth 1 that is + * not the /chosen node. + */ + if (depth == 1 && (strcmp(uname, "chosen") != 0)) + return 1; + return 0; +} + /* * __acpi_map_table() will be called before page_init(), so early_ioremap() * or early_memremap() should be called here to for ACPI table mapping. @@ -59,10 +93,20 @@ void __init __acpi_unmap_table(char *map, unsigned long size) */ void __init acpi_boot_table_init(void) { - /* If acpi_disabled, bail out */ - if (acpi_disabled) + /* + * Enable ACPI instead of device tree unless + * - ACPI has been disabled explicitly (acpi=off), or + * - the device tree is not empty (it has more than just a /chosen node) + * and ACPI has not been force enabled (acpi=force) + */ + if (param_acpi_off || + (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) return;
+ acpi_disabled = 0; + acpi_pci_disabled = 0; + acpi_noirq = 0; + /* Initialize the ACPI boot-time table parser. */ if (acpi_table_init()) disable_acpi();