From patchwork Tue Feb 2 10:09:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ganapatrao Kulkarni X-Patchwork-Id: 8187851 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9F1F1BEEE5 for ; Tue, 2 Feb 2016 10:11:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 78E3A202DD for ; Tue, 2 Feb 2016 10:11:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 18DDB202EB for ; Tue, 2 Feb 2016 10:11:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754616AbcBBKLG (ORCPT ); Tue, 2 Feb 2016 05:11:06 -0500 Received: from mail-bn1bon0085.outbound.protection.outlook.com ([157.56.111.85]:6243 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754476AbcBBKK5 (ORCPT ); Tue, 2 Feb 2016 05:10:57 -0500 Authentication-Results: lists.infradead.org; dkim=none (message not signed) header.d=none; lists.infradead.org; dmarc=none action=none header.from=caviumnetworks.com; Received: from mypc.cavium.com.com (111.93.218.67) by CY1PR0701MB1696.namprd07.prod.outlook.com (10.163.20.30) with Microsoft SMTP Server (TLS) id 15.1.396.15; Tue, 2 Feb 2016 10:10:42 +0000 From: Ganapatrao Kulkarni To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , CC: Subject: [PATCH v10 3/8] dt, numa: adding numa dt binding implementation. Date: Tue, 2 Feb 2016 15:39:18 +0530 Message-ID: <1454407763-1017-4-git-send-email-gkulkarni@caviumnetworks.com> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1454407763-1017-1-git-send-email-gkulkarni@caviumnetworks.com> References: <1454407763-1017-1-git-send-email-gkulkarni@caviumnetworks.com> MIME-Version: 1.0 X-Originating-IP: [111.93.218.67] X-ClientProxiedBy: BM1PR01CA0067.INDPRD01.PROD.OUTLOOK.COM (25.163.199.39) To CY1PR0701MB1696.namprd07.prod.outlook.com (25.163.20.30) X-Microsoft-Exchange-Diagnostics: 1; CY1PR0701MB1696; 2:/pI0eiZDuFZGHVbrYFYnU6W9Z6asACVoWKCW1CDkX1d5hSeziuoBMVVZndm0cnbQ0MqOQbOtSyxwpFPJ6zfZITsAtWRQdMgUdElWZkhmrovbVOurNV6BWK+noK+HlUW1TAWOnhvPjUGDWLWaPDEdIA==; 3:oySyBkrGRDBF/foCtDXtfXvScOJSRxpEIZbnlXGr1EcLvDs+8R6rvyxx0yf0hmyYauUpMtmQ3oAY42w2tVAZlaLvmxIpoRBE+pFoFyy81aSIZaEBqsofzkS8VnDFBasC; 25:6tcIHt+s6vN0tHfS1Jn2rj+U/wH8rOHcdyozusXWe1ByRLDRM/T5Ci4BToz5elr85SoqIJtf+6XFysHgQMcmIiR/QeeaijaaS1m+g7pCtOjnMAa14U/vtol3SNfGlYTE3MJGrazoSl8L55fiRot7Ca92M5bvOATTvlVhcdrN2LfzFl19ZJB3sTpWkVVJqIQ32OFgN3d+OlN9RTgZUWPDTaiCIJQ4/agV9Zgc167/GFgdpRhLeT8pLMLG941/Nk8U X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR0701MB1696; X-MS-Office365-Filtering-Correlation-Id: 84c28e78-7f15-4898-7a1d-08d32bb9231a X-Microsoft-Exchange-Diagnostics: 1; CY1PR0701MB1696; 20:T+L0On8oQP3bkaSHE2ovzd4fqoC9uRKqWEvCGZEHT+aAGgusoqDhBH2PJEO8zsuR2qZaTaJ7DV0kSzmDy+6ZOfeEYs4Aqt0b+WkdNSR+B43pLHz5psWVEqSs29U5BnzoQu40GhOQsV/M+9YjGNxLmtMHQern9lGkr93OsleMV9t0mTiHMbLB+dNNvObf6xDNWLLDGWXzHG7pTwqkTXifuuYb6B3fWJKkuMwcrcSxs111LAM0+NTAiQWzHz6Eb57OlH/4JtJDV+hTWsWc5K4fTuDeXfNDkJ4txgrbWzQfTw/1D5hr0RyYUAYs9hjiXfUv7vq/KHB+wNmO6+3IZZiybpUky/fPSykOyNnT4eDGrM/h90SXO3rlkQVUW3CHFVEJJqbZ8Qey7rgq7LaBqEzhCytxk1W8727zqBNijkS3HCbjiELb79b1luRm7O5hXnNMg0C6A6TVcpAd8Y5PYBED5MukI0Slsq26B9lzexi4DK+xmKo0faX67fEOm40FmkCD7J6nMKzUfwJaCs1cDaXOFcP9wHWGF9qrmnU4LxC6h2iTHdSECXmyIS8HS/9PBzw6bY8UuO+9AfpCmGuux+8/2p03qThggUp7bJg/Psqmnvw= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046); SRVR:CY1PR0701MB1696; BCL:0; PCL:0; RULEID:; SRVR:CY1PR0701MB1696; X-Microsoft-Exchange-Diagnostics: 1; CY1PR0701MB1696; 4:NtU+qSGRnxjP8/XblyhujECzBfz/FD8AsBIVFdD6/SjIsLNknbFp/SlRORW68TA9i+0sFjs9enkrFx42Au5iu+xXhk3xEzNrYlTcCPvKtiVP6m453Satpqo/LR1fvQQulD1gAkqcnStznbBNRlclAvxxYMsSpgADFFJsjR/Lf23tunBfbXeXR002IXdWVrTfOTL3U59VQzVq3aPyQNatla/FPH+vcXN5aooXJlcH+3uaCw8dCLMJKFS6lvRBH1NFtFo+JFUy0KGw4Wu/E2lIzqmvShpoYXGSVkeouSFg/G3EUROMKUYvgfgA+8/XX/aUukC1TCO6J2nr2Nc6jFNhIwB1T9HAI4V9p6Jay11sKmV2sVObkbLhv6Slj7BYRioE X-Forefront-PRVS: 084080FC15 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(87976001)(229853001)(2950100001)(47776003)(189998001)(66066001)(76176999)(42186005)(50226001)(19580405001)(77096005)(5001770100001)(50986999)(15975445007)(4001450100002)(5004730100002)(92566002)(36756003)(586003)(19580395003)(40100003)(5008740100001)(5009440100003)(6116002)(1096002)(3846002)(3470700001)(5003940100001)(2906002)(50466002)(4326007)(33646002)(2441003)(122386002)(48376002)(2201001)(7099028)(921003)(1121003)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR0701MB1696; H:mypc.cavium.com.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR0701MB1696; 23:XonPDXMM9l7mKG0LuawgQcHTzPjuZSL54AO1dn2?= =?us-ascii?Q?sdnifM4ThRPc45qG/bhsWJ9ZWj7TO1F5lZVYjaDh1rM1v9MpuO18VOjGQp/B?= =?us-ascii?Q?La4qpRrq8RLz+rjIakTp9C0x25zRV1ENPF8d1/7q9UbGh9+5iGQzTKPNvPHl?= =?us-ascii?Q?PFVhN7F0g7ph1zr6tlDZR4AUNlhQBg5GQDuOzTnEHT6Ivv+c5JneLcWQwwtX?= =?us-ascii?Q?wHqo5Yb/xDEgy/Ge1yUEj54phnFHUj39UUEzByJF2C2otpQ8yrWu3O5P0Ym3?= =?us-ascii?Q?S97DgaPhCXSoYn4RVa/wQ3HjxCfJ65bt+jON0meqbEeU8sH7BGfh4geUCU/Q?= =?us-ascii?Q?lWO9tVdwkCozfaMUsiMY5VIQkBujh7TEygjvlAsNsu7s7FCmKms+EtJSXAFi?= =?us-ascii?Q?RPZayPEva2gsBhmmSAfGf5nT8YEhyBzI0DEef3vwGrf/EBYVm5MicPoGmx+c?= =?us-ascii?Q?JLOqaSldnyPR4Bhccytq4SIx9xsBeGSycK4+2FyQJPEVDk7FyfqS0mZkygiY?= =?us-ascii?Q?Nf5AIWgvnJbfjUZaojgIAOFx3gOxexLegODMOkxUCsThOs39yeQkGdZ3NntK?= =?us-ascii?Q?8fs5B0YIgeHdEvRtT+YHxxSDJQRxdd5MMShx2+gQZ+NRIRoGhzMUUMfUZn2c?= =?us-ascii?Q?VSNQ7F4hiXqhvrNAVzfJWZTYQlVcKV0Q0ivUOLFU91YZewyxecngjU562dGb?= =?us-ascii?Q?6ob5YpXH2AlbK8xHy+FiSXRf9ZqpRq6CUObCxFbz6KVwRmjfZXu3x6Rz84mC?= =?us-ascii?Q?j5moT85i/Nyyrghk1/fvmFnGvI3MdVILwRRdwU1Yo4RTvE9BiK4D7IoVh82Q?= =?us-ascii?Q?ywh/jX0VVEX1TrdnD4vJ5USn4mMepEzSArZFD2OB4rTkwgM5lx9NzWXTisq6?= =?us-ascii?Q?9tR4FiZg6S7hBV5YZM0x9x2FPNANQRjueuV0MMrCKtJDzb/H7eMMMGelh9LK?= =?us-ascii?Q?jYmjKc03BbcckYPJZ+QoIr2oBIsTzRN2L+Q0J5usIUJpDDvCMbbO8xeUwomK?= =?us-ascii?Q?zSMRjSaRyPkhLm0uSw060gqi/kOm2m3+vXhLjp69bw0q8BM5ofhlbSFKtoew?= =?us-ascii?Q?kmYgqEjb8qRopgUPx2NM5L7gjXZe5y3B9VDOoCDqDA6oHtgbzsw=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR0701MB1696; 5:mmvMBdVPiEY9RJU6oIVwA5NO8MMFa5zt77p0AO8vhG5PtC0SDx528dB03CZQTb3yuEH5/3HBpAlPXRooko492tHvReDX++MGSsFgVSdVJAB5K3wKMuXy/bcvnJRLvyKGkFNOczt68XscQDAaj1euSQ==; 24:k4+R2IeN4idMzMDhjMEh+9i5+xLvgBdv6H+zdbsahiD0KgCc9+jA0IQXA6H7SODiDqWMHcgFFYWqr/Mrs/789yldeGgQOWOWXUpgMcmzcR0= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Feb 2016 10:10:42.5685 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR0701MB1696 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 dt node parsing for numa topology is done using device property numa-node-id and device node distance-map. Reviewed-by: Robert Richter Signed-off-by: Ganapatrao Kulkarni --- drivers/of/Kconfig | 11 +++ drivers/of/Makefile | 1 + drivers/of/of_numa.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 4 + 4 files changed, 223 insertions(+) create mode 100644 drivers/of/of_numa.c diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index e2a4841..8f9cc3a 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -112,4 +112,15 @@ config OF_OVERLAY While this option is selected automatically when needed, you can enable it manually to improve device tree unit test coverage. +config OF_NUMA + bool "Device Tree NUMA support" + depends on NUMA + depends on OF + depends on ARM64 + default y + help + Enable Device Tree NUMA support. + This enables the numa mapping of cpu, memory, io and + inter node distances using dt bindings. + endif # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 156c072..bee3fa9 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o +obj-$(CONFIG_OF_NUMA) += of_numa.o obj-$(CONFIG_OF_UNITTEST) += unittest-data/ diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c new file mode 100644 index 0000000..1142cdb --- /dev/null +++ b/drivers/of/of_numa.c @@ -0,0 +1,207 @@ +/* + * OF NUMA Parsing support. + * + * Copyright (C) 2015 Cavium Inc. + * Author: Ganapatrao Kulkarni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* define default numa node to 0 */ +#define DEFAULT_NODE 0 + +/* Returns nid in the range [0..MAX_NUMNODES-1], + * or NUMA_NO_NODE if no valid numa-node-id entry found + * or DEFAULT_NODE if no numa-node-id entry exists + */ +static int of_numa_prop_to_nid(const __be32 *of_numa_prop, int length) +{ + int nid; + + if (!of_numa_prop) + return DEFAULT_NODE; + + if (length != sizeof(*of_numa_prop)) { + pr_warn("NUMA: Invalid of_numa_prop length %d found.\n", + length); + return NUMA_NO_NODE; + } + + nid = of_read_number(of_numa_prop, 1); + if (nid >= MAX_NUMNODES) { + pr_warn("NUMA: Invalid numa node %d found.\n", nid); + return NUMA_NO_NODE; + } + + return nid; +} + +static int __init early_init_of_node_to_nid(unsigned long node) +{ + int length; + const __be32 *of_numa_prop; + + of_numa_prop = of_get_flat_dt_prop(node, "numa-node-id", &length); + + return of_numa_prop_to_nid(of_numa_prop, length); +} + +/* + * Even though we connect cpus to numa domains later in SMP + * init, we need to know the node ids now for all cpus. +*/ +static int __init early_init_parse_cpu_node(unsigned long node) +{ + int nid; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + + if (type == NULL) + return 0; + + if (strcmp(type, "cpu") != 0) + return 0; + + nid = early_init_of_node_to_nid(node); + if (nid == NUMA_NO_NODE) + return -EINVAL; + + node_set(nid, numa_nodes_parsed); + return 0; +} + +static int __init early_init_parse_memory_node(unsigned long node) +{ + const __be32 *reg, *endp; + int length; + int nid; + const char *type = of_get_flat_dt_prop(node, "device_type", NULL); + + if (type == NULL) + return 0; + + if (strcmp(type, "memory") != 0) + return 0; + + nid = early_init_of_node_to_nid(node); + if (nid == NUMA_NO_NODE) + return -EINVAL; + + reg = of_get_flat_dt_prop(node, "reg", &length); + endp = reg + (length / sizeof(__be32)); + + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + u64 base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + pr_debug("NUMA: base = %llx , node = %u\n", + base, nid); + + if (numa_add_memblk(nid, base, size) < 0) + return -EINVAL; + } + + return 0; +} + +static int __init early_init_parse_distance_map_v1(unsigned long node, + const char *uname) +{ + const __be32 *prop_dist_matrix; + int length = 0, i, matrix_count; + int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; + + pr_info("NUMA: parsing numa-distance-map-v1\n"); + + prop_dist_matrix = + of_get_flat_dt_prop(node, "distance-matrix", &length); + + if (!length) { + pr_err("NUMA: failed to parse distance-matrix\n"); + return -ENODEV; + } + + matrix_count = ((length / sizeof(__be32)) / (3 * nr_size_cells)); + + if ((matrix_count * sizeof(__be32) * 3 * nr_size_cells) != length) { + pr_warn("NUMA: invalid distance-matrix length %d\n", length); + return -EINVAL; + } + + for (i = 0; i < matrix_count; i++) { + u32 nodea, nodeb, distance; + + nodea = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix); + nodeb = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix); + distance = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix); + numa_set_distance(nodea, nodeb, distance); + pr_debug("NUMA: distance[node%d -> node%d] = %d\n", + nodea, nodeb, distance); + + /* Set default distance of node B->A same as A->B */ + if (nodeb > nodea) + numa_set_distance(nodeb, nodea, distance); + } + + return 0; +} + +static int __init early_init_parse_distance_map(unsigned long node, + const char *uname) +{ + if (strcmp(uname, "distance-map") != 0) + return 0; + + if (of_flat_dt_is_compatible(node, "numa-distance-map-v1")) + return early_init_parse_distance_map_v1(node, uname); + + pr_err("NUMA: invalid distance-map device node\n"); + return -EINVAL; +} + +static int __init early_init_of_scan_numa_map(unsigned long node, const char *uname, + int depth, void *data) +{ + int ret; + + ret = early_init_parse_cpu_node(node); + if (ret) + return ret; + + ret = early_init_parse_memory_node(node); + if (ret) + return ret; + + return early_init_parse_distance_map(node, uname); +} + +int of_node_to_nid(struct device_node *device) +{ + const __be32 *of_numa_prop; + int length; + + of_numa_prop = of_get_property(device, "numa-node-id", &length); + if (of_numa_prop) + return of_numa_prop_to_nid(of_numa_prop, length); + + return NUMA_NO_NODE; +} + +/* DT node mapping is done already early_init_of_scan_memory */ +int __init of_numa_init(void) +{ + return of_scan_flat_dt(early_init_of_scan_numa_map, NULL); +} diff --git a/include/linux/of.h b/include/linux/of.h index dd10626..23e5bad 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -685,6 +685,10 @@ static inline int of_node_to_nid(struct device_node *device) } #endif +#ifdef CONFIG_OF_NUMA +extern int __init of_numa_init(void); +#endif + static inline struct device_node *of_find_matching_node( struct device_node *from, const struct of_device_id *matches)