Thread (63 messages) 63 messages, 9 authors, 2014-08-21

[PATCH v2 08/18] ARM64 / ACPI: Get the enable method for SMP initialization in ACPI way

From: Hanjun Guo <hidden>
Date: 2014-08-19 11:28:20
Also in: linux-acpi, lkml

On 2014-8-19 2:34, Sudeep Holla wrote:
On 04/08/14 16:28, Hanjun Guo wrote:
[...]
quoted
  /* Basic configuration for ACPI */
  #ifdef    CONFIG_ACPI
+/*
+ * ACPI 5.1 only has two explicit methods to
+ * boot up SMP, PSCI and Parking protocol,
+ * but the Parking protocol is only defined
+ * for ARMv7 now, so make PSCI as the only
+ * way for the SMP boot protocol before some
+ * updates for the ACPI spec or the Parking
+ * protocol spec.
+ *
+ * This enum is intend to make the boot method
+ * scalable when above updates are happended,
+ * which NOT means to support all of them.
+ */
+enum acpi_smp_boot_protocol {
+    ACPI_SMP_BOOT_PSCI,
+    ACPI_SMP_BOOT_PARKING_PROTOCOL,
+    ACPI_SMP_BOOT_PROTOCOL_MAX
+};
+
+enum acpi_smp_boot_protocol smp_boot_protocol(void);
+
[...]
quoted
+/* Protocol to bring up secondary CPUs */
+enum acpi_smp_boot_protocol smp_boot_protocol(void)
+{
+    if (acpi_psci_present())
+        return ACPI_SMP_BOOT_PSCI;
+    else
+        return ACPI_SMP_BOOT_PARKING_PROTOCOL;
+}
+
Which do you need this here ? Can't you use acpi_psci_present directly
in acpi_get_cpu_boot_method ?
My intent was to make the code scalable if we introduce another (or more)
boot protocol in ACPI, does it make sense to you?
quoted
  static int __init acpi_parse_fadt(struct acpi_table_header *table)
  {
      struct acpi_table_fadt *fadt = (struct acpi_table_fadt *)table;
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
index d62d12f..05bc314 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -16,11 +16,13 @@
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */

-#include <asm/cpu_ops.h>
-#include <asm/smp_plat.h>
  #include <linux/errno.h>
  #include <linux/of.h>
  #include <linux/string.h>
+#include <linux/acpi.h>
+
+#include <asm/cpu_ops.h>
+#include <asm/smp_plat.h>

  extern const struct cpu_operations smp_spin_table_ops;
  extern const struct cpu_operations cpu_psci_ops;
@@ -49,12 +51,44 @@ static const struct cpu_operations * __init
cpu_get_ops(const char *name)
      return NULL;
  }

+#ifdef CONFIG_ACPI
+/*
+ * Get a cpu's boot method in the ACPI way.
+ */
+static char * __init acpi_get_cpu_boot_method(void)
+{
+    /*
+     * For ACPI 5.1, only two kind of methods are provided,
+     * Parking protocol and PSCI, but Parking protocol is
+     * specified for ARMv7 only, so make PSCI as the only method
+     * for SMP initialization before the ACPI spec or Parking
+     * protocol spec is updated.
+     */
+    switch (smp_boot_protocol()) {
+    case ACPI_SMP_BOOT_PSCI:
+        return "psci";
+    case ACPI_SMP_BOOT_PARKING_PROTOCOL:
+    default:
+        return NULL;
+    }
Use acpi_psci_present as mentioned above.
quoted
+}
+#else
+static inline char * __init acpi_get_cpu_boot_method(void) { return NULL; }
+#endif
+
  /*
- * Read a cpu's enable method from the device tree and record it in cpu_ops.
+ * Read a cpu's enable method and record it in cpu_ops.
   */
  int __init cpu_read_ops(struct device_node *dn, int cpu)
  {
-    const char *enable_method = of_get_property(dn, "enable-method", NULL);
+    const char *enable_method;
+
+    if (!acpi_disabled) {
+        enable_method = acpi_get_cpu_boot_method();
+        goto get_ops;
+    }
+
+    enable_method = of_get_property(dn, "enable-method", NULL);
      if (!enable_method) {
          /*
           * The boot CPU may not have an enable method (e.g. when
@@ -66,10 +100,17 @@ int __init cpu_read_ops(struct device_node *dn, int cpu)
          return -ENOENT;
      }

+get_ops:
      cpu_ops[cpu] = cpu_get_ops(enable_method);
      if (!cpu_ops[cpu]) {
-        pr_warn("%s: unsupported enable-method property: %s\n",
-            dn->full_name, enable_method);
+        if (acpi_disabled) {
+            pr_warn("%s: unsupported enable-method property: %s\n",
+                dn->full_name, enable_method);
+        } else {
+            pr_warn("CPU %d: boot protocol unsupported or unknown\n",
+                cpu);
+        }
+
          return -EOPNOTSUPP;
      }
@@ -78,7 +119,14 @@ int __init cpu_read_ops(struct device_node *dn, int cpu)

  void __init cpu_read_bootcpu_ops(void)
  {
-    struct device_node *dn = of_get_cpu_node(0, NULL);
+    struct device_node *dn;
+
+    if (!acpi_disabled) {
+        cpu_read_ops(NULL, 0);
+        return;
+    }
+
Again not good to mix ACPI in DT functions forcing you to pass
device_node ptr as NULL, better to separate this. 
I separate them in the first version, and combine tham as Geoff suggested
for scalable reasons.
Once you gather all
this !acpi_disabled case, you can create appropriate abstractions to be
used in setup.c

E.g. here you check !acpi_disabled and pass NULL for DT node to
cpu_read_ops and hence again you check for !acpi_disabled in
cpu_read_ops. So you need first identify all these checks and put in one
place to understand well how you can refactor existing code to avoid
these multiple checks.
I will remove the multiple acpi_disabled checks and refactor the code.

Thanks
Hanjun
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help