1 /* 2 * arch/arm64/kernel/topology.c 3 * 4 * Copyright (C) 2011,2013,2014 Linaro Limited. 5 * 6 * Based on the arm32 version written by Vincent Guittot in turn based on 7 * arch/sh/kernel/topology.c 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13 14 #include <linux/cpu.h> 15 #include <linux/cpumask.h> 16 #include <linux/init.h> 17 #include <linux/percpu.h> 18 #include <linux/node.h> 19 #include <linux/nodemask.h> 20 #include <linux/of.h> 21 #include <linux/sched.h> 22 23 #include <asm/topology.h> 24 25 static int __init get_cpu_for_node(struct device_node *node) 26 { 27 struct device_node *cpu_node; 28 int cpu; 29 30 cpu_node = of_parse_phandle(node, "cpu", 0); 31 if (!cpu_node) 32 return -1; 33 34 for_each_possible_cpu(cpu) { 35 if (of_get_cpu_node(cpu, NULL) == cpu_node) { 36 of_node_put(cpu_node); 37 return cpu; 38 } 39 } 40 41 pr_crit("Unable to find CPU node for %s\n", cpu_node->full_name); 42 43 of_node_put(cpu_node); 44 return -1; 45 } 46 47 static int __init parse_core(struct device_node *core, int cluster_id, 48 int core_id) 49 { 50 char name[10]; 51 bool leaf = true; 52 int i = 0; 53 int cpu; 54 struct device_node *t; 55 56 do { 57 snprintf(name, sizeof(name), "thread%d", i); 58 t = of_get_child_by_name(core, name); 59 if (t) { 60 leaf = false; 61 cpu = get_cpu_for_node(t); 62 if (cpu >= 0) { 63 cpu_topology[cpu].cluster_id = cluster_id; 64 cpu_topology[cpu].core_id = core_id; 65 cpu_topology[cpu].thread_id = i; 66 } else { 67 pr_err("%s: Can't get CPU for thread\n", 68 t->full_name); 69 of_node_put(t); 70 return -EINVAL; 71 } 72 of_node_put(t); 73 } 74 i++; 75 } while (t); 76 77 cpu = get_cpu_for_node(core); 78 if (cpu >= 0) { 79 if (!leaf) { 80 pr_err("%s: Core has both threads and CPU\n", 81 core->full_name); 82 return -EINVAL; 83 } 84 85 cpu_topology[cpu].cluster_id = cluster_id; 86 cpu_topology[cpu].core_id = core_id; 87 } else if (leaf) { 88 pr_err("%s: Can't get CPU for leaf core\n", core->full_name); 89 return -EINVAL; 90 } 91 92 return 0; 93 } 94 95 static int __init parse_cluster(struct device_node *cluster, int depth) 96 { 97 char name[10]; 98 bool leaf = true; 99 bool has_cores = false; 100 struct device_node *c; 101 static int cluster_id __initdata; 102 int core_id = 0; 103 int i, ret; 104 105 /* 106 * First check for child clusters; we currently ignore any 107 * information about the nesting of clusters and present the 108 * scheduler with a flat list of them. 109 */ 110 i = 0; 111 do { 112 snprintf(name, sizeof(name), "cluster%d", i); 113 c = of_get_child_by_name(cluster, name); 114 if (c) { 115 leaf = false; 116 ret = parse_cluster(c, depth + 1); 117 of_node_put(c); 118 if (ret != 0) 119 return ret; 120 } 121 i++; 122 } while (c); 123 124 /* Now check for cores */ 125 i = 0; 126 do { 127 snprintf(name, sizeof(name), "core%d", i); 128 c = of_get_child_by_name(cluster, name); 129 if (c) { 130 has_cores = true; 131 132 if (depth == 0) { 133 pr_err("%s: cpu-map children should be clusters\n", 134 c->full_name); 135 of_node_put(c); 136 return -EINVAL; 137 } 138 139 if (leaf) { 140 ret = parse_core(c, cluster_id, core_id++); 141 } else { 142 pr_err("%s: Non-leaf cluster with core %s\n", 143 cluster->full_name, name); 144 ret = -EINVAL; 145 } 146 147 of_node_put(c); 148 if (ret != 0) 149 return ret; 150 } 151 i++; 152 } while (c); 153 154 if (leaf && !has_cores) 155 pr_warn("%s: empty cluster\n", cluster->full_name); 156 157 if (leaf) 158 cluster_id++; 159 160 return 0; 161 } 162 163 static int __init parse_dt_topology(void) 164 { 165 struct device_node *cn, *map; 166 int ret = 0; 167 int cpu; 168 169 cn = of_find_node_by_path("/cpus"); 170 if (!cn) { 171 pr_err("No CPU information found in DT\n"); 172 return 0; 173 } 174 175 /* 176 * When topology is provided cpu-map is essentially a root 177 * cluster with restricted subnodes. 178 */ 179 map = of_get_child_by_name(cn, "cpu-map"); 180 if (!map) 181 goto out; 182 183 ret = parse_cluster(map, 0); 184 if (ret != 0) 185 goto out_map; 186 187 /* 188 * Check that all cores are in the topology; the SMP code will 189 * only mark cores described in the DT as possible. 190 */ 191 for_each_possible_cpu(cpu) { 192 if (cpu_topology[cpu].cluster_id == -1) { 193 pr_err("CPU%d: No topology information specified\n", 194 cpu); 195 ret = -EINVAL; 196 } 197 } 198 199 out_map: 200 of_node_put(map); 201 out: 202 of_node_put(cn); 203 return ret; 204 } 205 206 /* 207 * cpu topology table 208 */ 209 struct cpu_topology cpu_topology[NR_CPUS]; 210 EXPORT_SYMBOL_GPL(cpu_topology); 211 212 const struct cpumask *cpu_coregroup_mask(int cpu) 213 { 214 return &cpu_topology[cpu].core_sibling; 215 } 216 217 static void update_siblings_masks(unsigned int cpuid) 218 { 219 struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; 220 int cpu; 221 222 if (cpuid_topo->cluster_id == -1) { 223 /* 224 * DT does not contain topology information for this cpu. 225 */ 226 pr_debug("CPU%u: No topology information configured\n", cpuid); 227 return; 228 } 229 230 /* update core and thread sibling masks */ 231 for_each_possible_cpu(cpu) { 232 cpu_topo = &cpu_topology[cpu]; 233 234 if (cpuid_topo->cluster_id != cpu_topo->cluster_id) 235 continue; 236 237 cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); 238 if (cpu != cpuid) 239 cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); 240 241 if (cpuid_topo->core_id != cpu_topo->core_id) 242 continue; 243 244 cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); 245 if (cpu != cpuid) 246 cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); 247 } 248 } 249 250 void store_cpu_topology(unsigned int cpuid) 251 { 252 update_siblings_masks(cpuid); 253 } 254 255 static void __init reset_cpu_topology(void) 256 { 257 unsigned int cpu; 258 259 for_each_possible_cpu(cpu) { 260 struct cpu_topology *cpu_topo = &cpu_topology[cpu]; 261 262 cpu_topo->thread_id = -1; 263 cpu_topo->core_id = 0; 264 cpu_topo->cluster_id = -1; 265 266 cpumask_clear(&cpu_topo->core_sibling); 267 cpumask_set_cpu(cpu, &cpu_topo->core_sibling); 268 cpumask_clear(&cpu_topo->thread_sibling); 269 cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); 270 } 271 } 272 273 void __init init_cpu_topology(void) 274 { 275 reset_cpu_topology(); 276 277 /* 278 * Discard anything that was parsed if we hit an error so we 279 * don't use partial information. 280 */ 281 if (parse_dt_topology()) 282 reset_cpu_topology(); 283 } 284