aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/genapic_64.c85
-rw-r--r--arch/x86/kernel/genapic_flat_64.c26
-rw-r--r--arch/x86/kernel/genx2apic_cluster.c11
-rw-r--r--arch/x86/kernel/genx2apic_phys.c21
-rw-r--r--arch/x86/kernel/genx2apic_uv_x.c32
-rw-r--r--include/asm-x86/genapic_64.h1
6 files changed, 116 insertions, 60 deletions
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
index 3940d8161f8..b3ba969c50d 100644
--- a/arch/x86/kernel/genapic_64.c
+++ b/arch/x86/kernel/genapic_64.c
@@ -16,62 +16,37 @@
16#include <linux/ctype.h> 16#include <linux/ctype.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/hardirq.h> 18#include <linux/hardirq.h>
19#include <linux/dmar.h>
20 19
21#include <asm/smp.h> 20#include <asm/smp.h>
22#include <asm/ipi.h> 21#include <asm/ipi.h>
23#include <asm/genapic.h> 22#include <asm/genapic.h>
24 23
25#ifdef CONFIG_ACPI 24extern struct genapic apic_flat;
26#include <acpi/acpi_bus.h> 25extern struct genapic apic_physflat;
27#endif 26extern struct genapic apic_x2xpic_uv_x;
28 27extern struct genapic apic_x2apic_phys;
29DEFINE_PER_CPU(int, x2apic_extra_bits); 28extern struct genapic apic_x2apic_cluster;
30 29
31struct genapic __read_mostly *genapic = &apic_flat; 30struct genapic __read_mostly *genapic = &apic_flat;
32 31
33static int x2apic_phys = 0; 32static struct genapic *apic_probe[] __initdata = {
34 33 &apic_x2apic_uv_x,
35static int set_x2apic_phys_mode(char *arg) 34 &apic_x2apic_phys,
36{ 35 &apic_x2apic_cluster,
37 x2apic_phys = 1; 36 &apic_physflat,
38 return 0; 37 NULL,
39} 38};
40early_param("x2apic_phys", set_x2apic_phys_mode);
41
42static enum uv_system_type uv_system_type;
43 39
44/* 40/*
45 * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. 41 * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
46 */ 42 */
47void __init setup_apic_routing(void) 43void __init setup_apic_routing(void)
48{ 44{
49 if (uv_system_type == UV_NON_UNIQUE_APIC) 45 if (genapic == &apic_flat) {
50 genapic = &apic_x2apic_uv_x; 46 if (max_physical_apicid >= 8)
51 else if (cpu_has_x2apic && intr_remapping_enabled) { 47 genapic = &apic_physflat;
52 if (x2apic_phys) 48 printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
53 genapic = &apic_x2apic_phys; 49 }
54 else
55 genapic = &apic_x2apic_cluster;
56 } else
57#ifdef CONFIG_ACPI
58 /*
59 * Quirk: some x86_64 machines can only use physical APIC mode
60 * regardless of how many processors are present (x86_64 ES7000
61 * is an example).
62 */
63 if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
64 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
65 genapic = &apic_physflat;
66 else
67#endif
68
69 if (max_physical_apicid < 8)
70 genapic = &apic_flat;
71 else
72 genapic = &apic_physflat;
73
74 printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
75} 50}
76 51
77/* Same for both flat and physical. */ 52/* Same for both flat and physical. */
@@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector)
83 58
84int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) 59int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
85{ 60{
86 if (!strcmp(oem_id, "SGI")) { 61 int i;
87 if (!strcmp(oem_table_id, "UVL")) 62
88 uv_system_type = UV_LEGACY_APIC; 63 for (i = 0; apic_probe[i]; ++i) {
89 else if (!strcmp(oem_table_id, "UVX")) 64 if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
90 uv_system_type = UV_X2APIC; 65 genapic = apic_probe[i];
91 else if (!strcmp(oem_table_id, "UVH")) 66 printk(KERN_INFO "Setting APIC routing to %s.\n",
92 uv_system_type = UV_NON_UNIQUE_APIC; 67 genapic->name);
68 return 1;
69 }
93 } 70 }
94 return 0; 71 return 0;
95} 72}
96
97enum uv_system_type get_uv_system_type(void)
98{
99 return uv_system_type;
100}
101
102int is_uv_system(void)
103{
104 return uv_system_type != UV_NONE;
105}
diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
index 2c973cbf054..1740b83329f 100644
--- a/arch/x86/kernel/genapic_flat_64.c
+++ b/arch/x86/kernel/genapic_flat_64.c
@@ -21,6 +21,15 @@
21#include <asm/genapic.h> 21#include <asm/genapic.h>
22#include <mach_apicdef.h> 22#include <mach_apicdef.h>
23 23
24#ifdef CONFIG_ACPI
25#include <acpi/acpi_bus.h>
26#endif
27
28static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
29{
30 return 1;
31}
32
24static cpumask_t flat_target_cpus(void) 33static cpumask_t flat_target_cpus(void)
25{ 34{
26 return cpu_online_map; 35 return cpu_online_map;
@@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb)
138 147
139struct genapic apic_flat = { 148struct genapic apic_flat = {
140 .name = "flat", 149 .name = "flat",
150 .acpi_madt_oem_check = flat_acpi_madt_oem_check,
141 .int_delivery_mode = dest_LowestPrio, 151 .int_delivery_mode = dest_LowestPrio,
142 .int_dest_mode = (APIC_DEST_LOGICAL != 0), 152 .int_dest_mode = (APIC_DEST_LOGICAL != 0),
143 .target_cpus = flat_target_cpus, 153 .target_cpus = flat_target_cpus,
@@ -160,6 +170,21 @@ struct genapic apic_flat = {
160 * We cannot use logical delivery in this case because the mask 170 * We cannot use logical delivery in this case because the mask
161 * overflows, so use physical mode. 171 * overflows, so use physical mode.
162 */ 172 */
173static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
174{
175#ifdef CONFIG_ACPI
176 /*
177 * Quirk: some x86_64 machines can only use physical APIC mode
178 * regardless of how many processors are present (x86_64 ES7000
179 * is an example).
180 */
181 if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
182 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
183 return 1;
184#endif
185
186 return 0;
187}
163 188
164static cpumask_t physflat_target_cpus(void) 189static cpumask_t physflat_target_cpus(void)
165{ 190{
@@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
206 231
207struct genapic apic_physflat = { 232struct genapic apic_physflat = {
208 .name = "physical flat", 233 .name = "physical flat",
234 .acpi_madt_oem_check = physflat_acpi_madt_oem_check,
209 .int_delivery_mode = dest_Fixed, 235 .int_delivery_mode = dest_Fixed,
210 .int_dest_mode = (APIC_DEST_PHYSICAL != 0), 236 .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
211 .target_cpus = physflat_target_cpus, 237 .target_cpus = physflat_target_cpus,
diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c
index 40bc0140d89..ef3f3182d50 100644
--- a/arch/x86/kernel/genx2apic_cluster.c
+++ b/arch/x86/kernel/genx2apic_cluster.c
@@ -4,12 +4,22 @@
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/ctype.h> 5#include <linux/ctype.h>
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/dmar.h>
8
7#include <asm/smp.h> 9#include <asm/smp.h>
8#include <asm/ipi.h> 10#include <asm/ipi.h>
9#include <asm/genapic.h> 11#include <asm/genapic.h>
10 12
11DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); 13DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
12 14
15static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
16{
17 if (cpu_has_x2apic && intr_remapping_enabled)
18 return 1;
19
20 return 0;
21}
22
13/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ 23/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
14 24
15static cpumask_t x2apic_target_cpus(void) 25static cpumask_t x2apic_target_cpus(void)
@@ -135,6 +145,7 @@ static void init_x2apic_ldr(void)
135 145
136struct genapic apic_x2apic_cluster = { 146struct genapic apic_x2apic_cluster = {
137 .name = "cluster x2apic", 147 .name = "cluster x2apic",
148 .acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
138 .int_delivery_mode = dest_LowestPrio, 149 .int_delivery_mode = dest_LowestPrio,
139 .int_dest_mode = (APIC_DEST_LOGICAL != 0), 150 .int_dest_mode = (APIC_DEST_LOGICAL != 0),
140 .target_cpus = x2apic_target_cpus, 151 .target_cpus = x2apic_target_cpus,
diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c
index 2f3c6ca19de..f35a3bf3a9e 100644
--- a/arch/x86/kernel/genx2apic_phys.c
+++ b/arch/x86/kernel/genx2apic_phys.c
@@ -4,10 +4,30 @@
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/ctype.h> 5#include <linux/ctype.h>
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/dmar.h>
8
7#include <asm/smp.h> 9#include <asm/smp.h>
8#include <asm/ipi.h> 10#include <asm/ipi.h>
9#include <asm/genapic.h> 11#include <asm/genapic.h>
10 12
13DEFINE_PER_CPU(int, x2apic_extra_bits);
14
15static int x2apic_phys;
16
17static int set_x2apic_phys_mode(char *arg)
18{
19 x2apic_phys = 1;
20 return 0;
21}
22early_param("x2apic_phys", set_x2apic_phys_mode);
23
24static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
25{
26 if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys)
27 return 1;
28
29 return 0;
30}
11 31
12/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ 32/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
13 33
@@ -122,6 +142,7 @@ void init_x2apic_ldr(void)
122 142
123struct genapic apic_x2apic_phys = { 143struct genapic apic_x2apic_phys = {
124 .name = "physical x2apic", 144 .name = "physical x2apic",
145 .acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
125 .int_delivery_mode = dest_Fixed, 146 .int_delivery_mode = dest_Fixed,
126 .int_dest_mode = (APIC_DEST_PHYSICAL != 0), 147 .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
127 .target_cpus = x2apic_target_cpus, 148 .target_cpus = x2apic_target_cpus,
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
index a8e5cb4c4d4..a882bc3a2ce 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/genx2apic_uv_x.c
@@ -27,6 +27,33 @@
27#include <asm/uv/uv_hub.h> 27#include <asm/uv/uv_hub.h>
28#include <asm/uv/bios.h> 28#include <asm/uv/bios.h>
29 29
30static enum uv_system_type uv_system_type;
31
32static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
33{
34 if (!strcmp(oem_id, "SGI")) {
35 if (!strcmp(oem_table_id, "UVL"))
36 uv_system_type = UV_LEGACY_APIC;
37 else if (!strcmp(oem_table_id, "UVX"))
38 uv_system_type = UV_X2APIC;
39 else if (!strcmp(oem_table_id, "UVH")) {
40 uv_system_type = UV_NON_UNIQUE_APIC;
41 return 1;
42 }
43 }
44 return 0;
45}
46
47enum uv_system_type get_uv_system_type(void)
48{
49 return uv_system_type;
50}
51
52int is_uv_system(void)
53{
54 return uv_system_type != UV_NONE;
55}
56
30DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); 57DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
31EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); 58EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
32 59
@@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x)
153 return id; 180 return id;
154} 181}
155 182
156static long set_apic_id(unsigned int id) 183static unsigned long set_apic_id(unsigned int id)
157{ 184{
158 unsigned long x; 185 unsigned long x;
159 186
@@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector)
182 209
183struct genapic apic_x2apic_uv_x = { 210struct genapic apic_x2apic_uv_x = {
184 .name = "UV large system", 211 .name = "UV large system",
212 .acpi_madt_oem_check = uv_acpi_madt_oem_check,
185 .int_delivery_mode = dest_Fixed, 213 .int_delivery_mode = dest_Fixed,
186 .int_dest_mode = (APIC_DEST_PHYSICAL != 0), 214 .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
187 .target_cpus = uv_target_cpus, 215 .target_cpus = uv_target_cpus,
@@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void)
433 if (get_uv_system_type() == UV_NON_UNIQUE_APIC) 461 if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
434 set_x2apic_extra_bits(uv_hub_info->pnode); 462 set_x2apic_extra_bits(uv_hub_info->pnode);
435} 463}
464
465
diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h
index 2871b3fccb2..1e832e49f54 100644
--- a/include/asm-x86/genapic_64.h
+++ b/include/asm-x86/genapic_64.h
@@ -14,6 +14,7 @@
14 14
15struct genapic { 15struct genapic {
16 char *name; 16 char *name;
17 int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
17 u32 int_delivery_mode; 18 u32 int_delivery_mode;
18 u32 int_dest_mode; 19 u32 int_dest_mode;
19 int (*apic_id_registered)(void); 20 int (*apic_id_registered)(void);