]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Yinghai Lu <yhlu.kernel@gmail.com> |
2 | Subject: x86: add apic probe for genapic 64bit, v2 | |
3 | References: fate #303948 and fate #303984 | |
4 | Patch-Mainline: queued for .28 | |
5 | Commit-ID: 1b9b89e7f163336ad84200b66a17284dbf26aced | |
6 | ||
7 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
8 | ||
9 | introducing an APIC handling probing abstraction: | |
10 | ||
11 | static struct genapic *apic_probe[] __initdata = { | |
12 | &apic_x2apic_uv_x, | |
13 | &apic_x2apic_phys, | |
14 | &apic_x2apic_cluster, | |
15 | &apic_physflat, | |
16 | NULL, | |
17 | }; | |
18 | ||
19 | This way we can remove UV, x2apic specific code from genapic_64.c and | |
20 | move them to their specific genapic files. | |
21 | ||
22 | [ v2: fix compiling when CONFIG_ACPI is not set ] | |
23 | ||
24 | Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> | |
25 | Cc: Jack Steiner <steiner@sgi.com> | |
26 | Cc: Suresh Siddha <suresh.b.siddha@intel.com> | |
27 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | |
28 | ||
29 | --- | |
30 | arch/x86/kernel/genapic_64.c | 86 ++++++++++-------------------------- | |
31 | arch/x86/kernel/genapic_flat_64.c | 26 ++++++++++ | |
32 | arch/x86/kernel/genx2apic_cluster.c | 11 ++++ | |
33 | arch/x86/kernel/genx2apic_phys.c | 21 ++++++++ | |
34 | arch/x86/kernel/genx2apic_uv_x.c | 33 +++++++++++++ | |
35 | include/asm-x86/genapic_64.h | 1 | |
36 | 6 files changed, 117 insertions(+), 61 deletions(-) | |
37 | ||
38 | Index: linux-2.6.26/arch/x86/kernel/genapic_64.c | |
39 | =================================================================== | |
40 | --- linux-2.6.26.orig/arch/x86/kernel/genapic_64.c | |
41 | +++ linux-2.6.26/arch/x86/kernel/genapic_64.c | |
42 | @@ -16,62 +16,37 @@ | |
43 | #include <linux/ctype.h> | |
44 | #include <linux/init.h> | |
45 | #include <linux/hardirq.h> | |
46 | -#include <linux/dmar.h> | |
47 | ||
48 | #include <asm/smp.h> | |
49 | #include <asm/ipi.h> | |
50 | #include <asm/genapic.h> | |
51 | ||
52 | -#ifdef CONFIG_ACPI | |
53 | -#include <acpi/acpi_bus.h> | |
54 | -#endif | |
55 | - | |
56 | -DEFINE_PER_CPU(int, x2apic_extra_bits); | |
57 | +extern struct genapic apic_flat; | |
58 | +extern struct genapic apic_physflat; | |
59 | +extern struct genapic apic_x2xpic_uv_x; | |
60 | +extern struct genapic apic_x2apic_phys; | |
61 | +extern struct genapic apic_x2apic_cluster; | |
62 | ||
63 | struct genapic __read_mostly *genapic = &apic_flat; | |
64 | ||
65 | -static int x2apic_phys = 0; | |
66 | - | |
67 | -static int set_x2apic_phys_mode(char *arg) | |
68 | -{ | |
69 | - x2apic_phys = 1; | |
70 | - return 0; | |
71 | -} | |
72 | -early_param("x2apic_phys", set_x2apic_phys_mode); | |
73 | - | |
74 | -static enum uv_system_type uv_system_type; | |
75 | +static struct genapic *apic_probe[] __initdata = { | |
76 | + &apic_x2apic_uv_x, | |
77 | + &apic_x2apic_phys, | |
78 | + &apic_x2apic_cluster, | |
79 | + &apic_physflat, | |
80 | + NULL, | |
81 | +}; | |
82 | ||
83 | /* | |
84 | * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. | |
85 | */ | |
86 | void __init setup_apic_routing(void) | |
87 | { | |
88 | - if (uv_system_type == UV_NON_UNIQUE_APIC) | |
89 | - genapic = &apic_x2apic_uv_x; | |
90 | - else if (cpu_has_x2apic && intr_remapping_enabled) { | |
91 | - if (x2apic_phys) | |
92 | - genapic = &apic_x2apic_phys; | |
93 | - else | |
94 | - genapic = &apic_x2apic_cluster; | |
95 | - } else | |
96 | -#ifdef CONFIG_ACPI | |
97 | - /* | |
98 | - * Quirk: some x86_64 machines can only use physical APIC mode | |
99 | - * regardless of how many processors are present (x86_64 ES7000 | |
100 | - * is an example). | |
101 | - */ | |
102 | - if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && | |
103 | - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) | |
104 | - genapic = &apic_physflat; | |
105 | - else | |
106 | -#endif | |
107 | - | |
108 | - if (max_physical_apicid < 8) | |
109 | - genapic = &apic_flat; | |
110 | - else | |
111 | - genapic = &apic_physflat; | |
112 | - | |
113 | - printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); | |
114 | + if (genapic == &apic_flat) { | |
115 | + if (max_physical_apicid >= 8) | |
116 | + genapic = &apic_physflat; | |
117 | + printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); | |
118 | + } | |
119 | } | |
120 | ||
121 | /* Same for both flat and physical. */ | |
122 | @@ -83,24 +58,15 @@ void apic_send_IPI_self(int vector) | |
123 | ||
124 | int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
125 | { | |
126 | - if (!strcmp(oem_id, "SGI")) { | |
127 | - if (!strcmp(oem_table_id, "UVL")) | |
128 | - uv_system_type = UV_LEGACY_APIC; | |
129 | - else if (!strcmp(oem_table_id, "UVX")) | |
130 | - uv_system_type = UV_X2APIC; | |
131 | - else if (!strcmp(oem_table_id, "UVH")) | |
132 | - uv_system_type = UV_NON_UNIQUE_APIC; | |
133 | + int i; | |
134 | + | |
135 | + for (i = 0; apic_probe[i]; ++i) { | |
136 | + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { | |
137 | + genapic = apic_probe[i]; | |
138 | + printk(KERN_INFO "Setting APIC routing to %s.\n", | |
139 | + genapic->name); | |
140 | + return 1; | |
141 | + } | |
142 | } | |
143 | return 0; | |
144 | } | |
145 | - | |
146 | -enum uv_system_type get_uv_system_type(void) | |
147 | -{ | |
148 | - return uv_system_type; | |
149 | -} | |
150 | - | |
151 | -int is_uv_system(void) | |
152 | -{ | |
153 | - return uv_system_type != UV_NONE; | |
154 | -} | |
155 | -EXPORT_SYMBOL_GPL(is_uv_system); | |
156 | Index: linux-2.6.26/arch/x86/kernel/genapic_flat_64.c | |
157 | =================================================================== | |
158 | --- linux-2.6.26.orig/arch/x86/kernel/genapic_flat_64.c | |
159 | +++ linux-2.6.26/arch/x86/kernel/genapic_flat_64.c | |
160 | @@ -21,6 +21,15 @@ | |
161 | #include <asm/genapic.h> | |
162 | #include <mach_apicdef.h> | |
163 | ||
164 | +#ifdef CONFIG_ACPI | |
165 | +#include <acpi/acpi_bus.h> | |
166 | +#endif | |
167 | + | |
168 | +static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
169 | +{ | |
170 | + return 1; | |
171 | +} | |
172 | + | |
173 | static cpumask_t flat_target_cpus(void) | |
174 | { | |
175 | return cpu_online_map; | |
176 | @@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int inde | |
177 | ||
178 | struct genapic apic_flat = { | |
179 | .name = "flat", | |
180 | + .acpi_madt_oem_check = flat_acpi_madt_oem_check, | |
181 | .int_delivery_mode = dest_LowestPrio, | |
182 | .int_dest_mode = (APIC_DEST_LOGICAL != 0), | |
183 | .target_cpus = flat_target_cpus, | |
184 | @@ -160,6 +170,21 @@ struct genapic apic_flat = { | |
185 | * We cannot use logical delivery in this case because the mask | |
186 | * overflows, so use physical mode. | |
187 | */ | |
188 | +static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
189 | +{ | |
190 | +#ifdef CONFIG_ACPI | |
191 | + /* | |
192 | + * Quirk: some x86_64 machines can only use physical APIC mode | |
193 | + * regardless of how many processors are present (x86_64 ES7000 | |
194 | + * is an example). | |
195 | + */ | |
196 | + if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID && | |
197 | + (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) | |
198 | + return 1; | |
199 | +#endif | |
200 | + | |
201 | + return 0; | |
202 | +} | |
203 | ||
204 | static cpumask_t physflat_target_cpus(void) | |
205 | { | |
206 | @@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to | |
207 | ||
208 | struct genapic apic_physflat = { | |
209 | .name = "physical flat", | |
210 | + .acpi_madt_oem_check = physflat_acpi_madt_oem_check, | |
211 | .int_delivery_mode = dest_Fixed, | |
212 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), | |
213 | .target_cpus = physflat_target_cpus, | |
214 | Index: linux-2.6.26/arch/x86/kernel/genx2apic_cluster.c | |
215 | =================================================================== | |
216 | --- linux-2.6.26.orig/arch/x86/kernel/genx2apic_cluster.c | |
217 | +++ linux-2.6.26/arch/x86/kernel/genx2apic_cluster.c | |
218 | @@ -4,12 +4,22 @@ | |
219 | #include <linux/kernel.h> | |
220 | #include <linux/ctype.h> | |
221 | #include <linux/init.h> | |
222 | +#include <linux/dmar.h> | |
223 | + | |
224 | #include <asm/smp.h> | |
225 | #include <asm/ipi.h> | |
226 | #include <asm/genapic.h> | |
227 | ||
228 | DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); | |
229 | ||
230 | +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
231 | +{ | |
232 | + if (cpu_has_x2apic && intr_remapping_enabled) | |
233 | + return 1; | |
234 | + | |
235 | + return 0; | |
236 | +} | |
237 | + | |
238 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ | |
239 | ||
240 | static cpumask_t x2apic_target_cpus(void) | |
241 | @@ -135,6 +145,7 @@ static void init_x2apic_ldr(void) | |
242 | ||
243 | struct genapic apic_x2apic_cluster = { | |
244 | .name = "cluster x2apic", | |
245 | + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, | |
246 | .int_delivery_mode = dest_LowestPrio, | |
247 | .int_dest_mode = (APIC_DEST_LOGICAL != 0), | |
248 | .target_cpus = x2apic_target_cpus, | |
249 | Index: linux-2.6.26/arch/x86/kernel/genx2apic_phys.c | |
250 | =================================================================== | |
251 | --- linux-2.6.26.orig/arch/x86/kernel/genx2apic_phys.c | |
252 | +++ linux-2.6.26/arch/x86/kernel/genx2apic_phys.c | |
253 | @@ -4,10 +4,30 @@ | |
254 | #include <linux/kernel.h> | |
255 | #include <linux/ctype.h> | |
256 | #include <linux/init.h> | |
257 | +#include <linux/dmar.h> | |
258 | + | |
259 | #include <asm/smp.h> | |
260 | #include <asm/ipi.h> | |
261 | #include <asm/genapic.h> | |
262 | ||
263 | +DEFINE_PER_CPU(int, x2apic_extra_bits); | |
264 | + | |
265 | +static int x2apic_phys; | |
266 | + | |
267 | +static int set_x2apic_phys_mode(char *arg) | |
268 | +{ | |
269 | + x2apic_phys = 1; | |
270 | + return 0; | |
271 | +} | |
272 | +early_param("x2apic_phys", set_x2apic_phys_mode); | |
273 | + | |
274 | +static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
275 | +{ | |
276 | + if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys) | |
277 | + return 1; | |
278 | + | |
279 | + return 0; | |
280 | +} | |
281 | ||
282 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ | |
283 | ||
284 | @@ -122,6 +142,7 @@ void init_x2apic_ldr(void) | |
285 | ||
286 | struct genapic apic_x2apic_phys = { | |
287 | .name = "physical x2apic", | |
288 | + .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, | |
289 | .int_delivery_mode = dest_Fixed, | |
290 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), | |
291 | .target_cpus = x2apic_target_cpus, | |
292 | Index: linux-2.6.26/arch/x86/kernel/genx2apic_uv_x.c | |
293 | =================================================================== | |
294 | --- linux-2.6.26.orig/arch/x86/kernel/genx2apic_uv_x.c | |
295 | +++ linux-2.6.26/arch/x86/kernel/genx2apic_uv_x.c | |
296 | @@ -27,6 +27,34 @@ | |
297 | #include <asm/uv/uv_hub.h> | |
298 | #include <asm/uv/bios.h> | |
299 | ||
300 | +static enum uv_system_type uv_system_type; | |
301 | + | |
302 | +static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |
303 | +{ | |
304 | + if (!strcmp(oem_id, "SGI")) { | |
305 | + if (!strcmp(oem_table_id, "UVL")) | |
306 | + uv_system_type = UV_LEGACY_APIC; | |
307 | + else if (!strcmp(oem_table_id, "UVX")) | |
308 | + uv_system_type = UV_X2APIC; | |
309 | + else if (!strcmp(oem_table_id, "UVH")) { | |
310 | + uv_system_type = UV_NON_UNIQUE_APIC; | |
311 | + return 1; | |
312 | + } | |
313 | + } | |
314 | + return 0; | |
315 | +} | |
316 | + | |
317 | +enum uv_system_type get_uv_system_type(void) | |
318 | +{ | |
319 | + return uv_system_type; | |
320 | +} | |
321 | + | |
322 | +int is_uv_system(void) | |
323 | +{ | |
324 | + return uv_system_type != UV_NONE; | |
325 | +} | |
326 | +EXPORT_SYMBOL(is_uv_system); | |
327 | + | |
328 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | |
329 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); | |
330 | ||
331 | @@ -153,7 +181,7 @@ static unsigned int get_apic_id(unsigned | |
332 | return id; | |
333 | } | |
334 | ||
335 | -static long set_apic_id(unsigned int id) | |
336 | +static unsigned long set_apic_id(unsigned int id) | |
337 | { | |
338 | unsigned long x; | |
339 | ||
340 | @@ -182,6 +210,7 @@ static void uv_send_IPI_self(int vector) | |
341 | ||
342 | struct genapic apic_x2apic_uv_x = { | |
343 | .name = "UV large system", | |
344 | + .acpi_madt_oem_check = uv_acpi_madt_oem_check, | |
345 | .int_delivery_mode = dest_Fixed, | |
346 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), | |
347 | .target_cpus = uv_target_cpus, | |
348 | @@ -435,3 +464,5 @@ void __cpuinit uv_cpu_init(void) | |
349 | if (get_uv_system_type() == UV_NON_UNIQUE_APIC) | |
350 | set_x2apic_extra_bits(uv_hub_info->pnode); | |
351 | } | |
352 | + | |
353 | + | |
354 | Index: linux-2.6.26/include/asm-x86/genapic_64.h | |
355 | =================================================================== | |
356 | --- linux-2.6.26.orig/include/asm-x86/genapic_64.h | |
357 | +++ linux-2.6.26/include/asm-x86/genapic_64.h | |
358 | @@ -14,6 +14,7 @@ | |
359 | ||
360 | struct genapic { | |
361 | char *name; | |
362 | + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); | |
363 | u32 int_delivery_mode; | |
364 | u32 int_dest_mode; | |
365 | int (*apic_id_registered)(void); |