diff options
-rw-r--r-- | arch/x86/kernel/genapic_64.c | 85 | ||||
-rw-r--r-- | arch/x86/kernel/genapic_flat_64.c | 26 | ||||
-rw-r--r-- | arch/x86/kernel/genx2apic_cluster.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/genx2apic_phys.c | 21 | ||||
-rw-r--r-- | arch/x86/kernel/genx2apic_uv_x.c | 32 | ||||
-rw-r--r-- | include/asm-x86/genapic_64.h | 1 |
6 files changed, 116 insertions, 60 deletions
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c index 3940d8161f8b..b3ba969c50d2 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 | 24 | extern struct genapic apic_flat; |
26 | #include <acpi/acpi_bus.h> | 25 | extern struct genapic apic_physflat; |
27 | #endif | 26 | extern struct genapic apic_x2xpic_uv_x; |
28 | 27 | extern struct genapic apic_x2apic_phys; | |
29 | DEFINE_PER_CPU(int, x2apic_extra_bits); | 28 | extern struct genapic apic_x2apic_cluster; |
30 | 29 | ||
31 | struct genapic __read_mostly *genapic = &apic_flat; | 30 | struct genapic __read_mostly *genapic = &apic_flat; |
32 | 31 | ||
33 | static int x2apic_phys = 0; | 32 | static struct genapic *apic_probe[] __initdata = { |
34 | 33 | &apic_x2apic_uv_x, | |
35 | static 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 | }; |
40 | early_param("x2apic_phys", set_x2apic_phys_mode); | ||
41 | |||
42 | static 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 | */ |
47 | void __init setup_apic_routing(void) | 43 | void __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 | ||
84 | int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 59 | int __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 | |||
97 | enum uv_system_type get_uv_system_type(void) | ||
98 | { | ||
99 | return uv_system_type; | ||
100 | } | ||
101 | |||
102 | int 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 2c973cbf054f..1740b83329f6 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 | |||
28 | static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | ||
29 | { | ||
30 | return 1; | ||
31 | } | ||
32 | |||
24 | static cpumask_t flat_target_cpus(void) | 33 | static 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 | ||
139 | struct genapic apic_flat = { | 148 | struct 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 | */ |
173 | static 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 | ||
164 | static cpumask_t physflat_target_cpus(void) | 189 | static 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 | ||
207 | struct genapic apic_physflat = { | 232 | struct 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 40bc0140d89f..ef3f3182d50a 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 | ||
11 | DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); | 13 | DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); |
12 | 14 | ||
15 | static 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 | ||
15 | static cpumask_t x2apic_target_cpus(void) | 25 | static cpumask_t x2apic_target_cpus(void) |
@@ -135,6 +145,7 @@ static void init_x2apic_ldr(void) | |||
135 | 145 | ||
136 | struct genapic apic_x2apic_cluster = { | 146 | struct 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 2f3c6ca19de9..f35a3bf3a9e5 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 | ||
13 | DEFINE_PER_CPU(int, x2apic_extra_bits); | ||
14 | |||
15 | static int x2apic_phys; | ||
16 | |||
17 | static int set_x2apic_phys_mode(char *arg) | ||
18 | { | ||
19 | x2apic_phys = 1; | ||
20 | return 0; | ||
21 | } | ||
22 | early_param("x2apic_phys", set_x2apic_phys_mode); | ||
23 | |||
24 | static 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 | ||
123 | struct genapic apic_x2apic_phys = { | 143 | struct 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 a8e5cb4c4d43..a882bc3a2ce9 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 | ||
30 | static enum uv_system_type uv_system_type; | ||
31 | |||
32 | static 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 | |||
47 | enum uv_system_type get_uv_system_type(void) | ||
48 | { | ||
49 | return uv_system_type; | ||
50 | } | ||
51 | |||
52 | int is_uv_system(void) | ||
53 | { | ||
54 | return uv_system_type != UV_NONE; | ||
55 | } | ||
56 | |||
30 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | 57 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); |
31 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); | 58 | EXPORT_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 | ||
156 | static long set_apic_id(unsigned int id) | 183 | static 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 | ||
183 | struct genapic apic_x2apic_uv_x = { | 210 | struct 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 2871b3fccb21..1e832e49f54e 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | struct genapic { | 15 | struct 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); |