aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorZi Shen Lim <zlim@broadcom.com>2014-06-06 20:55:27 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2014-07-09 07:22:40 -0400
commit4e6f7084096c08e37f909d7b075a91b72580405f (patch)
tree701d86fcc8f65fae5579532aabd623b34e08c7dd /arch/arm64
parentcd3de83f147601356395b57a8673e9c5ff1e59d1 (diff)
arm64: topology: add MPIDR-based detection
Create cpu topology based on MPIDR. When hardware sets MPIDR to sane values, this method will always work. Therefore it should also work well as the fallback method. [1] When we have multiple processing elements in the system, we create the cpu topology by mapping each affinity level (from lowest to highest) to threads (if they exist), cores, and clusters. [1] http://www.spinics.net/lists/arm-kernel/msg317445.html Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Zi Shen Lim <zlim@broadcom.com> Signed-off-by: Mark Brown <broonie@linaro.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/include/asm/cputype.h2
-rw-r--r--arch/arm64/kernel/topology.c47
2 files changed, 35 insertions, 14 deletions
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 27f54a7cc81b..ed48a3a7836a 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -18,6 +18,8 @@
18 18
19#define INVALID_HWID ULONG_MAX 19#define INVALID_HWID ULONG_MAX
20 20
21#define MPIDR_UP_BITMASK (0x1 << 30)
22#define MPIDR_MT_BITMASK (0x1 << 24)
21#define MPIDR_HWID_BITMASK 0xff00ffffff 23#define MPIDR_HWID_BITMASK 0xff00ffffff
22 24
23#define MPIDR_LEVEL_BITS_SHIFT 3 25#define MPIDR_LEVEL_BITS_SHIFT 3
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 43514f905916..b6ee26b0939a 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -20,6 +20,7 @@
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/sched.h> 21#include <linux/sched.h>
22 22
23#include <asm/cputype.h>
23#include <asm/topology.h> 24#include <asm/topology.h>
24 25
25static int __init get_cpu_for_node(struct device_node *node) 26static int __init get_cpu_for_node(struct device_node *node)
@@ -188,13 +189,9 @@ static int __init parse_dt_topology(void)
188 * Check that all cores are in the topology; the SMP code will 189 * Check that all cores are in the topology; the SMP code will
189 * only mark cores described in the DT as possible. 190 * only mark cores described in the DT as possible.
190 */ 191 */
191 for_each_possible_cpu(cpu) { 192 for_each_possible_cpu(cpu)
192 if (cpu_topology[cpu].cluster_id == -1) { 193 if (cpu_topology[cpu].cluster_id == -1)
193 pr_err("CPU%d: No topology information specified\n",
194 cpu);
195 ret = -EINVAL; 194 ret = -EINVAL;
196 }
197 }
198 195
199out_map: 196out_map:
200 of_node_put(map); 197 of_node_put(map);
@@ -219,14 +216,6 @@ static void update_siblings_masks(unsigned int cpuid)
219 struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; 216 struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
220 int cpu; 217 int cpu;
221 218
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 */ 219 /* update core and thread sibling masks */
231 for_each_possible_cpu(cpu) { 220 for_each_possible_cpu(cpu) {
232 cpu_topo = &cpu_topology[cpu]; 221 cpu_topo = &cpu_topology[cpu];
@@ -249,6 +238,36 @@ static void update_siblings_masks(unsigned int cpuid)
249 238
250void store_cpu_topology(unsigned int cpuid) 239void store_cpu_topology(unsigned int cpuid)
251{ 240{
241 struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
242 u64 mpidr;
243
244 if (cpuid_topo->cluster_id != -1)
245 goto topology_populated;
246
247 mpidr = read_cpuid_mpidr();
248
249 /* Uniprocessor systems can rely on default topology values */
250 if (mpidr & MPIDR_UP_BITMASK)
251 return;
252
253 /* Create cpu topology mapping based on MPIDR. */
254 if (mpidr & MPIDR_MT_BITMASK) {
255 /* Multiprocessor system : Multi-threads per core */
256 cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
257 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
258 cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
259 } else {
260 /* Multiprocessor system : Single-thread per core */
261 cpuid_topo->thread_id = -1;
262 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
263 cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
264 }
265
266 pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
267 cpuid, cpuid_topo->cluster_id, cpuid_topo->core_id,
268 cpuid_topo->thread_id, mpidr);
269
270topology_populated:
252 update_siblings_masks(cpuid); 271 update_siblings_masks(cpuid);
253} 272}
254 273