diff options
Diffstat (limited to 'arch/x86/kernel/apic/probe_32.c')
-rw-r--r-- | arch/x86/kernel/apic/probe_32.c | 120 |
1 files changed, 49 insertions, 71 deletions
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 99d2fe016084..b5254ad044ab 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c | |||
@@ -52,29 +52,9 @@ static int __init print_ipi_mode(void) | |||
52 | } | 52 | } |
53 | late_initcall(print_ipi_mode); | 53 | late_initcall(print_ipi_mode); |
54 | 54 | ||
55 | void __init default_setup_apic_routing(void) | 55 | static int default_x86_32_early_logical_apicid(int cpu) |
56 | { | 56 | { |
57 | int version = apic_version[boot_cpu_physical_apicid]; | 57 | return 1 << cpu; |
58 | |||
59 | if (num_possible_cpus() > 8) { | ||
60 | switch (boot_cpu_data.x86_vendor) { | ||
61 | case X86_VENDOR_INTEL: | ||
62 | if (!APIC_XAPIC(version)) { | ||
63 | def_to_bigsmp = 0; | ||
64 | break; | ||
65 | } | ||
66 | /* If P4 and above fall through */ | ||
67 | case X86_VENDOR_AMD: | ||
68 | def_to_bigsmp = 1; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | #ifdef CONFIG_X86_BIGSMP | ||
73 | generic_bigsmp_probe(); | ||
74 | #endif | ||
75 | |||
76 | if (apic->setup_apic_routing) | ||
77 | apic->setup_apic_routing(); | ||
78 | } | 58 | } |
79 | 59 | ||
80 | static void setup_apic_flat_routing(void) | 60 | static void setup_apic_flat_routing(void) |
@@ -107,7 +87,7 @@ static int probe_default(void) | |||
107 | return 1; | 87 | return 1; |
108 | } | 88 | } |
109 | 89 | ||
110 | struct apic apic_default = { | 90 | static struct apic apic_default = { |
111 | 91 | ||
112 | .name = "default", | 92 | .name = "default", |
113 | .probe = probe_default, | 93 | .probe = probe_default, |
@@ -130,8 +110,6 @@ struct apic apic_default = { | |||
130 | .ioapic_phys_id_map = default_ioapic_phys_id_map, | 110 | .ioapic_phys_id_map = default_ioapic_phys_id_map, |
131 | .setup_apic_routing = setup_apic_flat_routing, | 111 | .setup_apic_routing = setup_apic_flat_routing, |
132 | .multi_timer_check = NULL, | 112 | .multi_timer_check = NULL, |
133 | .apicid_to_node = default_apicid_to_node, | ||
134 | .cpu_to_logical_apicid = default_cpu_to_logical_apicid, | ||
135 | .cpu_present_to_apicid = default_cpu_present_to_apicid, | 113 | .cpu_present_to_apicid = default_cpu_present_to_apicid, |
136 | .apicid_to_cpu_present = physid_set_mask_of_physid, | 114 | .apicid_to_cpu_present = physid_set_mask_of_physid, |
137 | .setup_portio_remap = NULL, | 115 | .setup_portio_remap = NULL, |
@@ -167,46 +145,26 @@ struct apic apic_default = { | |||
167 | .icr_write = native_apic_icr_write, | 145 | .icr_write = native_apic_icr_write, |
168 | .wait_icr_idle = native_apic_wait_icr_idle, | 146 | .wait_icr_idle = native_apic_wait_icr_idle, |
169 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, | 147 | .safe_wait_icr_idle = native_safe_apic_wait_icr_idle, |
148 | |||
149 | .x86_32_early_logical_apicid = default_x86_32_early_logical_apicid, | ||
170 | }; | 150 | }; |
171 | 151 | ||
172 | extern struct apic apic_numaq; | 152 | apic_driver(apic_default); |
173 | extern struct apic apic_summit; | ||
174 | extern struct apic apic_bigsmp; | ||
175 | extern struct apic apic_es7000; | ||
176 | extern struct apic apic_es7000_cluster; | ||
177 | 153 | ||
178 | struct apic *apic = &apic_default; | 154 | struct apic *apic = &apic_default; |
179 | EXPORT_SYMBOL_GPL(apic); | 155 | EXPORT_SYMBOL_GPL(apic); |
180 | 156 | ||
181 | static struct apic *apic_probe[] __initdata = { | ||
182 | #ifdef CONFIG_X86_NUMAQ | ||
183 | &apic_numaq, | ||
184 | #endif | ||
185 | #ifdef CONFIG_X86_SUMMIT | ||
186 | &apic_summit, | ||
187 | #endif | ||
188 | #ifdef CONFIG_X86_BIGSMP | ||
189 | &apic_bigsmp, | ||
190 | #endif | ||
191 | #ifdef CONFIG_X86_ES7000 | ||
192 | &apic_es7000, | ||
193 | &apic_es7000_cluster, | ||
194 | #endif | ||
195 | &apic_default, /* must be last */ | ||
196 | NULL, | ||
197 | }; | ||
198 | |||
199 | static int cmdline_apic __initdata; | 157 | static int cmdline_apic __initdata; |
200 | static int __init parse_apic(char *arg) | 158 | static int __init parse_apic(char *arg) |
201 | { | 159 | { |
202 | int i; | 160 | struct apic **drv; |
203 | 161 | ||
204 | if (!arg) | 162 | if (!arg) |
205 | return -EINVAL; | 163 | return -EINVAL; |
206 | 164 | ||
207 | for (i = 0; apic_probe[i]; i++) { | 165 | for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { |
208 | if (!strcmp(apic_probe[i]->name, arg)) { | 166 | if (!strcmp((*drv)->name, arg)) { |
209 | apic = apic_probe[i]; | 167 | apic = *drv; |
210 | cmdline_apic = 1; | 168 | cmdline_apic = 1; |
211 | return 0; | 169 | return 0; |
212 | } | 170 | } |
@@ -217,38 +175,58 @@ static int __init parse_apic(char *arg) | |||
217 | } | 175 | } |
218 | early_param("apic", parse_apic); | 176 | early_param("apic", parse_apic); |
219 | 177 | ||
220 | void __init generic_bigsmp_probe(void) | 178 | void __init default_setup_apic_routing(void) |
221 | { | 179 | { |
180 | int version = apic_version[boot_cpu_physical_apicid]; | ||
181 | |||
182 | if (num_possible_cpus() > 8) { | ||
183 | switch (boot_cpu_data.x86_vendor) { | ||
184 | case X86_VENDOR_INTEL: | ||
185 | if (!APIC_XAPIC(version)) { | ||
186 | def_to_bigsmp = 0; | ||
187 | break; | ||
188 | } | ||
189 | /* If P4 and above fall through */ | ||
190 | case X86_VENDOR_AMD: | ||
191 | def_to_bigsmp = 1; | ||
192 | } | ||
193 | } | ||
194 | |||
222 | #ifdef CONFIG_X86_BIGSMP | 195 | #ifdef CONFIG_X86_BIGSMP |
223 | /* | 196 | /* |
224 | * This routine is used to switch to bigsmp mode when | 197 | * This is used to switch to bigsmp mode when |
225 | * - There is no apic= option specified by the user | 198 | * - There is no apic= option specified by the user |
226 | * - generic_apic_probe() has chosen apic_default as the sub_arch | 199 | * - generic_apic_probe() has chosen apic_default as the sub_arch |
227 | * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support | 200 | * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support |
228 | */ | 201 | */ |
229 | 202 | ||
230 | if (!cmdline_apic && apic == &apic_default) { | 203 | if (!cmdline_apic && apic == &apic_default) { |
231 | if (apic_bigsmp.probe()) { | 204 | struct apic *bigsmp = generic_bigsmp_probe(); |
232 | apic = &apic_bigsmp; | 205 | if (bigsmp) { |
206 | apic = bigsmp; | ||
233 | printk(KERN_INFO "Overriding APIC driver with %s\n", | 207 | printk(KERN_INFO "Overriding APIC driver with %s\n", |
234 | apic->name); | 208 | apic->name); |
235 | } | 209 | } |
236 | } | 210 | } |
237 | #endif | 211 | #endif |
212 | |||
213 | if (apic->setup_apic_routing) | ||
214 | apic->setup_apic_routing(); | ||
238 | } | 215 | } |
239 | 216 | ||
240 | void __init generic_apic_probe(void) | 217 | void __init generic_apic_probe(void) |
241 | { | 218 | { |
242 | if (!cmdline_apic) { | 219 | if (!cmdline_apic) { |
243 | int i; | 220 | struct apic **drv; |
244 | for (i = 0; apic_probe[i]; i++) { | 221 | |
245 | if (apic_probe[i]->probe()) { | 222 | for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { |
246 | apic = apic_probe[i]; | 223 | if ((*drv)->probe()) { |
224 | apic = *drv; | ||
247 | break; | 225 | break; |
248 | } | 226 | } |
249 | } | 227 | } |
250 | /* Not visible without early console */ | 228 | /* Not visible without early console */ |
251 | if (!apic_probe[i]) | 229 | if (drv == __apicdrivers_end) |
252 | panic("Didn't find an APIC driver"); | 230 | panic("Didn't find an APIC driver"); |
253 | } | 231 | } |
254 | printk(KERN_INFO "Using APIC driver %s\n", apic->name); | 232 | printk(KERN_INFO "Using APIC driver %s\n", apic->name); |
@@ -259,16 +237,16 @@ void __init generic_apic_probe(void) | |||
259 | int __init | 237 | int __init |
260 | generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | 238 | generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) |
261 | { | 239 | { |
262 | int i; | 240 | struct apic **drv; |
263 | 241 | ||
264 | for (i = 0; apic_probe[i]; ++i) { | 242 | for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { |
265 | if (!apic_probe[i]->mps_oem_check) | 243 | if (!((*drv)->mps_oem_check)) |
266 | continue; | 244 | continue; |
267 | if (!apic_probe[i]->mps_oem_check(mpc, oem, productid)) | 245 | if (!(*drv)->mps_oem_check(mpc, oem, productid)) |
268 | continue; | 246 | continue; |
269 | 247 | ||
270 | if (!cmdline_apic) { | 248 | if (!cmdline_apic) { |
271 | apic = apic_probe[i]; | 249 | apic = *drv; |
272 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", | 250 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
273 | apic->name); | 251 | apic->name); |
274 | } | 252 | } |
@@ -279,16 +257,16 @@ generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid) | |||
279 | 257 | ||
280 | int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 258 | int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
281 | { | 259 | { |
282 | int i; | 260 | struct apic **drv; |
283 | 261 | ||
284 | for (i = 0; apic_probe[i]; ++i) { | 262 | for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { |
285 | if (!apic_probe[i]->acpi_madt_oem_check) | 263 | if (!(*drv)->acpi_madt_oem_check) |
286 | continue; | 264 | continue; |
287 | if (!apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) | 265 | if (!(*drv)->acpi_madt_oem_check(oem_id, oem_table_id)) |
288 | continue; | 266 | continue; |
289 | 267 | ||
290 | if (!cmdline_apic) { | 268 | if (!cmdline_apic) { |
291 | apic = apic_probe[i]; | 269 | apic = *drv; |
292 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", | 270 | printk(KERN_INFO "Switched to APIC driver `%s'.\n", |
293 | apic->name); | 271 | apic->name); |
294 | } | 272 | } |