[v4,21/21] arm/acpi: Add acpi parameter to enable/disable acpi
diff mbox

Message ID 1453540813-15764-22-git-send-email-zhaoshenglong@huawei.com
State New, archived
Headers show

Commit Message

Shannon Zhao Jan. 23, 2016, 9:20 a.m. UTC
From: Shannon Zhao <shannon.zhao@linaro.org>

Define new command line parameter "acpi" to enable/disable acpi.
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

Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
V4: be consistent with Linux
---
 xen/arch/arm/acpi/boot.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

Comments

Stefano Stabellini Feb. 2, 2016, 5:58 p.m. UTC | #1
On Sat, 23 Jan 2016, Shannon Zhao wrote:
> From: Shannon Zhao <shannon.zhao@linaro.org>
> 
> Define new command line parameter "acpi" to enable/disable acpi.
> 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
> 
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> ---
> V4: be consistent with Linux

Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>


>  xen/arch/arm/acpi/boot.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/xen/arch/arm/acpi/boot.c b/xen/arch/arm/acpi/boot.c
> index c9135f2..8eb6c37 100644
> --- a/xen/arch/arm/acpi/boot.c
> +++ b/xen/arch/arm/acpi/boot.c
> @@ -30,9 +30,11 @@
>  #include <xen/errno.h>
>  #include <acpi/actables.h>
>  #include <xen/mm.h>
> +#include <xen/device_tree.h>
>  
>  #include <asm/acpi.h>
>  #include <asm/smp.h>
> +#include <asm/setup.h>
>  
>  /* Processors with enabled flag and sane MPIDR */
>  static unsigned int enabled_cpus;
> @@ -182,6 +184,36 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
>      return -EINVAL;
>  }
>  
> +static bool_t __initdata param_acpi_off;
> +static bool_t __initdata param_acpi_force;
> +
> +static void __init parse_acpi_param(char *arg)
> +{
> +    if ( !arg )
> +        return;
> +
> +    /* Interpret the parameter for use within Xen. */
> +    if ( !parse_bool(arg) )
> +        param_acpi_off = true;
> +    else if ( !strcmp(arg, "force") ) /* force ACPI to be enabled */
> +        param_acpi_force = true;
> +}
> +custom_param("acpi", parse_acpi_param);
> +
> +static int __init dt_scan_depth1_nodes(const void *fdt, int node,
> +                                       const char *uname, int depth,
> +                                       u32 address_cells, u32 size_cells,
> +                                       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_boot_table_init() called from setup_arch(), always.
>   *      1. find RSDP and get its address, and then find XSDT
> @@ -198,6 +230,26 @@ int __init acpi_boot_table_init(void)
>  {
>      int error;
>  
> +    /*
> +     * 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
> +                             && device_tree_for_each_node(device_tree_flattened,
> +                                                   dt_scan_depth1_nodes, NULL)))
> +    {
> +        disable_acpi();
> +        return 0;
> +    }
> +
> +    /*
> +     * ACPI is disabled at this point. Enable it in order to parse
> +     * the ACPI tables.
> +     */
> +    enable_acpi();
> +
>      /* Initialize the ACPI boot-time table parser. */
>      error = acpi_table_init();
>      if ( error )
> -- 
> 2.0.4
> 
>

Patch
diff mbox

diff --git a/xen/arch/arm/acpi/boot.c b/xen/arch/arm/acpi/boot.c
index c9135f2..8eb6c37 100644
--- a/xen/arch/arm/acpi/boot.c
+++ b/xen/arch/arm/acpi/boot.c
@@ -30,9 +30,11 @@ 
 #include <xen/errno.h>
 #include <acpi/actables.h>
 #include <xen/mm.h>
+#include <xen/device_tree.h>
 
 #include <asm/acpi.h>
 #include <asm/smp.h>
+#include <asm/setup.h>
 
 /* Processors with enabled flag and sane MPIDR */
 static unsigned int enabled_cpus;
@@ -182,6 +184,36 @@  static int __init acpi_parse_fadt(struct acpi_table_header *table)
     return -EINVAL;
 }
 
+static bool_t __initdata param_acpi_off;
+static bool_t __initdata param_acpi_force;
+
+static void __init parse_acpi_param(char *arg)
+{
+    if ( !arg )
+        return;
+
+    /* Interpret the parameter for use within Xen. */
+    if ( !parse_bool(arg) )
+        param_acpi_off = true;
+    else if ( !strcmp(arg, "force") ) /* force ACPI to be enabled */
+        param_acpi_force = true;
+}
+custom_param("acpi", parse_acpi_param);
+
+static int __init dt_scan_depth1_nodes(const void *fdt, int node,
+                                       const char *uname, int depth,
+                                       u32 address_cells, u32 size_cells,
+                                       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_boot_table_init() called from setup_arch(), always.
  *      1. find RSDP and get its address, and then find XSDT
@@ -198,6 +230,26 @@  int __init acpi_boot_table_init(void)
 {
     int error;
 
+    /*
+     * 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
+                             && device_tree_for_each_node(device_tree_flattened,
+                                                   dt_scan_depth1_nodes, NULL)))
+    {
+        disable_acpi();
+        return 0;
+    }
+
+    /*
+     * ACPI is disabled at this point. Enable it in order to parse
+     * the ACPI tables.
+     */
+    enable_acpi();
+
     /* Initialize the ACPI boot-time table parser. */
     error = acpi_table_init();
     if ( error )