Commit 6c3ff8b11a16ec69199ab85b74a5fae6d9c59db7
Committed by
Kumar Gala
1 parent
cf1e8f0cd6
Exists in
master
and in
13 other branches
ARM: Introduce CPU_METHOD_OF_DECLARE() for cpu hotplug/smp
The goal of multi-platform kernels is to remove the need for mach directories and machine descriptors. To further that goal, introduce CPU_METHOD_OF_DECLARE() to allow cpu hotplug/smp support to be separated from the machine descriptors. Implementers should specify an enable-method property in their cpus node and then implement a matching set of smp_ops in their hotplug/smp code, wiring it up with the CPU_METHOD_OF_DECLARE() macro. When the kernel is compiled we'll collect all the enable-method smp_ops into one section for use at boot. At boot time we'll look for an enable-method in each cpu node and try to match that against all known CPU enable methods in the kernel. If there are no enable-methods in the cpu nodes we fallback to the cpus node and try to use any enable-method found there. If that doesn't work we fall back to the old way of using the machine descriptor. Acked-by: Mark Rutland <mark.rutland@arm.com> Cc: Russell King <linux@arm.linux.org.uk> Cc: <devicetree@vger.kernel.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Kumar Gala <galak@codeaurora.org>
Showing 3 changed files with 59 additions and 0 deletions Side-by-side Diff
arch/arm/include/asm/smp.h
... | ... | @@ -114,6 +114,15 @@ |
114 | 114 | #endif |
115 | 115 | }; |
116 | 116 | |
117 | +struct of_cpu_method { | |
118 | + const char *method; | |
119 | + struct smp_operations *ops; | |
120 | +}; | |
121 | + | |
122 | +#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \ | |
123 | + static const struct of_cpu_method __cpu_method_of_table_##name \ | |
124 | + __used __section(__cpu_method_of_table) \ | |
125 | + = { .method = _method, .ops = _ops } | |
117 | 126 | /* |
118 | 127 | * set platform specific SMP operations |
119 | 128 | */ |
arch/arm/kernel/devtree.c
... | ... | @@ -18,6 +18,7 @@ |
18 | 18 | #include <linux/of_fdt.h> |
19 | 19 | #include <linux/of_irq.h> |
20 | 20 | #include <linux/of_platform.h> |
21 | +#include <linux/smp.h> | |
21 | 22 | |
22 | 23 | #include <asm/cputype.h> |
23 | 24 | #include <asm/setup.h> |
... | ... | @@ -63,6 +64,34 @@ |
63 | 64 | } |
64 | 65 | } |
65 | 66 | |
67 | +#ifdef CONFIG_SMP | |
68 | +extern struct of_cpu_method __cpu_method_of_table_begin[]; | |
69 | +extern struct of_cpu_method __cpu_method_of_table_end[]; | |
70 | + | |
71 | +static int __init set_smp_ops_by_method(struct device_node *node) | |
72 | +{ | |
73 | + const char *method; | |
74 | + struct of_cpu_method *m = __cpu_method_of_table_begin; | |
75 | + | |
76 | + if (of_property_read_string(node, "enable-method", &method)) | |
77 | + return 0; | |
78 | + | |
79 | + for (; m < __cpu_method_of_table_end; m++) | |
80 | + if (!strcmp(m->method, method)) { | |
81 | + smp_set_ops(m->ops); | |
82 | + return 1; | |
83 | + } | |
84 | + | |
85 | + return 0; | |
86 | +} | |
87 | +#else | |
88 | +static inline int set_smp_ops_by_method(struct device_node *node) | |
89 | +{ | |
90 | + return 1; | |
91 | +} | |
92 | +#endif | |
93 | + | |
94 | + | |
66 | 95 | /* |
67 | 96 | * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree |
68 | 97 | * and builds the cpu logical map array containing MPIDR values related to |
... | ... | @@ -79,6 +108,7 @@ |
79 | 108 | * read as 0. |
80 | 109 | */ |
81 | 110 | struct device_node *cpu, *cpus; |
111 | + int found_method = 0; | |
82 | 112 | u32 i, j, cpuidx = 1; |
83 | 113 | u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; |
84 | 114 | |
85 | 115 | |
... | ... | @@ -150,7 +180,17 @@ |
150 | 180 | } |
151 | 181 | |
152 | 182 | tmp_map[i] = hwid; |
183 | + | |
184 | + if (!found_method) | |
185 | + found_method = set_smp_ops_by_method(cpu); | |
153 | 186 | } |
187 | + | |
188 | + /* | |
189 | + * Fallback to an enable-method in the cpus node if nothing found in | |
190 | + * a cpu node. | |
191 | + */ | |
192 | + if (!found_method) | |
193 | + set_smp_ops_by_method(cpus); | |
154 | 194 | |
155 | 195 | if (!bootcpu_valid) { |
156 | 196 | pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n"); |
include/asm-generic/vmlinux.lds.h
... | ... | @@ -167,6 +167,15 @@ |
167 | 167 | #define CLK_OF_TABLES() |
168 | 168 | #endif |
169 | 169 | |
170 | +#ifdef CONFIG_SMP | |
171 | +#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ | |
172 | + VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ | |
173 | + *(__cpu_method_of_table) \ | |
174 | + VMLINUX_SYMBOL(__cpu_method_of_table_end) = .; | |
175 | +#else | |
176 | +#define CPU_METHOD_OF_TABLES() | |
177 | +#endif | |
178 | + | |
170 | 179 | #define KERNEL_DTB() \ |
171 | 180 | STRUCT_ALIGN(); \ |
172 | 181 | VMLINUX_SYMBOL(__dtb_start) = .; \ |
... | ... | @@ -491,6 +500,7 @@ |
491 | 500 | MEM_DISCARD(init.rodata) \ |
492 | 501 | CLK_OF_TABLES() \ |
493 | 502 | CLKSRC_OF_TABLES() \ |
503 | + CPU_METHOD_OF_TABLES() \ | |
494 | 504 | KERNEL_DTB() \ |
495 | 505 | IRQCHIP_OF_MATCH_TABLE() |
496 | 506 |