diff options
-rw-r--r-- | arch/arm64/include/asm/cpu_ops.h | 33 | ||||
-rw-r--r-- | arch/arm64/include/asm/smp.h | 11 | ||||
-rw-r--r-- | arch/arm64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_ops.c | 47 | ||||
-rw-r--r-- | arch/arm64/kernel/psci.c | 11 | ||||
-rw-r--r-- | arch/arm64/kernel/smp.c | 39 | ||||
-rw-r--r-- | arch/arm64/kernel/smp_spin_table.c | 11 |
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 | |||
22 | struct device_node; | ||
23 | |||
24 | struct cpu_operations { | ||
25 | const char *name; | ||
26 | int (*cpu_init)(struct device_node *, unsigned int); | ||
27 | int (*cpu_prepare)(unsigned int); | ||
28 | }; | ||
29 | |||
30 | extern const struct cpu_operations *cpu_ops[NR_CPUS]; | ||
31 | extern 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; | |||
66 | extern void arch_send_call_function_single_ipi(int cpu); | 66 | extern void arch_send_call_function_single_ipi(int cpu); |
67 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | 67 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
68 | 68 | ||
69 | struct device_node; | ||
70 | |||
71 | struct smp_enable_ops { | ||
72 | const char *name; | ||
73 | int (*init_cpu)(struct device_node *, int); | ||
74 | int (*prepare_cpu)(int); | ||
75 | }; | ||
76 | |||
77 | extern const struct smp_enable_ops smp_spin_table_ops; | ||
78 | extern 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) | |||
9 | arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ | 9 | arm64-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 | ||
14 | arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ | 14 | arm64-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 | |||
22 | extern const struct cpu_operations smp_spin_table_ops; | ||
23 | extern const struct cpu_operations cpu_psci_ops; | ||
24 | |||
25 | const struct cpu_operations *cpu_ops[NR_CPUS]; | ||
26 | |||
27 | static 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 | |||
35 | const 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 | ||
234 | static int __init smp_psci_init_cpu(struct device_node *dn, int cpu) | 235 | static 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 | ||
239 | static int __init smp_psci_prepare_cpu(int cpu) | 240 | static 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 | ||
257 | const struct smp_enable_ops smp_psci_ops __initconst = { | 258 | const 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 | ||
233 | static void (*smp_cross_call)(const struct cpumask *, unsigned int); | 234 | static void (*smp_cross_call)(const struct cpumask *, unsigned int); |
234 | 235 | ||
235 | static const struct smp_enable_ops *enable_ops[] __initconst = { | ||
236 | &smp_spin_table_ops, | ||
237 | &smp_psci_ops, | ||
238 | NULL, | ||
239 | }; | ||
240 | |||
241 | static const struct smp_enable_ops *smp_enable_ops[NR_CPUS]; | ||
242 | |||
243 | static 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 | ||
381 | void __init smp_prepare_cpus(unsigned int max_cpus) | 360 | void __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 | ||
25 | static phys_addr_t cpu_release_addr[NR_CPUS]; | 26 | static phys_addr_t cpu_release_addr[NR_CPUS]; |
26 | 27 | ||
27 | static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu) | 28 | static 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 | ||
43 | static int __init smp_spin_table_prepare_cpu(int cpu) | 44 | static 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 | ||
62 | const struct smp_enable_ops smp_spin_table_ops __initconst = { | 63 | const 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 | }; |