aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/es7000_32.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2008-11-16 06:12:49 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-17 11:57:34 -0500
commit569712b2b0970fa5b19673544d62ae661d04a220 (patch)
tree2bfd507fe1ab746115586d556ec9624d36d16337 /arch/x86/kernel/es7000_32.c
parente14c8bf86350f6c39186a139c5c584a6111b2f01 (diff)
x86: fix wakeup_cpu with numaq/es7000, v2
Impact: fix secondary-CPU wakeup/init path with numaq and es7000 While looking at wakeup_secondary_cpu for WAKE_SECONDARY_VIA_NMI: |#ifdef WAKE_SECONDARY_VIA_NMI |/* | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this | * won't ... remember to clear down the APIC, etc later. | */ |static int __devinit |wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) |{ | unsigned long send_status, accept_status = 0; | int maxlvt; |... | if (APIC_INTEGRATED(apic_version[phys_apicid])) { | maxlvt = lapic_get_maxlvt(); I noticed that there is no warning about undefined phys_apicid... because WAKE_SECONDARY_VIA_NMI and WAKE_SECONDARY_VIA_INIT can not be defined at the same time. So NUMAQ is using wrong wakeup_secondary_cpu. WAKE_SECONDARY_VIA_NMI, WAKE_SECONDARY_VIA_INIT and WAKE_SECONDARY_VIA_MIP are variants of a weird and fragile preprocessor-driven "HAL" mechanisms to specify the kind of secondary-CPU wakeup strategy a given x86 kernel will use. The vast majority of systems want to use INIT for secondary wakeup - NUMAQ uses an NMI, (old-style-) ES7000 uses 'MIP' (a firmware driven in-memory flag to let secondaries continue). So convert these mechanisms to x86_quirks and add a ->wakeup_secondary_cpu() method to specify the rare exception to the sane default. Extend genapic accordingly as well, for 32-bit. While looking further, I noticed that functions in wakecup.h for numaq and es7000 are different to the default in mach_wakecpu.h - but smpboot.c will only use default mach_wakecpu.h with smphook.h. So we need to add mach_wakecpu.h for mach_generic, to properly support numaq and es7000, and vectorize the following SMP init methods: int trampoline_phys_low; int trampoline_phys_high; void (*wait_for_init_deassert)(atomic_t *deassert); void (*smp_callin_clear_local_apic)(void); void (*store_NMI_vector)(unsigned short *high, unsigned short *low); void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); void (*inquire_remote_apic)(int apicid); Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/es7000_32.c')
-rw-r--r--arch/x86/kernel/es7000_32.c44
1 files changed, 24 insertions, 20 deletions
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c
index f454c78fcef6..bed10dddf099 100644
--- a/arch/x86/kernel/es7000_32.c
+++ b/arch/x86/kernel/es7000_32.c
@@ -40,6 +40,7 @@
40#include <asm/smp.h> 40#include <asm/smp.h>
41#include <asm/apicdef.h> 41#include <asm/apicdef.h>
42#include <mach_mpparse.h> 42#include <mach_mpparse.h>
43#include <asm/setup.h>
43 44
44/* 45/*
45 * ES7000 chipsets 46 * ES7000 chipsets
@@ -161,6 +162,26 @@ es7000_rename_gsi(int ioapic, int gsi)
161 return gsi; 162 return gsi;
162} 163}
163 164
165#ifdef CONFIG_ES7000_CLUSTERED_APIC
166static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
167{
168 unsigned long vect = 0, psaival = 0;
169
170 if (psai == NULL)
171 return -1;
172
173 vect = ((unsigned long)__pa(eip)/0x1000) << 16;
174 psaival = (0x1000000 | vect | cpu);
175
176 while (*psai & 0x1000000)
177 ;
178
179 *psai = psaival;
180
181 return 0;
182}
183#endif
184
164void __init 185void __init
165setup_unisys(void) 186setup_unisys(void)
166{ 187{
@@ -176,6 +197,9 @@ setup_unisys(void)
176 else 197 else
177 es7000_plat = ES7000_CLASSIC; 198 es7000_plat = ES7000_CLASSIC;
178 ioapic_renumber_irq = es7000_rename_gsi; 199 ioapic_renumber_irq = es7000_rename_gsi;
200#ifdef CONFIG_ES7000_CLUSTERED_APIC
201 x86_quirks->wakeup_secondary_cpu = wakeup_secondary_cpu_via_mip;
202#endif
179} 203}
180 204
181/* 205/*
@@ -324,26 +348,6 @@ es7000_mip_write(struct mip_reg *mip_reg)
324 return status; 348 return status;
325} 349}
326 350
327int
328es7000_start_cpu(int cpu, unsigned long eip)
329{
330 unsigned long vect = 0, psaival = 0;
331
332 if (psai == NULL)
333 return -1;
334
335 vect = ((unsigned long)__pa(eip)/0x1000) << 16;
336 psaival = (0x1000000 | vect | cpu);
337
338 while (*psai & 0x1000000)
339 ;
340
341 *psai = psaival;
342
343 return 0;
344
345}
346
347void __init 351void __init
348es7000_sw_apic(void) 352es7000_sw_apic(void)
349{ 353{