From patchwork Mon Aug 4 15:28:13 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 4670961 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 29B0BC0338 for ; Mon, 4 Aug 2014 15:32:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0D0AC2013D for ; Mon, 4 Aug 2014 15:32:26 +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 E65202012F for ; Mon, 4 Aug 2014 15:32:24 +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 1XEKDN-0008Pd-MP; Mon, 04 Aug 2014 15:30:21 +0000 Received: from mail-pa0-f42.google.com ([209.85.220.42]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XEKDE-00071Z-1W for linux-arm-kernel@lists.infradead.org; Mon, 04 Aug 2014 15:30:13 +0000 Received: by mail-pa0-f42.google.com with SMTP id lf10so10235069pab.29 for ; Mon, 04 Aug 2014 08:29:50 -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=KPM8SvIrmKJDZp0hPhpOrO+RW5gd0xcuG9QlvHq+8cU=; b=FSO6E1EVAOV0nJ+/e/HdvMGvzAiGy6HGXOX6u8tIFSCWF8L0L6rf+2jDq/T0i2SIvj vRX8MTDsW7lXK7Y8KV1Cdre3NKBJtesI9YgKiSZmTOm3rRi6Mhrhi27MUP95qObia+03 MZV75L7gHtfVWBbb4AkTdiQwVFN6zR+nRloYjLiJzgP+kXdLlZXSGwW+USM1aPjSJtSK Kd0ogShottYZ7kZh6K5NXZKp/6xrH6Ukx3huMrltorK1usxu6dK3S+U0785OdP5ss3AC cScQtCgU/dRQLRtw3Ehd6ZXeskIoVTV9Xj8aqrM1Wqh2pd6aQxtVX7n/N+/UVF1fwZ1B v6jg== X-Gm-Message-State: ALoCoQlf9k8TKRjpG+MQI85SQ8tlu1LXkBFo95CNf3ya+g+lfrP0Q/2NIi3bMrCb1wepDHo+Ys+4 X-Received: by 10.68.167.133 with SMTP id zo5mr24289056pbb.21.1407166190897; Mon, 04 Aug 2014 08:29:50 -0700 (PDT) Received: from localhost ([39.182.20.233]) by mx.google.com with ESMTPSA id t3sm27214803pdf.54.2014.08.04.08.29.43 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 04 Aug 2014 08:29:50 -0700 (PDT) From: Hanjun Guo To: Catalin Marinas , "Rafael J. Wysocki" , Mark Rutland Subject: [PATCH v2 06/18] ARM64 / ACPI: Parse MADT to map logical cpu to MPIDR and get cpu_possible/present_map Date: Mon, 4 Aug 2014 23:28:13 +0800 Message-Id: <1407166105-17675-7-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_083012_163786_4FEA9960 X-CRM114-Status: GOOD ( 23.40 ) 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 MADT contains the information for MPIDR which is essential for SMP initialization, parse the GIC cpu interface structures to get the MPIDR value and map it to cpu_logical_map(), and add enabled cpu with valid MPIDR into cpu_possible_map and cpu_present_map. Signed-off-by: Hanjun Guo Signed-off-by: Tomasz Nowicki --- arch/arm64/include/asm/acpi.h | 2 + arch/arm64/kernel/acpi.c | 129 ++++++++++++++++++++++++++++++++++++++++- arch/arm64/kernel/smp.c | 10 +++- 3 files changed, 138 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 6e04868..e877967 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -64,6 +64,8 @@ static inline void arch_fix_phys_package_id(int num, u32 slot) { } extern int (*acpi_suspend_lowlevel)(void); #define acpi_wakeup_address 0 +#define MAX_GIC_CPU_INTERFACE 65535 + #endif /* CONFIG_ACPI */ #endif /*_ASM_ACPI_H*/ diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 69a315d..9e07d99 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -22,6 +22,9 @@ #include #include +#include +#include + int acpi_noirq; /* skip ACPI IRQ initialization */ int acpi_disabled; EXPORT_SYMBOL(acpi_disabled); @@ -29,6 +32,8 @@ EXPORT_SYMBOL(acpi_disabled); int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); +static int enabled_cpus; /* Processors (GICC) with enabled flag in MADT */ + /* * __acpi_map_table() will be called before page_init(), so early_ioremap() * or early_memremap() should be called here to for ACPI table mapping. @@ -49,6 +54,122 @@ void __init __acpi_unmap_table(char *map, unsigned long size) early_memunmap(map, size); } +/** + * acpi_register_gic_cpu_interface - register a gic cpu interface and + * generates a logical cpu number + * @mpidr: CPU's hardware id to register, MPIDR represented in MADT + * @enabled: this cpu is enabled or not + * + * Returns the logical cpu number which maps to the gic cpu interface + */ +static int acpi_register_gic_cpu_interface(u64 mpidr, u8 enabled) +{ + int cpu; + + if (mpidr == INVALID_HWID) { + pr_info("Skip invalid cpu hardware ID\n"); + return -EINVAL; + } + + total_cpus++; + if (!enabled) + return -EINVAL; + + if (enabled_cpus >= NR_CPUS) { + pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n", + NR_CPUS, total_cpus, mpidr); + return -EINVAL; + } + + /* If it is the first CPU, no need to check duplicate MPIDRs */ + if (!enabled_cpus) + goto skip_mpidr_check; + + /* + * Duplicate MPIDRs are a recipe for disaster. Scan + * all initialized entries and check for + * duplicates. If any is found just ignore the CPU. + */ + for_each_present_cpu(cpu) { + if (cpu_logical_map(cpu) == mpidr) { + pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n", + mpidr); + return -EINVAL; + } + } + +skip_mpidr_check: + enabled_cpus++; + + /* allocate a logical cpu id for the new comer */ + if (cpu_logical_map(0) == mpidr) { + /* + * boot_cpu_init() already hold bit 0 in cpu_present_mask + * for BSP, no need to allocate again. + */ + cpu = 0; + } else { + cpu = cpumask_next_zero(-1, cpu_present_mask); + } + + /* map the logical cpu id to cpu MPIDR */ + cpu_logical_map(cpu) = mpidr; + + set_cpu_possible(cpu, true); + set_cpu_present(cpu, true); + + return cpu; +} + +static int __init +acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_generic_interrupt *processor; + + processor = (struct acpi_madt_generic_interrupt *)header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + acpi_register_gic_cpu_interface(processor->arm_mpidr, + processor->flags & ACPI_MADT_ENABLED); + + return 0; +} + +/* + * Parse GIC cpu interface related entries in MADT + * returns 0 on success, < 0 on error + */ +static int __init acpi_parse_madt_gic_cpu_interface_entries(void) +{ + int count; + + /* + * do a partial walk of MADT to determine how many CPUs + * we have including disabled CPUs, and get information + * we need for SMP init + */ + count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, + acpi_parse_gic_cpu_interface, MAX_GIC_CPU_INTERFACE); + + if (!count) { + pr_err("No GIC CPU interface entries present\n"); + return -ENODEV; + } else if (count < 0) { + pr_err("Error parsing GIC CPU interface entry\n"); + return count; + } + + /* Make boot-up look pretty */ + pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus); + + return 0; +} + static int __init acpi_parse_fadt(struct acpi_table_header *table) { struct acpi_table_fadt *fadt = (struct acpi_table_fadt *)table; @@ -99,8 +220,12 @@ int __init acpi_boot_init(void) return -ENODEV; err = acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt); - if (err) - pr_err("Can't find FADT\n"); + if (err) { + pr_err("Can't find FADT or error happened during parsing FADT\n"); + return err; + } + + err = acpi_parse_madt_gic_cpu_interface_entries(); return err; } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 40f38f4..8f1d37c 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -458,7 +459,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (err) continue; - set_cpu_present(cpu, true); + /* + * In ACPI mode, cpu_present_map was initialised when + * MADT table was parsed which before this function + * is called. + */ + if (acpi_disabled) + set_cpu_present(cpu, true); + max_cpus--; } }