diff options
author | Yinghai Lu <yinghai@kernel.org> | 2008-11-16 06:12:49 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-17 11:57:34 -0500 |
commit | 569712b2b0970fa5b19673544d62ae661d04a220 (patch) | |
tree | 2bfd507fe1ab746115586d556ec9624d36d16337 /arch/x86 | |
parent | e14c8bf86350f6c39186a139c5c584a6111b2f01 (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')
-rw-r--r-- | arch/x86/include/asm/bigsmp/apic.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/es7000/apic.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/es7000/wakecpu.h | 41 | ||||
-rw-r--r-- | arch/x86/include/asm/genapic_32.h | 17 | ||||
-rw-r--r-- | arch/x86/include/asm/mach-default/mach_wakecpu.h | 24 | ||||
-rw-r--r-- | arch/x86/include/asm/mach-default/smpboot_hooks.h | 8 | ||||
-rw-r--r-- | arch/x86/include/asm/mach-generic/mach_wakecpu.h | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/numaq/wakecpu.h | 24 | ||||
-rw-r--r-- | arch/x86/include/asm/setup.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/es7000_32.c | 44 | ||||
-rw-r--r-- | arch/x86/kernel/numaq_32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 24 | ||||
-rw-r--r-- | arch/x86/mach-generic/bigsmp.c | 1 | ||||
-rw-r--r-- | arch/x86/mach-generic/default.c | 1 | ||||
-rw-r--r-- | arch/x86/mach-generic/summit.c | 1 |
15 files changed, 110 insertions, 95 deletions
diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h index 1d9543b9d358..ce547f24a1cd 100644 --- a/arch/x86/include/asm/bigsmp/apic.h +++ b/arch/x86/include/asm/bigsmp/apic.h | |||
@@ -24,8 +24,6 @@ static inline cpumask_t target_cpus(void) | |||
24 | #define INT_DELIVERY_MODE (dest_Fixed) | 24 | #define INT_DELIVERY_MODE (dest_Fixed) |
25 | #define INT_DEST_MODE (0) /* phys delivery to target proc */ | 25 | #define INT_DEST_MODE (0) /* phys delivery to target proc */ |
26 | #define NO_BALANCE_IRQ (0) | 26 | #define NO_BALANCE_IRQ (0) |
27 | #define WAKE_SECONDARY_VIA_INIT | ||
28 | |||
29 | 27 | ||
30 | static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) | 28 | static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) |
31 | { | 29 | { |
diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h index 380f0b4f17ed..9d8cf776c285 100644 --- a/arch/x86/include/asm/es7000/apic.h +++ b/arch/x86/include/asm/es7000/apic.h | |||
@@ -23,8 +23,6 @@ static inline cpumask_t target_cpus(void) | |||
23 | #define INT_DELIVERY_MODE (dest_LowestPrio) | 23 | #define INT_DELIVERY_MODE (dest_LowestPrio) |
24 | #define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */ | 24 | #define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */ |
25 | #define NO_BALANCE_IRQ (1) | 25 | #define NO_BALANCE_IRQ (1) |
26 | #undef WAKE_SECONDARY_VIA_INIT | ||
27 | #define WAKE_SECONDARY_VIA_MIP | ||
28 | #else | 26 | #else |
29 | #define APIC_DFR_VALUE (APIC_DFR_FLAT) | 27 | #define APIC_DFR_VALUE (APIC_DFR_FLAT) |
30 | #define INT_DELIVERY_MODE (dest_Fixed) | 28 | #define INT_DELIVERY_MODE (dest_Fixed) |
@@ -32,7 +30,6 @@ static inline cpumask_t target_cpus(void) | |||
32 | #define NO_BALANCE_IRQ (0) | 30 | #define NO_BALANCE_IRQ (0) |
33 | #undef APIC_DEST_LOGICAL | 31 | #undef APIC_DEST_LOGICAL |
34 | #define APIC_DEST_LOGICAL 0x0 | 32 | #define APIC_DEST_LOGICAL 0x0 |
35 | #define WAKE_SECONDARY_VIA_INIT | ||
36 | #endif | 33 | #endif |
37 | 34 | ||
38 | static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) | 35 | static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) |
diff --git a/arch/x86/include/asm/es7000/wakecpu.h b/arch/x86/include/asm/es7000/wakecpu.h index 398493461913..78f0daaee436 100644 --- a/arch/x86/include/asm/es7000/wakecpu.h +++ b/arch/x86/include/asm/es7000/wakecpu.h | |||
@@ -1,36 +1,12 @@ | |||
1 | #ifndef __ASM_ES7000_WAKECPU_H | 1 | #ifndef __ASM_ES7000_WAKECPU_H |
2 | #define __ASM_ES7000_WAKECPU_H | 2 | #define __ASM_ES7000_WAKECPU_H |
3 | 3 | ||
4 | /* | 4 | #define TRAMPOLINE_PHYS_LOW 0x467 |
5 | * This file copes with machines that wakeup secondary CPUs by the | 5 | #define TRAMPOLINE_PHYS_HIGH 0x469 |
6 | * INIT, INIT, STARTUP sequence. | ||
7 | */ | ||
8 | |||
9 | #ifdef CONFIG_ES7000_CLUSTERED_APIC | ||
10 | #define WAKE_SECONDARY_VIA_MIP | ||
11 | #else | ||
12 | #define WAKE_SECONDARY_VIA_INIT | ||
13 | #endif | ||
14 | |||
15 | #ifdef WAKE_SECONDARY_VIA_MIP | ||
16 | extern int es7000_start_cpu(int cpu, unsigned long eip); | ||
17 | static inline int | ||
18 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | ||
19 | { | ||
20 | int boot_error = 0; | ||
21 | boot_error = es7000_start_cpu(phys_apicid, start_eip); | ||
22 | return boot_error; | ||
23 | } | ||
24 | #endif | ||
25 | |||
26 | #define TRAMPOLINE_LOW phys_to_virt(0x467) | ||
27 | #define TRAMPOLINE_HIGH phys_to_virt(0x469) | ||
28 | |||
29 | #define boot_cpu_apicid boot_cpu_physical_apicid | ||
30 | 6 | ||
31 | static inline void wait_for_init_deassert(atomic_t *deassert) | 7 | static inline void wait_for_init_deassert(atomic_t *deassert) |
32 | { | 8 | { |
33 | #ifdef WAKE_SECONDARY_VIA_INIT | 9 | #ifndef CONFIG_ES7000_CLUSTERED_APIC |
34 | while (!atomic_read(deassert)) | 10 | while (!atomic_read(deassert)) |
35 | cpu_relax(); | 11 | cpu_relax(); |
36 | #endif | 12 | #endif |
@@ -50,9 +26,12 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) | |||
50 | { | 26 | { |
51 | } | 27 | } |
52 | 28 | ||
53 | #define inquire_remote_apic(apicid) do { \ | 29 | extern void __inquire_remote_apic(int apicid); |
54 | if (apic_verbosity >= APIC_DEBUG) \ | 30 | |
55 | __inquire_remote_apic(apicid); \ | 31 | static inline void inquire_remote_apic(int apicid) |
56 | } while (0) | 32 | { |
33 | if (apic_verbosity >= APIC_DEBUG) | ||
34 | __inquire_remote_apic(apicid); | ||
35 | } | ||
57 | 36 | ||
58 | #endif /* __ASM_MACH_WAKECPU_H */ | 37 | #endif /* __ASM_MACH_WAKECPU_H */ |
diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 5cbd4fcc06fd..39bd8c1db3f5 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _ASM_X86_GENAPIC_32_H | 2 | #define _ASM_X86_GENAPIC_32_H |
3 | 3 | ||
4 | #include <asm/mpspec.h> | 4 | #include <asm/mpspec.h> |
5 | #include <asm/atomic.h> | ||
5 | 6 | ||
6 | /* | 7 | /* |
7 | * Generic APIC driver interface. | 8 | * Generic APIC driver interface. |
@@ -65,6 +66,13 @@ struct genapic { | |||
65 | void (*send_IPI_allbutself)(int vector); | 66 | void (*send_IPI_allbutself)(int vector); |
66 | void (*send_IPI_all)(int vector); | 67 | void (*send_IPI_all)(int vector); |
67 | #endif | 68 | #endif |
69 | int trampoline_phys_low; | ||
70 | int trampoline_phys_high; | ||
71 | void (*wait_for_init_deassert)(atomic_t *deassert); | ||
72 | void (*smp_callin_clear_local_apic)(void); | ||
73 | void (*store_NMI_vector)(unsigned short *high, unsigned short *low); | ||
74 | void (*restore_NMI_vector)(unsigned short *high, unsigned short *low); | ||
75 | void (*inquire_remote_apic)(int apicid); | ||
68 | }; | 76 | }; |
69 | 77 | ||
70 | #define APICFUNC(x) .x = x, | 78 | #define APICFUNC(x) .x = x, |
@@ -105,13 +113,20 @@ struct genapic { | |||
105 | APICFUNC(get_apic_id) \ | 113 | APICFUNC(get_apic_id) \ |
106 | .apic_id_mask = APIC_ID_MASK, \ | 114 | .apic_id_mask = APIC_ID_MASK, \ |
107 | APICFUNC(cpu_mask_to_apicid) \ | 115 | APICFUNC(cpu_mask_to_apicid) \ |
108 | APICFUNC(vector_allocation_domain) \ | 116 | APICFUNC(vector_allocation_domain) \ |
109 | APICFUNC(acpi_madt_oem_check) \ | 117 | APICFUNC(acpi_madt_oem_check) \ |
110 | IPIFUNC(send_IPI_mask) \ | 118 | IPIFUNC(send_IPI_mask) \ |
111 | IPIFUNC(send_IPI_allbutself) \ | 119 | IPIFUNC(send_IPI_allbutself) \ |
112 | IPIFUNC(send_IPI_all) \ | 120 | IPIFUNC(send_IPI_all) \ |
113 | APICFUNC(enable_apic_mode) \ | 121 | APICFUNC(enable_apic_mode) \ |
114 | APICFUNC(phys_pkg_id) \ | 122 | APICFUNC(phys_pkg_id) \ |
123 | .trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \ | ||
124 | .trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \ | ||
125 | APICFUNC(wait_for_init_deassert) \ | ||
126 | APICFUNC(smp_callin_clear_local_apic) \ | ||
127 | APICFUNC(store_NMI_vector) \ | ||
128 | APICFUNC(restore_NMI_vector) \ | ||
129 | APICFUNC(inquire_remote_apic) \ | ||
115 | } | 130 | } |
116 | 131 | ||
117 | extern struct genapic *genapic; | 132 | extern struct genapic *genapic; |
diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h index 9d80db91e992..ceb013660146 100644 --- a/arch/x86/include/asm/mach-default/mach_wakecpu.h +++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h | |||
@@ -1,17 +1,8 @@ | |||
1 | #ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H | 1 | #ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H |
2 | #define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H | 2 | #define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H |
3 | 3 | ||
4 | /* | 4 | #define TRAMPOLINE_PHYS_LOW (0x467) |
5 | * This file copes with machines that wakeup secondary CPUs by the | 5 | #define TRAMPOLINE_PHYS_HIGH (0x469) |
6 | * INIT, INIT, STARTUP sequence. | ||
7 | */ | ||
8 | |||
9 | #define WAKE_SECONDARY_VIA_INIT | ||
10 | |||
11 | #define TRAMPOLINE_LOW phys_to_virt(0x467) | ||
12 | #define TRAMPOLINE_HIGH phys_to_virt(0x469) | ||
13 | |||
14 | #define boot_cpu_apicid boot_cpu_physical_apicid | ||
15 | 6 | ||
16 | static inline void wait_for_init_deassert(atomic_t *deassert) | 7 | static inline void wait_for_init_deassert(atomic_t *deassert) |
17 | { | 8 | { |
@@ -33,9 +24,12 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) | |||
33 | { | 24 | { |
34 | } | 25 | } |
35 | 26 | ||
36 | #define inquire_remote_apic(apicid) do { \ | 27 | extern void __inquire_remote_apic(int apicid); |
37 | if (apic_verbosity >= APIC_DEBUG) \ | 28 | |
38 | __inquire_remote_apic(apicid); \ | 29 | static inline void inquire_remote_apic(int apicid) |
39 | } while (0) | 30 | { |
31 | if (apic_verbosity >= APIC_DEBUG) | ||
32 | __inquire_remote_apic(apicid); | ||
33 | } | ||
40 | 34 | ||
41 | #endif /* _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H */ | 35 | #endif /* _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H */ |
diff --git a/arch/x86/include/asm/mach-default/smpboot_hooks.h b/arch/x86/include/asm/mach-default/smpboot_hooks.h index dbab36d64d48..23bf52103b89 100644 --- a/arch/x86/include/asm/mach-default/smpboot_hooks.h +++ b/arch/x86/include/asm/mach-default/smpboot_hooks.h | |||
@@ -13,9 +13,11 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip) | |||
13 | CMOS_WRITE(0xa, 0xf); | 13 | CMOS_WRITE(0xa, 0xf); |
14 | local_flush_tlb(); | 14 | local_flush_tlb(); |
15 | pr_debug("1.\n"); | 15 | pr_debug("1.\n"); |
16 | *((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4; | 16 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = |
17 | start_eip >> 4; | ||
17 | pr_debug("2.\n"); | 18 | pr_debug("2.\n"); |
18 | *((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf; | 19 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = |
20 | start_eip & 0xf; | ||
19 | pr_debug("3.\n"); | 21 | pr_debug("3.\n"); |
20 | } | 22 | } |
21 | 23 | ||
@@ -32,7 +34,7 @@ static inline void smpboot_restore_warm_reset_vector(void) | |||
32 | */ | 34 | */ |
33 | CMOS_WRITE(0, 0xf); | 35 | CMOS_WRITE(0, 0xf); |
34 | 36 | ||
35 | *((volatile long *) phys_to_virt(0x467)) = 0; | 37 | *((volatile long *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0; |
36 | } | 38 | } |
37 | 39 | ||
38 | static inline void __init smpboot_setup_io_apic(void) | 40 | static inline void __init smpboot_setup_io_apic(void) |
diff --git a/arch/x86/include/asm/mach-generic/mach_wakecpu.h b/arch/x86/include/asm/mach-generic/mach_wakecpu.h new file mode 100644 index 000000000000..1ab16b168c8a --- /dev/null +++ b/arch/x86/include/asm/mach-generic/mach_wakecpu.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H | ||
2 | #define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H | ||
3 | |||
4 | #define TRAMPOLINE_PHYS_LOW (genapic->trampoline_phys_low) | ||
5 | #define TRAMPOLINE_PHYS_HIGH (genapic->trampoline_phys_high) | ||
6 | #define wait_for_init_deassert (genapic->wait_for_init_deassert) | ||
7 | #define smp_callin_clear_local_apic (genapic->smp_callin_clear_local_apic) | ||
8 | #define store_NMI_vector (genapic->store_NMI_vector) | ||
9 | #define restore_NMI_vector (genapic->restore_NMI_vector) | ||
10 | #define inquire_remote_apic (genapic->inquire_remote_apic) | ||
11 | |||
12 | #endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */ | ||
diff --git a/arch/x86/include/asm/numaq/wakecpu.h b/arch/x86/include/asm/numaq/wakecpu.h index c577bda5b1c5..6f499df8eddb 100644 --- a/arch/x86/include/asm/numaq/wakecpu.h +++ b/arch/x86/include/asm/numaq/wakecpu.h | |||
@@ -3,12 +3,8 @@ | |||
3 | 3 | ||
4 | /* This file copes with machines that wakeup secondary CPUs by NMIs */ | 4 | /* This file copes with machines that wakeup secondary CPUs by NMIs */ |
5 | 5 | ||
6 | #define WAKE_SECONDARY_VIA_NMI | 6 | #define TRAMPOLINE_PHYS_LOW (0x8) |
7 | 7 | #define TRAMPOLINE_PHYS_HIGH (0xa) | |
8 | #define TRAMPOLINE_LOW phys_to_virt(0x8) | ||
9 | #define TRAMPOLINE_HIGH phys_to_virt(0xa) | ||
10 | |||
11 | #define boot_cpu_apicid boot_cpu_logical_apicid | ||
12 | 8 | ||
13 | /* We don't do anything here because we use NMI's to boot instead */ | 9 | /* We don't do anything here because we use NMI's to boot instead */ |
14 | static inline void wait_for_init_deassert(atomic_t *deassert) | 10 | static inline void wait_for_init_deassert(atomic_t *deassert) |
@@ -27,17 +23,23 @@ static inline void smp_callin_clear_local_apic(void) | |||
27 | static inline void store_NMI_vector(unsigned short *high, unsigned short *low) | 23 | static inline void store_NMI_vector(unsigned short *high, unsigned short *low) |
28 | { | 24 | { |
29 | printk("Storing NMI vector\n"); | 25 | printk("Storing NMI vector\n"); |
30 | *high = *((volatile unsigned short *) TRAMPOLINE_HIGH); | 26 | *high = |
31 | *low = *((volatile unsigned short *) TRAMPOLINE_LOW); | 27 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)); |
28 | *low = | ||
29 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)); | ||
32 | } | 30 | } |
33 | 31 | ||
34 | static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) | 32 | static inline void restore_NMI_vector(unsigned short *high, unsigned short *low) |
35 | { | 33 | { |
36 | printk("Restoring NMI vector\n"); | 34 | printk("Restoring NMI vector\n"); |
37 | *((volatile unsigned short *) TRAMPOLINE_HIGH) = *high; | 35 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = |
38 | *((volatile unsigned short *) TRAMPOLINE_LOW) = *low; | 36 | *high; |
37 | *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = | ||
38 | *low; | ||
39 | } | 39 | } |
40 | 40 | ||
41 | #define inquire_remote_apic(apicid) {} | 41 | static inline void inquire_remote_apic(int apicid) |
42 | { | ||
43 | } | ||
42 | 44 | ||
43 | #endif /* __ASM_NUMAQ_WAKECPU_H */ | 45 | #endif /* __ASM_NUMAQ_WAKECPU_H */ |
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index f12d37237465..40b2d3304911 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -16,6 +16,7 @@ static inline void visws_early_detect(void) { } | |||
16 | static inline int is_visws_box(void) { return 0; } | 16 | static inline int is_visws_box(void) { return 0; } |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); | ||
19 | /* | 20 | /* |
20 | * Any setup quirks to be performed? | 21 | * Any setup quirks to be performed? |
21 | */ | 22 | */ |
@@ -39,6 +40,7 @@ struct x86_quirks { | |||
39 | void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable, | 40 | void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable, |
40 | unsigned short oemsize); | 41 | unsigned short oemsize); |
41 | int (*setup_ioapic_ids)(void); | 42 | int (*setup_ioapic_ids)(void); |
43 | int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip); | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | extern struct x86_quirks *x86_quirks; | 46 | extern struct x86_quirks *x86_quirks; |
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 | ||
166 | static 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 | |||
164 | void __init | 185 | void __init |
165 | setup_unisys(void) | 186 | setup_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 | ||
327 | int | ||
328 | es7000_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 | |||
347 | void __init | 351 | void __init |
348 | es7000_sw_apic(void) | 352 | es7000_sw_apic(void) |
349 | { | 353 | { |
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c index 4caff39078e0..745891b7d0fb 100644 --- a/arch/x86/kernel/numaq_32.c +++ b/arch/x86/kernel/numaq_32.c | |||
@@ -250,6 +250,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = { | |||
250 | .mpc_oem_pci_bus = mpc_oem_pci_bus, | 250 | .mpc_oem_pci_bus = mpc_oem_pci_bus, |
251 | .smp_read_mpc_oem = smp_read_mpc_oem, | 251 | .smp_read_mpc_oem = smp_read_mpc_oem, |
252 | .setup_ioapic_ids = numaq_setup_ioapic_ids, | 252 | .setup_ioapic_ids = numaq_setup_ioapic_ids, |
253 | .wakeup_secondary_cpu = wakeup_secondary_cpu_via_nmi, | ||
253 | }; | 254 | }; |
254 | 255 | ||
255 | void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, | 256 | void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem, |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7b1093397319..498c1ef37fe0 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <asm/mtrr.h> | 62 | #include <asm/mtrr.h> |
63 | #include <asm/vmi.h> | 63 | #include <asm/vmi.h> |
64 | #include <asm/genapic.h> | 64 | #include <asm/genapic.h> |
65 | #include <asm/setup.h> | ||
65 | #include <linux/mc146818rtc.h> | 66 | #include <linux/mc146818rtc.h> |
66 | 67 | ||
67 | #include <mach_apic.h> | 68 | #include <mach_apic.h> |
@@ -536,7 +537,7 @@ static void impress_friends(void) | |||
536 | pr_debug("Before bogocount - setting activated=1.\n"); | 537 | pr_debug("Before bogocount - setting activated=1.\n"); |
537 | } | 538 | } |
538 | 539 | ||
539 | static inline void __inquire_remote_apic(int apicid) | 540 | void __inquire_remote_apic(int apicid) |
540 | { | 541 | { |
541 | unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; | 542 | unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; |
542 | char *names[] = { "ID", "VERSION", "SPIV" }; | 543 | char *names[] = { "ID", "VERSION", "SPIV" }; |
@@ -575,14 +576,13 @@ static inline void __inquire_remote_apic(int apicid) | |||
575 | } | 576 | } |
576 | } | 577 | } |
577 | 578 | ||
578 | #ifdef WAKE_SECONDARY_VIA_NMI | ||
579 | /* | 579 | /* |
580 | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal | 580 | * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal |
581 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this | 581 | * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this |
582 | * won't ... remember to clear down the APIC, etc later. | 582 | * won't ... remember to clear down the APIC, etc later. |
583 | */ | 583 | */ |
584 | static int __devinit | 584 | int __devinit |
585 | wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | 585 | wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) |
586 | { | 586 | { |
587 | unsigned long send_status, accept_status = 0; | 587 | unsigned long send_status, accept_status = 0; |
588 | int maxlvt; | 588 | int maxlvt; |
@@ -599,7 +599,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | |||
599 | * Give the other CPU some time to accept the IPI. | 599 | * Give the other CPU some time to accept the IPI. |
600 | */ | 600 | */ |
601 | udelay(200); | 601 | udelay(200); |
602 | if (APIC_INTEGRATED(apic_version[phys_apicid])) { | 602 | if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { |
603 | maxlvt = lapic_get_maxlvt(); | 603 | maxlvt = lapic_get_maxlvt(); |
604 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ | 604 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ |
605 | apic_write(APIC_ESR, 0); | 605 | apic_write(APIC_ESR, 0); |
@@ -614,11 +614,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | |||
614 | 614 | ||
615 | return (send_status | accept_status); | 615 | return (send_status | accept_status); |
616 | } | 616 | } |
617 | #endif /* WAKE_SECONDARY_VIA_NMI */ | ||
618 | 617 | ||
619 | #ifdef WAKE_SECONDARY_VIA_INIT | ||
620 | static int __devinit | 618 | static int __devinit |
621 | wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | 619 | wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) |
622 | { | 620 | { |
623 | unsigned long send_status, accept_status = 0; | 621 | unsigned long send_status, accept_status = 0; |
624 | int maxlvt, num_starts, j; | 622 | int maxlvt, num_starts, j; |
@@ -737,7 +735,15 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) | |||
737 | 735 | ||
738 | return (send_status | accept_status); | 736 | return (send_status | accept_status); |
739 | } | 737 | } |
740 | #endif /* WAKE_SECONDARY_VIA_INIT */ | 738 | |
739 | static int __devinit | ||
740 | wakeup_secondary_cpu(int apicid, unsigned long start_eip) | ||
741 | { | ||
742 | if (x86_quirks->wakeup_secondary_cpu) | ||
743 | return x86_quirks->wakeup_secondary_cpu(apicid, start_eip); | ||
744 | |||
745 | return wakeup_secondary_cpu_via_init(apicid, start_eip); | ||
746 | } | ||
741 | 747 | ||
742 | struct create_idle { | 748 | struct create_idle { |
743 | struct work_struct work; | 749 | struct work_struct work; |
diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c index 3c3b471ea496..3624a364b7f3 100644 --- a/arch/x86/mach-generic/bigsmp.c +++ b/arch/x86/mach-generic/bigsmp.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/bigsmp/apic.h> | 17 | #include <asm/bigsmp/apic.h> |
18 | #include <asm/bigsmp/ipi.h> | 18 | #include <asm/bigsmp/ipi.h> |
19 | #include <asm/mach-default/mach_mpparse.h> | 19 | #include <asm/mach-default/mach_mpparse.h> |
20 | #include <asm/mach-default/mach_wakecpu.h> | ||
20 | 21 | ||
21 | static int dmi_bigsmp; /* can be set by dmi scanners */ | 22 | static int dmi_bigsmp; /* can be set by dmi scanners */ |
22 | 23 | ||
diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c index 9e835a11a13a..e63a4a76d8cd 100644 --- a/arch/x86/mach-generic/default.c +++ b/arch/x86/mach-generic/default.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/mach-default/mach_apic.h> | 16 | #include <asm/mach-default/mach_apic.h> |
17 | #include <asm/mach-default/mach_ipi.h> | 17 | #include <asm/mach-default/mach_ipi.h> |
18 | #include <asm/mach-default/mach_mpparse.h> | 18 | #include <asm/mach-default/mach_mpparse.h> |
19 | #include <asm/mach-default/mach_wakecpu.h> | ||
19 | 20 | ||
20 | /* should be called last. */ | 21 | /* should be called last. */ |
21 | static int probe_default(void) | 22 | static int probe_default(void) |
diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c index 6272b5e69da6..2c6d234e0009 100644 --- a/arch/x86/mach-generic/summit.c +++ b/arch/x86/mach-generic/summit.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/summit/apic.h> | 16 | #include <asm/summit/apic.h> |
17 | #include <asm/summit/ipi.h> | 17 | #include <asm/summit/ipi.h> |
18 | #include <asm/summit/mpparse.h> | 18 | #include <asm/summit/mpparse.h> |
19 | #include <asm/mach-default/mach_wakecpu.h> | ||
19 | 20 | ||
20 | static int probe_summit(void) | 21 | static int probe_summit(void) |
21 | { | 22 | { |