From patchwork Wed Apr 24 17:28:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Pieralisi X-Patchwork-Id: 2485591 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 9ABA33FD85 for ; Wed, 24 Apr 2013 17:44:21 +0000 (UTC) Received: from merlin.infradead.org ([205.233.59.134]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV3eS-0007A1-BU; Wed, 24 Apr 2013 17:38:41 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV3XZ-0007VG-Nt; Wed, 24 Apr 2013 17:31:33 +0000 Received: from service87.mimecast.com ([91.220.42.44]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV3W9-0007Nm-AA for linux-arm-kernel@lists.infradead.org; Wed, 24 Apr 2013 17:30:08 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Wed, 24 Apr 2013 18:29:05 +0100 Received: from e102568-lin.cambridge.arm.com ([10.1.255.212]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 24 Apr 2013 18:29:04 +0100 From: Lorenzo Pieralisi To: linux-arm-kernel@lists.infradead.org, devicetree-discuss@lists.ozlabs.org Subject: [RFC PATCH v3 17/17] ARM: DT: kernel: DT cpus/cpu node bindings update Date: Wed, 24 Apr 2013 18:28:22 +0100 Message-Id: <1366824502-19729-18-git-send-email-lorenzo.pieralisi@arm.com> X-Mailer: git-send-email 1.7.12 In-Reply-To: <1366824502-19729-1-git-send-email-lorenzo.pieralisi@arm.com> References: <1366824502-19729-1-git-send-email-lorenzo.pieralisi@arm.com> X-OriginalArrivalTime: 24 Apr 2013 17:29:04.0653 (UTC) FILETIME=[37C993D0:01CE4111] X-MC-Unique: 113042418290505301 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130424_133005_628733_6AFE826D X-CRM114-Status: GOOD ( 18.12 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [91.220.42.44 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Nicolas Pitre , Jon Medhurst , Dave Martin , Andrew Lunn , Tony Lindgren , Benjamin Herrenschmidt , Linus Walleij , Will Deacon , Viresh Kumar , Kukjin Kim , Mark Rutland , Lennert Buytenhek , Lorenzo Pieralisi , Russell King , Magnus Damm , Catalin Marinas , Grant Likely , David Brown , Jean-Christophe Plagniol-Villard , Dinh Nguyen , Arnd Bergmann , Stephen Warren , Sekhar Nori , Rob Herring , Simon Horman , Barry Song , Vincent Guittot , Vinayak Kale , Amit Kucheria , Nicolas Ferre , Olof Johansson , Maxime Ripard , Shawn Guo X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 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 DT cpu map parsing code must be made compliant with the latest cpus/cpu nodes bindings updates, hence this patch updates the arm_dt_init_cpu_maps() function with checks and additional parsing rules. Uniprocessor systems predating v7 do not parse the cpus node at all since the reg property is meaningless on those systems. Device trees for 64-bit systems can be taken as device tree input also for 64-bit CPUs running in 32-bit mode. The code checks that the reg entries are zeroed as required in the respective fields and detects automatically the cpus node #address-cells value so that device tree written for 64-bit ARM platforms (that can have cpus node #address-cells == 2) can still be taken as input. The correct device tree entries are to be set up by the boot loader, kernel code just checks that device tree entries in the cpus node are as expected for a 32-bit CPU (reg[63:24] == 0). cpu node entries with invalid reg property or containing duplicates are ignored and the device tree parsing is not stopped anymore when such entries are encountered, the device tree cpu node entry is just skipped. A device tree with cpu nodes missing the boot CPU MPIDR is considered a hard error and the kernel flags this up as a bug to force firmware updates. Signed-off-by: Lorenzo Pieralisi --- arch/arm/kernel/devtree.c | 78 +++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index f149217..b667217 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -81,48 +82,64 @@ void __init arm_dt_init_cpu_maps(void) static u32 tmp_map[NR_CPUS] __initdata = { [0 ... NR_CPUS-1] = UINT_MAX }; struct device_node *cpu, *cpus; - u32 i, j, cpuidx = 1; + u32 i, j, ac, cpuidx = 1; u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; - + int len; bool bootcpu_valid = false; + cpus = of_find_node_by_path("/cpus"); - if (!cpus) + if (!cpus || ((cpu_architecture() < CPU_ARCH_ARMv7) && !is_smp())) return; + if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac))) + ac = of_n_addr_cells(cpus); + for_each_child_of_node(cpus, cpu) { - u32 hwid; + u64 hwid64; + u32 hwid32; + const __be32 *prop; pr_debug(" * %s...\n", cpu->full_name); /* - * A device tree containing CPU nodes with missing "reg" - * properties is considered invalid to build the - * cpu_logical_map. + * A CPU node with missing or wrong "reg" property is + * considered invalid to build a cpu_logical_map entry. */ - if (of_property_read_u32(cpu, "reg", &hwid)) { - pr_debug(" * %s missing reg property\n", - cpu->full_name); - return; + prop = of_get_property(cpu, "reg", &len); + if (!prop || len < (ac * sizeof(*prop))) { + WARN(1, " * %s node missing/wrong reg property, skipped\n", + cpu->full_name); + goto next; } - /* - * 8 MSBs must be set to 0 in the DT since the reg property - * defines the MPIDR[23:0]. + * Always read reg as u64 value. + * For dts with #address-cells == 1 hwid64[63:32] + * will be set to 0 by of_read_number. + * Toss away the top 32 bits and store value in hwid32. + */ + hwid32 = hwid64 = of_read_number(prop, ac); + /* + * hwid64[63:24] must be always be 0 since the reg + * property defines the MPIDR[23:0] bits regardless + * of the cpus node #address-cells value. */ - if (hwid & ~MPIDR_HWID_BITMASK) - return; + if (hwid64 & ~MPIDR_HWID_BITMASK) { + WARN(1, " * %s node reg[63:24] must be 0 on 32-bit dts, got %#016llx, skipped\n", + cpu->full_name, hwid64); + goto next; + } /* * Duplicate MPIDRs are a recipe for disaster. * Scan all initialized entries and check for - * duplicates. If any is found just bail out. + * duplicates. If any is found just ignore the CPU. * temp values were initialized to UINT_MAX * to avoid matching valid MPIDR[23:0] values. */ for (j = 0; j < cpuidx; j++) - if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg " - "properties in the DT\n")) - return; + if (WARN(tmp_map[j] == hwid32, " * %s node duplicate cpu reg property, skipped\n", + cpu->full_name)) + goto next; /* * Build a stashed array of MPIDR values. Numbering scheme @@ -133,26 +150,27 @@ void __init arm_dt_init_cpu_maps(void) * logical map built from DT is validated and can be used * to override the map created in smp_setup_processor_id(). */ - if (hwid == mpidr) { + if (hwid32 == mpidr) { i = 0; bootcpu_valid = true; } else { i = cpuidx++; } - if (WARN(cpuidx > nr_cpu_ids, "DT /cpu %u nodes greater than " - "max cores %u, capping them\n", - cpuidx, nr_cpu_ids)) { + if (WARN_ONCE(cpuidx > nr_cpu_ids, "DT cpu %u nodes greater than max cores %u, capping them\n", + cpuidx, nr_cpu_ids)) { cpuidx = nr_cpu_ids; - break; + goto next; } - tmp_map[i] = hwid; + tmp_map[i] = hwid32; +next: ; } - - if (WARN(!bootcpu_valid, "DT missing boot CPU MPIDR[23:0], " - "fall back to default cpu_logical_map\n")) - return; + /* + * A DT missing the boot CPU MPIDR is a really bad omen + * Flag it up as such and force firmware/dtb updates + */ + BUG_ON(!bootcpu_valid); /* * Since the boot CPU node contains proper data, and all nodes have