diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-05-01 13:02:50 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-01 13:02:50 -0400 |
commit | 4420471f14b79f2a42e4603be7794ea49b68bca4 (patch) | |
tree | d391d25458bc0aa86dcf2823fd6c1464883b0533 /arch/x86/kernel/apic/apic.c | |
parent | 15e957d08dd4a841359cfec59ecb74041e0097aa (diff) | |
parent | e0e42142bab96404de535cceb85d6533d5ad7942 (diff) |
Merge branch 'x86/apic' into irq/numa
Conflicts:
arch/x86/kernel/apic/io_apic.c
Merge reason: non-trivial interaction between ongoing work in io_apic.c
and the NUMA migration feature in the irq tree.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 253 |
1 files changed, 153 insertions, 100 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index f2870920f246..28f747d61d78 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -98,6 +98,29 @@ early_param("lapic", parse_lapic); | |||
98 | /* Local APIC was disabled by the BIOS and enabled by the kernel */ | 98 | /* Local APIC was disabled by the BIOS and enabled by the kernel */ |
99 | static int enabled_via_apicbase; | 99 | static int enabled_via_apicbase; |
100 | 100 | ||
101 | /* | ||
102 | * Handle interrupt mode configuration register (IMCR). | ||
103 | * This register controls whether the interrupt signals | ||
104 | * that reach the BSP come from the master PIC or from the | ||
105 | * local APIC. Before entering Symmetric I/O Mode, either | ||
106 | * the BIOS or the operating system must switch out of | ||
107 | * PIC Mode by changing the IMCR. | ||
108 | */ | ||
109 | static inline void imcr_pic_to_apic(void) | ||
110 | { | ||
111 | /* select IMCR register */ | ||
112 | outb(0x70, 0x22); | ||
113 | /* NMI and 8259 INTR go through APIC */ | ||
114 | outb(0x01, 0x23); | ||
115 | } | ||
116 | |||
117 | static inline void imcr_apic_to_pic(void) | ||
118 | { | ||
119 | /* select IMCR register */ | ||
120 | outb(0x70, 0x22); | ||
121 | /* NMI and 8259 INTR go directly to BSP */ | ||
122 | outb(0x00, 0x23); | ||
123 | } | ||
101 | #endif | 124 | #endif |
102 | 125 | ||
103 | #ifdef CONFIG_X86_64 | 126 | #ifdef CONFIG_X86_64 |
@@ -111,13 +134,19 @@ static __init int setup_apicpmtimer(char *s) | |||
111 | __setup("apicpmtimer", setup_apicpmtimer); | 134 | __setup("apicpmtimer", setup_apicpmtimer); |
112 | #endif | 135 | #endif |
113 | 136 | ||
137 | int x2apic_mode; | ||
114 | #ifdef CONFIG_X86_X2APIC | 138 | #ifdef CONFIG_X86_X2APIC |
115 | int x2apic; | ||
116 | /* x2apic enabled before OS handover */ | 139 | /* x2apic enabled before OS handover */ |
117 | static int x2apic_preenabled; | 140 | static int x2apic_preenabled; |
118 | static int disable_x2apic; | 141 | static int disable_x2apic; |
119 | static __init int setup_nox2apic(char *str) | 142 | static __init int setup_nox2apic(char *str) |
120 | { | 143 | { |
144 | if (x2apic_enabled()) { | ||
145 | pr_warning("Bios already enabled x2apic, " | ||
146 | "can't enforce nox2apic"); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
121 | disable_x2apic = 1; | 150 | disable_x2apic = 1; |
122 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); | 151 | setup_clear_cpu_cap(X86_FEATURE_X2APIC); |
123 | return 0; | 152 | return 0; |
@@ -209,6 +238,24 @@ static int modern_apic(void) | |||
209 | return lapic_get_version() >= 0x14; | 238 | return lapic_get_version() >= 0x14; |
210 | } | 239 | } |
211 | 240 | ||
241 | /* | ||
242 | * bare function to substitute write operation | ||
243 | * and it's _that_ fast :) | ||
244 | */ | ||
245 | void native_apic_write_dummy(u32 reg, u32 v) | ||
246 | { | ||
247 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * right after this call apic->write doesn't do anything | ||
252 | * note that there is no restore operation it works one way | ||
253 | */ | ||
254 | void apic_disable(void) | ||
255 | { | ||
256 | apic->write = native_apic_write_dummy; | ||
257 | } | ||
258 | |||
212 | void native_apic_wait_icr_idle(void) | 259 | void native_apic_wait_icr_idle(void) |
213 | { | 260 | { |
214 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 261 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) |
@@ -815,7 +862,7 @@ void clear_local_APIC(void) | |||
815 | u32 v; | 862 | u32 v; |
816 | 863 | ||
817 | /* APIC hasn't been mapped yet */ | 864 | /* APIC hasn't been mapped yet */ |
818 | if (!x2apic && !apic_phys) | 865 | if (!x2apic_mode && !apic_phys) |
819 | return; | 866 | return; |
820 | 867 | ||
821 | maxlvt = lapic_get_maxlvt(); | 868 | maxlvt = lapic_get_maxlvt(); |
@@ -1287,7 +1334,7 @@ void check_x2apic(void) | |||
1287 | { | 1334 | { |
1288 | if (x2apic_enabled()) { | 1335 | if (x2apic_enabled()) { |
1289 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); | 1336 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); |
1290 | x2apic_preenabled = x2apic = 1; | 1337 | x2apic_preenabled = x2apic_mode = 1; |
1291 | } | 1338 | } |
1292 | } | 1339 | } |
1293 | 1340 | ||
@@ -1295,7 +1342,7 @@ void enable_x2apic(void) | |||
1295 | { | 1342 | { |
1296 | int msr, msr2; | 1343 | int msr, msr2; |
1297 | 1344 | ||
1298 | if (!x2apic) | 1345 | if (!x2apic_mode) |
1299 | return; | 1346 | return; |
1300 | 1347 | ||
1301 | rdmsr(MSR_IA32_APICBASE, msr, msr2); | 1348 | rdmsr(MSR_IA32_APICBASE, msr, msr2); |
@@ -1304,6 +1351,7 @@ void enable_x2apic(void) | |||
1304 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); | 1351 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); |
1305 | } | 1352 | } |
1306 | } | 1353 | } |
1354 | #endif /* CONFIG_X86_X2APIC */ | ||
1307 | 1355 | ||
1308 | void __init enable_IR_x2apic(void) | 1356 | void __init enable_IR_x2apic(void) |
1309 | { | 1357 | { |
@@ -1312,32 +1360,21 @@ void __init enable_IR_x2apic(void) | |||
1312 | unsigned long flags; | 1360 | unsigned long flags; |
1313 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 1361 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1314 | 1362 | ||
1315 | if (!cpu_has_x2apic) | 1363 | ret = dmar_table_init(); |
1316 | return; | 1364 | if (ret) { |
1317 | 1365 | pr_debug("dmar_table_init() failed with %d:\n", ret); | |
1318 | if (!x2apic_preenabled && disable_x2apic) { | 1366 | goto ir_failed; |
1319 | pr_info("Skipped enabling x2apic and Interrupt-remapping " | ||
1320 | "because of nox2apic\n"); | ||
1321 | return; | ||
1322 | } | 1367 | } |
1323 | 1368 | ||
1324 | if (x2apic_preenabled && disable_x2apic) | 1369 | if (!intr_remapping_supported()) { |
1325 | panic("Bios already enabled x2apic, can't enforce nox2apic"); | 1370 | pr_debug("intr-remapping not supported\n"); |
1326 | 1371 | goto ir_failed; | |
1327 | if (!x2apic_preenabled && skip_ioapic_setup) { | ||
1328 | pr_info("Skipped enabling x2apic and Interrupt-remapping " | ||
1329 | "because of skipping io-apic setup\n"); | ||
1330 | return; | ||
1331 | } | 1372 | } |
1332 | 1373 | ||
1333 | ret = dmar_table_init(); | ||
1334 | if (ret) { | ||
1335 | pr_info("dmar_table_init() failed with %d:\n", ret); | ||
1336 | 1374 | ||
1337 | if (x2apic_preenabled) | 1375 | if (!x2apic_preenabled && skip_ioapic_setup) { |
1338 | panic("x2apic enabled by bios. But IR enabling failed"); | 1376 | pr_info("Skipped enabling intr-remap because of skipping " |
1339 | else | 1377 | "io-apic setup\n"); |
1340 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1341 | return; | 1378 | return; |
1342 | } | 1379 | } |
1343 | 1380 | ||
@@ -1357,19 +1394,16 @@ void __init enable_IR_x2apic(void) | |||
1357 | mask_IO_APIC_setup(ioapic_entries); | 1394 | mask_IO_APIC_setup(ioapic_entries); |
1358 | mask_8259A(); | 1395 | mask_8259A(); |
1359 | 1396 | ||
1360 | ret = enable_intr_remapping(EIM_32BIT_APIC_ID); | 1397 | ret = enable_intr_remapping(x2apic_supported()); |
1361 | |||
1362 | if (ret && x2apic_preenabled) { | ||
1363 | local_irq_restore(flags); | ||
1364 | panic("x2apic enabled by bios. But IR enabling failed"); | ||
1365 | } | ||
1366 | |||
1367 | if (ret) | 1398 | if (ret) |
1368 | goto end_restore; | 1399 | goto end_restore; |
1369 | 1400 | ||
1370 | if (!x2apic) { | 1401 | pr_info("Enabled Interrupt-remapping\n"); |
1371 | x2apic = 1; | 1402 | |
1403 | if (x2apic_supported() && !x2apic_mode) { | ||
1404 | x2apic_mode = 1; | ||
1372 | enable_x2apic(); | 1405 | enable_x2apic(); |
1406 | pr_info("Enabled x2apic\n"); | ||
1373 | } | 1407 | } |
1374 | 1408 | ||
1375 | end_restore: | 1409 | end_restore: |
@@ -1378,37 +1412,34 @@ end_restore: | |||
1378 | * IR enabling failed | 1412 | * IR enabling failed |
1379 | */ | 1413 | */ |
1380 | restore_IO_APIC_setup(ioapic_entries); | 1414 | restore_IO_APIC_setup(ioapic_entries); |
1381 | else | ||
1382 | reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries); | ||
1383 | 1415 | ||
1384 | unmask_8259A(); | 1416 | unmask_8259A(); |
1385 | local_irq_restore(flags); | 1417 | local_irq_restore(flags); |
1386 | 1418 | ||
1387 | end: | 1419 | end: |
1388 | if (!ret) { | ||
1389 | if (!x2apic_preenabled) | ||
1390 | pr_info("Enabled x2apic and interrupt-remapping\n"); | ||
1391 | else | ||
1392 | pr_info("Enabled Interrupt-remapping\n"); | ||
1393 | } else | ||
1394 | pr_err("Failed to enable Interrupt-remapping and x2apic\n"); | ||
1395 | if (ioapic_entries) | 1420 | if (ioapic_entries) |
1396 | free_ioapic_entries(ioapic_entries); | 1421 | free_ioapic_entries(ioapic_entries); |
1422 | |||
1423 | if (!ret) | ||
1424 | return; | ||
1425 | |||
1426 | ir_failed: | ||
1427 | if (x2apic_preenabled) | ||
1428 | panic("x2apic enabled by bios. But IR enabling failed"); | ||
1429 | else if (cpu_has_x2apic) | ||
1430 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1397 | #else | 1431 | #else |
1398 | if (!cpu_has_x2apic) | 1432 | if (!cpu_has_x2apic) |
1399 | return; | 1433 | return; |
1400 | 1434 | ||
1401 | if (x2apic_preenabled) | 1435 | if (x2apic_preenabled) |
1402 | panic("x2apic enabled prior OS handover," | 1436 | panic("x2apic enabled prior OS handover," |
1403 | " enable CONFIG_INTR_REMAP"); | 1437 | " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP"); |
1404 | |||
1405 | pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping " | ||
1406 | " and x2apic\n"); | ||
1407 | #endif | 1438 | #endif |
1408 | 1439 | ||
1409 | return; | 1440 | return; |
1410 | } | 1441 | } |
1411 | #endif /* CONFIG_X86_X2APIC */ | 1442 | |
1412 | 1443 | ||
1413 | #ifdef CONFIG_X86_64 | 1444 | #ifdef CONFIG_X86_64 |
1414 | /* | 1445 | /* |
@@ -1539,7 +1570,7 @@ void __init early_init_lapic_mapping(void) | |||
1539 | */ | 1570 | */ |
1540 | void __init init_apic_mappings(void) | 1571 | void __init init_apic_mappings(void) |
1541 | { | 1572 | { |
1542 | if (x2apic) { | 1573 | if (x2apic_mode) { |
1543 | boot_cpu_physical_apicid = read_apic_id(); | 1574 | boot_cpu_physical_apicid = read_apic_id(); |
1544 | return; | 1575 | return; |
1545 | } | 1576 | } |
@@ -1565,6 +1596,12 @@ void __init init_apic_mappings(void) | |||
1565 | */ | 1596 | */ |
1566 | if (boot_cpu_physical_apicid == -1U) | 1597 | if (boot_cpu_physical_apicid == -1U) |
1567 | boot_cpu_physical_apicid = read_apic_id(); | 1598 | boot_cpu_physical_apicid = read_apic_id(); |
1599 | |||
1600 | /* lets check if we may to NOP'ify apic operations */ | ||
1601 | if (!cpu_has_apic) { | ||
1602 | pr_info("APIC: disable apic facility\n"); | ||
1603 | apic_disable(); | ||
1604 | } | ||
1568 | } | 1605 | } |
1569 | 1606 | ||
1570 | /* | 1607 | /* |
@@ -1733,8 +1770,7 @@ void __init connect_bsp_APIC(void) | |||
1733 | */ | 1770 | */ |
1734 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " | 1771 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " |
1735 | "enabling APIC mode.\n"); | 1772 | "enabling APIC mode.\n"); |
1736 | outb(0x70, 0x22); | 1773 | imcr_pic_to_apic(); |
1737 | outb(0x01, 0x23); | ||
1738 | } | 1774 | } |
1739 | #endif | 1775 | #endif |
1740 | if (apic->enable_apic_mode) | 1776 | if (apic->enable_apic_mode) |
@@ -1762,8 +1798,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
1762 | */ | 1798 | */ |
1763 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " | 1799 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " |
1764 | "entering PIC mode.\n"); | 1800 | "entering PIC mode.\n"); |
1765 | outb(0x70, 0x22); | 1801 | imcr_apic_to_pic(); |
1766 | outb(0x00, 0x23); | ||
1767 | return; | 1802 | return; |
1768 | } | 1803 | } |
1769 | #endif | 1804 | #endif |
@@ -1969,10 +2004,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1969 | 2004 | ||
1970 | local_irq_save(flags); | 2005 | local_irq_save(flags); |
1971 | disable_local_APIC(); | 2006 | disable_local_APIC(); |
1972 | #ifdef CONFIG_INTR_REMAP | 2007 | |
1973 | if (intr_remapping_enabled) | 2008 | if (intr_remapping_enabled) |
1974 | disable_intr_remapping(); | 2009 | disable_intr_remapping(); |
1975 | #endif | 2010 | |
1976 | local_irq_restore(flags); | 2011 | local_irq_restore(flags); |
1977 | return 0; | 2012 | return 0; |
1978 | } | 2013 | } |
@@ -1982,8 +2017,6 @@ static int lapic_resume(struct sys_device *dev) | |||
1982 | unsigned int l, h; | 2017 | unsigned int l, h; |
1983 | unsigned long flags; | 2018 | unsigned long flags; |
1984 | int maxlvt; | 2019 | int maxlvt; |
1985 | |||
1986 | #ifdef CONFIG_INTR_REMAP | ||
1987 | int ret; | 2020 | int ret; |
1988 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 2021 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1989 | 2022 | ||
@@ -1991,7 +2024,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1991 | return 0; | 2024 | return 0; |
1992 | 2025 | ||
1993 | local_irq_save(flags); | 2026 | local_irq_save(flags); |
1994 | if (x2apic) { | 2027 | if (intr_remapping_enabled) { |
1995 | ioapic_entries = alloc_ioapic_entries(); | 2028 | ioapic_entries = alloc_ioapic_entries(); |
1996 | if (!ioapic_entries) { | 2029 | if (!ioapic_entries) { |
1997 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2030 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); |
@@ -2007,17 +2040,10 @@ static int lapic_resume(struct sys_device *dev) | |||
2007 | 2040 | ||
2008 | mask_IO_APIC_setup(ioapic_entries); | 2041 | mask_IO_APIC_setup(ioapic_entries); |
2009 | mask_8259A(); | 2042 | mask_8259A(); |
2010 | enable_x2apic(); | ||
2011 | } | 2043 | } |
2012 | #else | ||
2013 | if (!apic_pm_state.active) | ||
2014 | return 0; | ||
2015 | 2044 | ||
2016 | local_irq_save(flags); | 2045 | if (x2apic_mode) |
2017 | if (x2apic) | ||
2018 | enable_x2apic(); | 2046 | enable_x2apic(); |
2019 | #endif | ||
2020 | |||
2021 | else { | 2047 | else { |
2022 | /* | 2048 | /* |
2023 | * Make sure the APICBASE points to the right address | 2049 | * Make sure the APICBASE points to the right address |
@@ -2055,20 +2081,15 @@ static int lapic_resume(struct sys_device *dev) | |||
2055 | apic_write(APIC_ESR, 0); | 2081 | apic_write(APIC_ESR, 0); |
2056 | apic_read(APIC_ESR); | 2082 | apic_read(APIC_ESR); |
2057 | 2083 | ||
2058 | #ifdef CONFIG_INTR_REMAP | 2084 | if (intr_remapping_enabled) { |
2059 | if (intr_remapping_enabled) | 2085 | reenable_intr_remapping(x2apic_mode); |
2060 | reenable_intr_remapping(EIM_32BIT_APIC_ID); | ||
2061 | |||
2062 | if (x2apic) { | ||
2063 | unmask_8259A(); | 2086 | unmask_8259A(); |
2064 | restore_IO_APIC_setup(ioapic_entries); | 2087 | restore_IO_APIC_setup(ioapic_entries); |
2065 | free_ioapic_entries(ioapic_entries); | 2088 | free_ioapic_entries(ioapic_entries); |
2066 | } | 2089 | } |
2067 | #endif | ||
2068 | 2090 | ||
2069 | local_irq_restore(flags); | 2091 | local_irq_restore(flags); |
2070 | 2092 | ||
2071 | |||
2072 | return 0; | 2093 | return 0; |
2073 | } | 2094 | } |
2074 | 2095 | ||
@@ -2117,31 +2138,14 @@ static void apic_pm_activate(void) { } | |||
2117 | #endif /* CONFIG_PM */ | 2138 | #endif /* CONFIG_PM */ |
2118 | 2139 | ||
2119 | #ifdef CONFIG_X86_64 | 2140 | #ifdef CONFIG_X86_64 |
2120 | /* | 2141 | |
2121 | * apic_is_clustered_box() -- Check if we can expect good TSC | 2142 | static int __cpuinit apic_cluster_num(void) |
2122 | * | ||
2123 | * Thus far, the major user of this is IBM's Summit2 series: | ||
2124 | * | ||
2125 | * Clustered boxes may have unsynced TSC problems if they are | ||
2126 | * multi-chassis. Use available data to take a good guess. | ||
2127 | * If in doubt, go HPET. | ||
2128 | */ | ||
2129 | __cpuinit int apic_is_clustered_box(void) | ||
2130 | { | 2143 | { |
2131 | int i, clusters, zeros; | 2144 | int i, clusters, zeros; |
2132 | unsigned id; | 2145 | unsigned id; |
2133 | u16 *bios_cpu_apicid; | 2146 | u16 *bios_cpu_apicid; |
2134 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); | 2147 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); |
2135 | 2148 | ||
2136 | /* | ||
2137 | * there is not this kind of box with AMD CPU yet. | ||
2138 | * Some AMD box with quadcore cpu and 8 sockets apicid | ||
2139 | * will be [4, 0x23] or [8, 0x27] could be thought to | ||
2140 | * vsmp box still need checking... | ||
2141 | */ | ||
2142 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box()) | ||
2143 | return 0; | ||
2144 | |||
2145 | bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); | 2149 | bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); |
2146 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); | 2150 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); |
2147 | 2151 | ||
@@ -2177,18 +2181,67 @@ __cpuinit int apic_is_clustered_box(void) | |||
2177 | ++zeros; | 2181 | ++zeros; |
2178 | } | 2182 | } |
2179 | 2183 | ||
2180 | /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are | 2184 | return clusters; |
2181 | * not guaranteed to be synced between boards | 2185 | } |
2182 | */ | 2186 | |
2183 | if (is_vsmp_box() && clusters > 1) | 2187 | static int __cpuinitdata multi_checked; |
2188 | static int __cpuinitdata multi; | ||
2189 | |||
2190 | static int __cpuinit set_multi(const struct dmi_system_id *d) | ||
2191 | { | ||
2192 | if (multi) | ||
2193 | return 0; | ||
2194 | printk(KERN_INFO "APIC: %s detected, Multi Chassis\n", d->ident); | ||
2195 | multi = 1; | ||
2196 | return 0; | ||
2197 | } | ||
2198 | |||
2199 | static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { | ||
2200 | { | ||
2201 | .callback = set_multi, | ||
2202 | .ident = "IBM System Summit2", | ||
2203 | .matches = { | ||
2204 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
2205 | DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"), | ||
2206 | }, | ||
2207 | }, | ||
2208 | {} | ||
2209 | }; | ||
2210 | |||
2211 | static void __cpuinit dmi_check_multi(void) | ||
2212 | { | ||
2213 | if (multi_checked) | ||
2214 | return; | ||
2215 | |||
2216 | dmi_check_system(multi_dmi_table); | ||
2217 | multi_checked = 1; | ||
2218 | } | ||
2219 | |||
2220 | /* | ||
2221 | * apic_is_clustered_box() -- Check if we can expect good TSC | ||
2222 | * | ||
2223 | * Thus far, the major user of this is IBM's Summit2 series: | ||
2224 | * Clustered boxes may have unsynced TSC problems if they are | ||
2225 | * multi-chassis. | ||
2226 | * Use DMI to check them | ||
2227 | */ | ||
2228 | __cpuinit int apic_is_clustered_box(void) | ||
2229 | { | ||
2230 | dmi_check_multi(); | ||
2231 | if (multi) | ||
2184 | return 1; | 2232 | return 1; |
2185 | 2233 | ||
2234 | if (!is_vsmp_box()) | ||
2235 | return 0; | ||
2236 | |||
2186 | /* | 2237 | /* |
2187 | * If clusters > 2, then should be multi-chassis. | 2238 | * ScaleMP vSMPowered boxes have one cluster per board and TSCs are |
2188 | * May have to revisit this when multi-core + hyperthreaded CPUs come | 2239 | * not guaranteed to be synced between boards |
2189 | * out, but AFAIK this will work even for them. | ||
2190 | */ | 2240 | */ |
2191 | return (clusters > 2); | 2241 | if (apic_cluster_num() > 1) |
2242 | return 1; | ||
2243 | |||
2244 | return 0; | ||
2192 | } | 2245 | } |
2193 | #endif | 2246 | #endif |
2194 | 2247 | ||