From patchwork Mon Aug 4 15:28:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 4671011 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 922C99F375 for ; Mon, 4 Aug 2014 15:32:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BC04A2012F for ; Mon, 4 Aug 2014 15:32:43 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9484820127 for ; Mon, 4 Aug 2014 15:32:42 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XEKDi-0000LH-NT; Mon, 04 Aug 2014 15:30:42 +0000 Received: from mail-pa0-f49.google.com ([209.85.220.49]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XEKDb-0008L1-Ew for linux-arm-kernel@lists.infradead.org; Mon, 04 Aug 2014 15:30:36 +0000 Received: by mail-pa0-f49.google.com with SMTP id hz1so10182703pad.22 for ; Mon, 04 Aug 2014 08:30:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RmGGQEJWmuEfoHCG7Vokq1wjBu0aa474BANL4UHoAaA=; b=DgyGAOGrs8WoQE3vfG9wYCdZ8hTuV816XEbQfN71ad+ubKzeJmnVgXFG0zdAo9Wumd eSlZPhIAr7QIIPj3WzxghXIWt6241iyw7p5iGoeVUbr6B8Vc6AGrPJm1tA1r7sXuHa0a EhxKbVuoomBH299+lZZIwT5bwW/7ueZY8Kzip4EG8saUvfOkMN5+XQ6pxd3zI9q+2KWY Q/CPXTAWhi5clXPiLvb5rXQ27HDNv/pS60tiG0hoz6QndhQgOCu7fYA8fSfu675x3LJf QV/wSs1d1xiSkxUi7MLdpFoEYjzdzSTrbQ0Wkw+F9GjBDVJ2x/VIugprvlz1Wg0Nh2UF IFxQ== X-Gm-Message-State: ALoCoQngfBLdXI6toZ+RZUQsqrwHfy46fScozjBeOvc6bYWAcwpexWg8kUFFrQv3H29o7Hxtdhbx X-Received: by 10.69.17.230 with SMTP id gh6mr24767195pbd.0.1407166213877; Mon, 04 Aug 2014 08:30:13 -0700 (PDT) Received: from localhost ([39.182.20.233]) by mx.google.com with ESMTPSA id ib5sm17808158pbb.55.2014.08.04.08.30.05 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 04 Aug 2014 08:30:12 -0700 (PDT) From: Hanjun Guo To: Catalin Marinas , "Rafael J. Wysocki" , Mark Rutland Subject: [PATCH v2 08/18] ARM64 / ACPI: Get the enable method for SMP initialization in ACPI way Date: Mon, 4 Aug 2014 23:28:15 +0800 Message-Id: <1407166105-17675-9-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1407166105-17675-1-git-send-email-hanjun.guo@linaro.org> References: <1407166105-17675-1-git-send-email-hanjun.guo@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140804_083035_562476_9036A1F0 X-CRM114-Status: GOOD ( 22.56 ) X-Spam-Score: -0.7 (/) Cc: linaro-acpi@lists.linaro.org, Liviu Dudau , Lv Zheng , Rob Herring , Lorenzo Pieralisi , Daniel Lezcano , Robert Moore , linux-acpi@vger.kernel.org, Grant Likely , Charles.Garcia-Tobin@arm.com, Robert Richter , Jason Cooper , Arnd Bergmann , Marc Zyngier , Will Deacon , Tomasz Nowicki , Mark Brown , Bjorn Helgaas , linux-arm-kernel@lists.infradead.org, Graeme Gregory , Randy Dunlap , linux-kernel@vger.kernel.org, Hanjun Guo , Sudeep Holla , Olof Johansson X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ACPI 5.1 only has two explicit methods to boot up SMP, PSCI and Parking protocol, but the Parking protocol is only suitable 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. Signed-off-by: Hanjun Guo Signed-off-by: Tomasz Nowicki --- arch/arm64/include/asm/acpi.h | 21 ++++++++++++++ arch/arm64/include/asm/smp.h | 3 +- arch/arm64/kernel/acpi.c | 9 ++++++ arch/arm64/kernel/cpu_ops.c | 62 ++++++++++++++++++++++++++++++++++++----- arch/arm64/kernel/smp.c | 27 +++++++++++++++++- 5 files changed, 113 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index e877967..022f4ad 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -14,6 +14,27 @@ /* 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); + #define acpi_strict 1 /* No out-of-spec workarounds on ARM64 */ extern int acpi_disabled; extern int acpi_noirq; diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index a498f2c..282932c2 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -39,7 +39,8 @@ extern void show_ipi_list(struct seq_file *p, int prec); extern void handle_IPI(int ipinr, struct pt_regs *regs); /* - * Setup the set of possible CPUs (via set_cpu_possible) + * Discover the set of possible CPUs and determine their + * SMP operations. */ extern void smp_init_cpus(void); diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 9e07d99..8a54b4e 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -170,6 +170,15 @@ static int __init acpi_parse_madt_gic_cpu_interface_entries(void) return 0; } +/* 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; +} + 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 . */ -#include -#include #include #include #include +#include + +#include +#include 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; + } +} +#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; + } + + dn = of_get_cpu_node(0, NULL); if (!dn) { pr_err("Failed to find device node for boot cpu\n"); return; diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 8f1d37c..e21bbc9 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -315,7 +315,7 @@ static void (*smp_cross_call)(const struct cpumask *, unsigned int); * cpu logical map array containing MPIDR values related to logical * cpus. Assumes that cpu_logical_map(0) has already been initialized. */ -void __init smp_init_cpus(void) +static void __init of_smp_init_cpus(void) { struct device_node *dn = NULL; unsigned int i, cpu = 1; @@ -418,6 +418,31 @@ next: set_cpu_possible(i, true); } +/* + * In ACPI mode, the cpu possible map was enumerated before SMP + * initialization when MADT table was parsed, so we can get the + * possible map here to initialize CPUs. + */ +static void __init acpi_smp_init_cpus(void) +{ + int cpu; + + for_each_possible_cpu(cpu) { + if (cpu_read_ops(NULL, cpu) != 0) + continue; + + cpu_ops[cpu]->cpu_init(NULL, cpu); + } +} + +void __init smp_init_cpus(void) +{ + if (acpi_disabled) + of_smp_init_cpus(); + else + acpi_smp_init_cpus(); +} + void __init smp_prepare_cpus(unsigned int max_cpus) { int err;