1 /* 2 * OF NUMA Parsing support. 3 * 4 * Copyright (C) 2015 - 2016 Cavium Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #define pr_fmt(fmt) "OF: NUMA: " fmt 20 21 #include <linux/of.h> 22 #include <linux/of_address.h> 23 #include <linux/nodemask.h> 24 25 #include <asm/numa.h> 26 27 /* define default numa node to 0 */ 28 #define DEFAULT_NODE 0 29 30 /* 31 * Even though we connect cpus to numa domains later in SMP 32 * init, we need to know the node ids now for all cpus. 33 */ 34 static void __init of_numa_parse_cpu_nodes(void) 35 { 36 u32 nid; 37 int r; 38 struct device_node *cpus; 39 struct device_node *np = NULL; 40 41 cpus = of_find_node_by_path("/cpus"); 42 if (!cpus) 43 return; 44 45 for_each_child_of_node(cpus, np) { 46 /* Skip things that are not CPUs */ 47 if (of_node_cmp(np->type, "cpu") != 0) 48 continue; 49 50 r = of_property_read_u32(np, "numa-node-id", &nid); 51 if (r) 52 continue; 53 54 pr_debug("CPU on %u\n", nid); 55 if (nid >= MAX_NUMNODES) 56 pr_warn("Node id %u exceeds maximum value\n", nid); 57 else 58 node_set(nid, numa_nodes_parsed); 59 } 60 61 of_node_put(cpus); 62 } 63 64 static int __init of_numa_parse_memory_nodes(void) 65 { 66 struct device_node *np = NULL; 67 struct resource rsrc; 68 u32 nid; 69 int i, r; 70 71 for_each_node_by_type(np, "memory") { 72 r = of_property_read_u32(np, "numa-node-id", &nid); 73 if (r == -EINVAL) 74 /* 75 * property doesn't exist if -EINVAL, continue 76 * looking for more memory nodes with 77 * "numa-node-id" property 78 */ 79 continue; 80 81 if (nid >= MAX_NUMNODES) { 82 pr_warn("Node id %u exceeds maximum value\n", nid); 83 r = -EINVAL; 84 } 85 86 for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++) 87 r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1); 88 89 if (!i || r) { 90 of_node_put(np); 91 pr_err("bad property in memory node\n"); 92 return r ? : -EINVAL; 93 } 94 } 95 96 return 0; 97 } 98 99 static int __init of_numa_parse_distance_map_v1(struct device_node *map) 100 { 101 const __be32 *matrix; 102 int entry_count; 103 int i; 104 105 pr_info("parsing numa-distance-map-v1\n"); 106 107 matrix = of_get_property(map, "distance-matrix", NULL); 108 if (!matrix) { 109 pr_err("No distance-matrix property in distance-map\n"); 110 return -EINVAL; 111 } 112 113 entry_count = of_property_count_u32_elems(map, "distance-matrix"); 114 if (entry_count <= 0) { 115 pr_err("Invalid distance-matrix\n"); 116 return -EINVAL; 117 } 118 119 for (i = 0; i + 2 < entry_count; i += 3) { 120 u32 nodea, nodeb, distance; 121 122 nodea = of_read_number(matrix, 1); 123 matrix++; 124 nodeb = of_read_number(matrix, 1); 125 matrix++; 126 distance = of_read_number(matrix, 1); 127 matrix++; 128 129 numa_set_distance(nodea, nodeb, distance); 130 pr_debug("distance[node%d -> node%d] = %d\n", 131 nodea, nodeb, distance); 132 133 /* Set default distance of node B->A same as A->B */ 134 if (nodeb > nodea) 135 numa_set_distance(nodeb, nodea, distance); 136 } 137 138 return 0; 139 } 140 141 static int __init of_numa_parse_distance_map(void) 142 { 143 int ret = 0; 144 struct device_node *np; 145 146 np = of_find_compatible_node(NULL, NULL, 147 "numa-distance-map-v1"); 148 if (np) 149 ret = of_numa_parse_distance_map_v1(np); 150 151 of_node_put(np); 152 return ret; 153 } 154 155 int of_node_to_nid(struct device_node *device) 156 { 157 struct device_node *np; 158 u32 nid; 159 int r = -ENODATA; 160 161 np = of_node_get(device); 162 163 while (np) { 164 r = of_property_read_u32(np, "numa-node-id", &nid); 165 /* 166 * -EINVAL indicates the property was not found, and 167 * we walk up the tree trying to find a parent with a 168 * "numa-node-id". Any other type of error indicates 169 * a bad device tree and we give up. 170 */ 171 if (r != -EINVAL) 172 break; 173 174 np = of_get_next_parent(np); 175 } 176 if (np && r) 177 pr_warn("Invalid \"numa-node-id\" property in node %s\n", 178 np->name); 179 of_node_put(np); 180 181 /* 182 * If numa=off passed on command line, or with a defective 183 * device tree, the nid may not be in the set of possible 184 * nodes. Check for this case and return NUMA_NO_NODE. 185 */ 186 if (!r && nid < MAX_NUMNODES && node_possible(nid)) 187 return nid; 188 189 return NUMA_NO_NODE; 190 } 191 EXPORT_SYMBOL(of_node_to_nid); 192 193 int __init of_numa_init(void) 194 { 195 int r; 196 197 of_numa_parse_cpu_nodes(); 198 r = of_numa_parse_memory_nodes(); 199 if (r) 200 return r; 201 return of_numa_parse_distance_map(); 202 } 203