aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/cpu_ops.h33
-rw-r--r--arch/arm64/include/asm/smp.h11
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/cpu_ops.c47
-rw-r--r--arch/arm64/kernel/psci.c11
-rw-r--r--arch/arm64/kernel/smp.c39
-rw-r--r--arch/arm64/kernel/smp_spin_table.c11
7 files changed, 102 insertions, 52 deletions
diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
new file mode 100644
index 000000000000..3c60c8d1d928
--- /dev/null
+++ b/arch/arm64/include/asm/cpu_ops.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2013 ARM Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef __ASM_CPU_OPS_H
17#define __ASM_CPU_OPS_H
18
19#include <linux/init.h>
20#include <linux/threads.h>
21
22struct device_node;
23
24struct cpu_operations {
25 const char *name;
26 int (*cpu_init)(struct device_node *, unsigned int);
27 int (*cpu_prepare)(unsigned int);
28};
29
30extern const struct cpu_operations *cpu_ops[NR_CPUS];
31extern const struct cpu_operations * __init cpu_get_ops(const char *name);
32
33#endif /* ifndef __ASM_CPU_OPS_H */
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 4b8023c5d146..7e34295f78e3 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -66,15 +66,4 @@ extern volatile unsigned long secondary_holding_pen_release;
66extern void arch_send_call_function_single_ipi(int cpu); 66extern void arch_send_call_function_single_ipi(int cpu);
67extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); 67extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
68 68
69struct device_node;
70
71struct smp_enable_ops {
72 const char *name;
73 int (*init_cpu)(struct device_node *, int);
74 int (*prepare_cpu)(int);
75};
76
77extern const struct smp_enable_ops smp_spin_table_ops;
78extern const struct smp_enable_ops smp_psci_ops;
79
80#endif /* ifndef __ASM_SMP_H */ 69#endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 75a90c15b30b..5ba2fd43a75b 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,7 +9,7 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
9arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ 9arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
10 entry-fpsimd.o process.o ptrace.o setup.o signal.o \ 10 entry-fpsimd.o process.o ptrace.o setup.o signal.o \
11 sys.o stacktrace.o time.o traps.o io.o vdso.o \ 11 sys.o stacktrace.o time.o traps.o io.o vdso.o \
12 hyp-stub.o psci.o 12 hyp-stub.o psci.o cpu_ops.o
13 13
14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ 14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
15 sys_compat.o 15 sys_compat.o
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
new file mode 100644
index 000000000000..e2652aadd9ea
--- /dev/null
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -0,0 +1,47 @@
1/*
2 * CPU kernel entry/exit control
3 *
4 * Copyright (C) 2013 ARM Ltd.
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#include <asm/cpu_ops.h>
20#include <linux/string.h>
21
22extern const struct cpu_operations smp_spin_table_ops;
23extern const struct cpu_operations cpu_psci_ops;
24
25const struct cpu_operations *cpu_ops[NR_CPUS];
26
27static const struct cpu_operations *supported_cpu_ops[] __initconst = {
28#ifdef CONFIG_SMP
29 &smp_spin_table_ops,
30 &cpu_psci_ops,
31#endif
32 NULL,
33};
34
35const struct cpu_operations * __init cpu_get_ops(const char *name)
36{
37 const struct cpu_operations **ops = supported_cpu_ops;
38
39 while (*ops) {
40 if (!strcmp(name, (*ops)->name))
41 return *ops;
42
43 ops++;
44 }
45
46 return NULL;
47}
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 368b78788cb5..ccec2ca67755 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -20,6 +20,7 @@
20#include <linux/smp.h> 20#include <linux/smp.h>
21 21
22#include <asm/compiler.h> 22#include <asm/compiler.h>
23#include <asm/cpu_ops.h>
23#include <asm/errno.h> 24#include <asm/errno.h>
24#include <asm/psci.h> 25#include <asm/psci.h>
25#include <asm/smp_plat.h> 26#include <asm/smp_plat.h>
@@ -231,12 +232,12 @@ out_put_node:
231 232
232#ifdef CONFIG_SMP 233#ifdef CONFIG_SMP
233 234
234static int __init smp_psci_init_cpu(struct device_node *dn, int cpu) 235static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
235{ 236{
236 return 0; 237 return 0;
237} 238}
238 239
239static int __init smp_psci_prepare_cpu(int cpu) 240static int __init cpu_psci_cpu_prepare(unsigned int cpu)
240{ 241{
241 int err; 242 int err;
242 243
@@ -254,10 +255,10 @@ static int __init smp_psci_prepare_cpu(int cpu)
254 return 0; 255 return 0;
255} 256}
256 257
257const struct smp_enable_ops smp_psci_ops __initconst = { 258const struct cpu_operations cpu_psci_ops = {
258 .name = "psci", 259 .name = "psci",
259 .init_cpu = smp_psci_init_cpu, 260 .cpu_init = cpu_psci_cpu_init,
260 .prepare_cpu = smp_psci_prepare_cpu, 261 .cpu_prepare = cpu_psci_cpu_prepare,
261}; 262};
262 263
263#endif 264#endif
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 78db90dcc910..8965fb7dee89 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -39,6 +39,7 @@
39#include <asm/atomic.h> 39#include <asm/atomic.h>
40#include <asm/cacheflush.h> 40#include <asm/cacheflush.h>
41#include <asm/cputype.h> 41#include <asm/cputype.h>
42#include <asm/cpu_ops.h>
42#include <asm/mmu_context.h> 43#include <asm/mmu_context.h>
43#include <asm/pgtable.h> 44#include <asm/pgtable.h>
44#include <asm/pgalloc.h> 45#include <asm/pgalloc.h>
@@ -232,28 +233,6 @@ void __init smp_prepare_boot_cpu(void)
232 233
233static void (*smp_cross_call)(const struct cpumask *, unsigned int); 234static void (*smp_cross_call)(const struct cpumask *, unsigned int);
234 235
235static const struct smp_enable_ops *enable_ops[] __initconst = {
236 &smp_spin_table_ops,
237 &smp_psci_ops,
238 NULL,
239};
240
241static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];
242
243static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
244{
245 const struct smp_enable_ops **ops = enable_ops;
246
247 while (*ops) {
248 if (!strcmp(name, (*ops)->name))
249 return *ops;
250
251 ops++;
252 }
253
254 return NULL;
255}
256
257/* 236/*
258 * Enumerate the possible CPU set from the device tree and build the 237 * Enumerate the possible CPU set from the device tree and build the
259 * cpu logical map array containing MPIDR values related to logical 238 * cpu logical map array containing MPIDR values related to logical
@@ -263,7 +242,7 @@ void __init smp_init_cpus(void)
263{ 242{
264 const char *enable_method; 243 const char *enable_method;
265 struct device_node *dn = NULL; 244 struct device_node *dn = NULL;
266 int i, cpu = 1; 245 unsigned int i, cpu = 1;
267 bool bootcpu_valid = false; 246 bool bootcpu_valid = false;
268 247
269 while ((dn = of_find_node_by_type(dn, "cpu"))) { 248 while ((dn = of_find_node_by_type(dn, "cpu"))) {
@@ -342,15 +321,15 @@ void __init smp_init_cpus(void)
342 goto next; 321 goto next;
343 } 322 }
344 323
345 smp_enable_ops[cpu] = smp_get_enable_ops(enable_method); 324 cpu_ops[cpu] = cpu_get_ops(enable_method);
346 325
347 if (!smp_enable_ops[cpu]) { 326 if (!cpu_ops[cpu]) {
348 pr_err("%s: invalid enable-method property: %s\n", 327 pr_err("%s: invalid enable-method property: %s\n",
349 dn->full_name, enable_method); 328 dn->full_name, enable_method);
350 goto next; 329 goto next;
351 } 330 }
352 331
353 if (smp_enable_ops[cpu]->init_cpu(dn, cpu)) 332 if (cpu_ops[cpu]->cpu_init(dn, cpu))
354 goto next; 333 goto next;
355 334
356 pr_debug("cpu logical map 0x%llx\n", hwid); 335 pr_debug("cpu logical map 0x%llx\n", hwid);
@@ -380,8 +359,8 @@ next:
380 359
381void __init smp_prepare_cpus(unsigned int max_cpus) 360void __init smp_prepare_cpus(unsigned int max_cpus)
382{ 361{
383 int cpu, err; 362 int err;
384 unsigned int ncores = num_possible_cpus(); 363 unsigned int cpu, ncores = num_possible_cpus();
385 364
386 /* 365 /*
387 * are we trying to boot more cores than exist? 366 * are we trying to boot more cores than exist?
@@ -408,10 +387,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
408 if (cpu == smp_processor_id()) 387 if (cpu == smp_processor_id())
409 continue; 388 continue;
410 389
411 if (!smp_enable_ops[cpu]) 390 if (!cpu_ops[cpu])
412 continue; 391 continue;
413 392
414 err = smp_enable_ops[cpu]->prepare_cpu(cpu); 393 err = cpu_ops[cpu]->cpu_prepare(cpu);
415 if (err) 394 if (err)
416 continue; 395 continue;
417 396
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 7c35fa682f76..a8b76e4eccff 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -21,10 +21,11 @@
21#include <linux/smp.h> 21#include <linux/smp.h>
22 22
23#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
24#include <asm/cpu_ops.h>
24 25
25static phys_addr_t cpu_release_addr[NR_CPUS]; 26static phys_addr_t cpu_release_addr[NR_CPUS];
26 27
27static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu) 28static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
28{ 29{
29 /* 30 /*
30 * Determine the address from which the CPU is polling. 31 * Determine the address from which the CPU is polling.
@@ -40,7 +41,7 @@ static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu)
40 return 0; 41 return 0;
41} 42}
42 43
43static int __init smp_spin_table_prepare_cpu(int cpu) 44static int smp_spin_table_cpu_prepare(unsigned int cpu)
44{ 45{
45 void **release_addr; 46 void **release_addr;
46 47
@@ -59,8 +60,8 @@ static int __init smp_spin_table_prepare_cpu(int cpu)
59 return 0; 60 return 0;
60} 61}
61 62
62const struct smp_enable_ops smp_spin_table_ops __initconst = { 63const struct cpu_operations smp_spin_table_ops = {
63 .name = "spin-table", 64 .name = "spin-table",
64 .init_cpu = smp_spin_table_init_cpu, 65 .cpu_init = smp_spin_table_cpu_init,
65 .prepare_cpu = smp_spin_table_prepare_cpu, 66 .cpu_prepare = smp_spin_table_cpu_prepare,
66}; 67};