brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · 2ec2088 Raw
188 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * OF NUMA Parsing support.4 *5 * Copyright (C) 2015 - 2016 Cavium Inc.6 */7 8#define pr_fmt(fmt) "OF: NUMA: " fmt9 10#include <linux/of.h>11#include <linux/of_address.h>12#include <linux/nodemask.h>13#include <linux/numa_memblks.h>14 15#include <asm/numa.h>16 17/* define default numa node to 0 */18#define DEFAULT_NODE 019 20/*21 * Even though we connect cpus to numa domains later in SMP22 * init, we need to know the node ids now for all cpus.23*/24static void __init of_numa_parse_cpu_nodes(void)25{26	u32 nid;27	int r;28	struct device_node *np;29 30	for_each_of_cpu_node(np) {31		r = of_property_read_u32(np, "numa-node-id", &nid);32		if (r)33			continue;34 35		pr_debug("CPU on %u\n", nid);36		if (nid >= MAX_NUMNODES)37			pr_warn("Node id %u exceeds maximum value\n", nid);38		else39			node_set(nid, numa_nodes_parsed);40	}41}42 43static int __init of_numa_parse_memory_nodes(void)44{45	struct device_node *np = NULL;46	struct resource rsrc;47	u32 nid;48	int i, r = -EINVAL;49 50	for_each_node_by_type(np, "memory") {51		r = of_property_read_u32(np, "numa-node-id", &nid);52		if (r == -EINVAL)53			/*54			 * property doesn't exist if -EINVAL, continue55			 * looking for more memory nodes with56			 * "numa-node-id" property57			 */58			continue;59 60		if (nid >= MAX_NUMNODES) {61			pr_warn("Node id %u exceeds maximum value\n", nid);62			r = -EINVAL;63		}64 65		for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++)66			r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);67 68		if (!i || r) {69			of_node_put(np);70			pr_err("bad property in memory node\n");71			return r ? : -EINVAL;72		}73	}74 75	return r;76}77 78static int __init of_numa_parse_distance_map_v1(struct device_node *map)79{80	const __be32 *matrix;81	int entry_count;82	int i;83 84	pr_info("parsing numa-distance-map-v1\n");85 86	matrix = of_get_property(map, "distance-matrix", NULL);87	if (!matrix) {88		pr_err("No distance-matrix property in distance-map\n");89		return -EINVAL;90	}91 92	entry_count = of_property_count_u32_elems(map, "distance-matrix");93	if (entry_count <= 0) {94		pr_err("Invalid distance-matrix\n");95		return -EINVAL;96	}97 98	for (i = 0; i + 2 < entry_count; i += 3) {99		u32 nodea, nodeb, distance;100 101		nodea = of_read_number(matrix, 1);102		matrix++;103		nodeb = of_read_number(matrix, 1);104		matrix++;105		distance = of_read_number(matrix, 1);106		matrix++;107 108		if ((nodea == nodeb && distance != LOCAL_DISTANCE) ||109		    (nodea != nodeb && distance <= LOCAL_DISTANCE)) {110			pr_err("Invalid distance[node%d -> node%d] = %d\n",111			       nodea, nodeb, distance);112			return -EINVAL;113		}114 115		node_set(nodea, numa_nodes_parsed);116 117		numa_set_distance(nodea, nodeb, distance);118 119		/* Set default distance of node B->A same as A->B */120		if (nodeb > nodea)121			numa_set_distance(nodeb, nodea, distance);122	}123 124	return 0;125}126 127static int __init of_numa_parse_distance_map(void)128{129	int ret = 0;130	struct device_node *np;131 132	np = of_find_compatible_node(NULL, NULL,133				     "numa-distance-map-v1");134	if (np)135		ret = of_numa_parse_distance_map_v1(np);136 137	of_node_put(np);138	return ret;139}140 141int of_node_to_nid(struct device_node *device)142{143	struct device_node *np;144	u32 nid;145	int r = -ENODATA;146 147	np = of_node_get(device);148 149	while (np) {150		r = of_property_read_u32(np, "numa-node-id", &nid);151		/*152		 * -EINVAL indicates the property was not found, and153		 *  we walk up the tree trying to find a parent with a154		 *  "numa-node-id".  Any other type of error indicates155		 *  a bad device tree and we give up.156		 */157		if (r != -EINVAL)158			break;159 160		np = of_get_next_parent(np);161	}162	if (np && r)163		pr_warn("Invalid \"numa-node-id\" property in node %pOFn\n",164			np);165	of_node_put(np);166 167	/*168	 * If numa=off passed on command line, or with a defective169	 * device tree, the nid may not be in the set of possible170	 * nodes.  Check for this case and return NUMA_NO_NODE.171	 */172	if (!r && nid < MAX_NUMNODES && node_possible(nid))173		return nid;174 175	return NUMA_NO_NODE;176}177 178int __init of_numa_init(void)179{180	int r;181 182	of_numa_parse_cpu_nodes();183	r = of_numa_parse_memory_nodes();184	if (r)185		return r;186	return of_numa_parse_distance_map();187}188