diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-06-01 18:13:02 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-06-01 18:25:31 -0400 |
commit | 48b1fddbb100a64f3983ca9768b8ea629a09aa20 (patch) | |
tree | 7cf552c623cb0aa0dd945df55b7eaf5a0697e277 /arch/x86/kernel/apic/apic.c | |
parent | 38736072d45488fd45f076388b6570419bbbc682 (diff) | |
parent | ee4c24a5c9b530481394132c8dbc10572d57c075 (diff) |
Merge branch 'irq/numa' into x86/mce3
Merge reason: arch/x86/kernel/irqinit_{32,64}.c unified in irq/numa
and modified in x86/mce3; this merge resolves the conflict.
Conflicts:
arch/x86/kernel/irqinit.c
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 293 |
1 files changed, 178 insertions, 115 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index ad532289ef2e..ee75d2a9b9cd 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,31 @@ 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 | static void native_apic_write_dummy(u32 reg, u32 v) | ||
246 | { | ||
247 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | ||
248 | } | ||
249 | |||
250 | static u32 native_apic_read_dummy(u32 reg) | ||
251 | { | ||
252 | WARN_ON_ONCE((cpu_has_apic || !disable_apic)); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * right after this call apic->write/read doesn't do anything | ||
258 | * note that there is no restore operation it works one way | ||
259 | */ | ||
260 | void apic_disable(void) | ||
261 | { | ||
262 | apic->read = native_apic_read_dummy; | ||
263 | apic->write = native_apic_write_dummy; | ||
264 | } | ||
265 | |||
212 | void native_apic_wait_icr_idle(void) | 266 | void native_apic_wait_icr_idle(void) |
213 | { | 267 | { |
214 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 268 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) |
@@ -348,7 +402,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
348 | 402 | ||
349 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | 403 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) |
350 | { | 404 | { |
351 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | 405 | unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0); |
352 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | 406 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; |
353 | 407 | ||
354 | apic_write(reg, v); | 408 | apic_write(reg, v); |
@@ -815,7 +869,7 @@ void clear_local_APIC(void) | |||
815 | u32 v; | 869 | u32 v; |
816 | 870 | ||
817 | /* APIC hasn't been mapped yet */ | 871 | /* APIC hasn't been mapped yet */ |
818 | if (!x2apic && !apic_phys) | 872 | if (!x2apic_mode && !apic_phys) |
819 | return; | 873 | return; |
820 | 874 | ||
821 | maxlvt = lapic_get_maxlvt(); | 875 | maxlvt = lapic_get_maxlvt(); |
@@ -1287,7 +1341,7 @@ void check_x2apic(void) | |||
1287 | { | 1341 | { |
1288 | if (x2apic_enabled()) { | 1342 | if (x2apic_enabled()) { |
1289 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); | 1343 | pr_info("x2apic enabled by BIOS, switching to x2apic ops\n"); |
1290 | x2apic_preenabled = x2apic = 1; | 1344 | x2apic_preenabled = x2apic_mode = 1; |
1291 | } | 1345 | } |
1292 | } | 1346 | } |
1293 | 1347 | ||
@@ -1295,7 +1349,7 @@ void enable_x2apic(void) | |||
1295 | { | 1349 | { |
1296 | int msr, msr2; | 1350 | int msr, msr2; |
1297 | 1351 | ||
1298 | if (!x2apic) | 1352 | if (!x2apic_mode) |
1299 | return; | 1353 | return; |
1300 | 1354 | ||
1301 | rdmsr(MSR_IA32_APICBASE, msr, msr2); | 1355 | rdmsr(MSR_IA32_APICBASE, msr, msr2); |
@@ -1304,6 +1358,7 @@ void enable_x2apic(void) | |||
1304 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); | 1358 | wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0); |
1305 | } | 1359 | } |
1306 | } | 1360 | } |
1361 | #endif /* CONFIG_X86_X2APIC */ | ||
1307 | 1362 | ||
1308 | void __init enable_IR_x2apic(void) | 1363 | void __init enable_IR_x2apic(void) |
1309 | { | 1364 | { |
@@ -1312,32 +1367,21 @@ void __init enable_IR_x2apic(void) | |||
1312 | unsigned long flags; | 1367 | unsigned long flags; |
1313 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 1368 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1314 | 1369 | ||
1315 | if (!cpu_has_x2apic) | 1370 | ret = dmar_table_init(); |
1316 | return; | 1371 | if (ret) { |
1317 | 1372 | pr_debug("dmar_table_init() failed with %d:\n", ret); | |
1318 | if (!x2apic_preenabled && disable_x2apic) { | 1373 | goto ir_failed; |
1319 | pr_info("Skipped enabling x2apic and Interrupt-remapping " | ||
1320 | "because of nox2apic\n"); | ||
1321 | return; | ||
1322 | } | 1374 | } |
1323 | 1375 | ||
1324 | if (x2apic_preenabled && disable_x2apic) | 1376 | if (!intr_remapping_supported()) { |
1325 | panic("Bios already enabled x2apic, can't enforce nox2apic"); | 1377 | pr_debug("intr-remapping not supported\n"); |
1326 | 1378 | 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 | } | 1379 | } |
1332 | 1380 | ||
1333 | ret = dmar_table_init(); | ||
1334 | if (ret) { | ||
1335 | pr_info("dmar_table_init() failed with %d:\n", ret); | ||
1336 | 1381 | ||
1337 | if (x2apic_preenabled) | 1382 | if (!x2apic_preenabled && skip_ioapic_setup) { |
1338 | panic("x2apic enabled by bios. But IR enabling failed"); | 1383 | pr_info("Skipped enabling intr-remap because of skipping " |
1339 | else | 1384 | "io-apic setup\n"); |
1340 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1341 | return; | 1385 | return; |
1342 | } | 1386 | } |
1343 | 1387 | ||
@@ -1357,19 +1401,16 @@ void __init enable_IR_x2apic(void) | |||
1357 | mask_IO_APIC_setup(ioapic_entries); | 1401 | mask_IO_APIC_setup(ioapic_entries); |
1358 | mask_8259A(); | 1402 | mask_8259A(); |
1359 | 1403 | ||
1360 | ret = enable_intr_remapping(EIM_32BIT_APIC_ID); | 1404 | 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) | 1405 | if (ret) |
1368 | goto end_restore; | 1406 | goto end_restore; |
1369 | 1407 | ||
1370 | if (!x2apic) { | 1408 | pr_info("Enabled Interrupt-remapping\n"); |
1371 | x2apic = 1; | 1409 | |
1410 | if (x2apic_supported() && !x2apic_mode) { | ||
1411 | x2apic_mode = 1; | ||
1372 | enable_x2apic(); | 1412 | enable_x2apic(); |
1413 | pr_info("Enabled x2apic\n"); | ||
1373 | } | 1414 | } |
1374 | 1415 | ||
1375 | end_restore: | 1416 | end_restore: |
@@ -1378,37 +1419,34 @@ end_restore: | |||
1378 | * IR enabling failed | 1419 | * IR enabling failed |
1379 | */ | 1420 | */ |
1380 | restore_IO_APIC_setup(ioapic_entries); | 1421 | restore_IO_APIC_setup(ioapic_entries); |
1381 | else | ||
1382 | reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries); | ||
1383 | 1422 | ||
1384 | unmask_8259A(); | 1423 | unmask_8259A(); |
1385 | local_irq_restore(flags); | 1424 | local_irq_restore(flags); |
1386 | 1425 | ||
1387 | end: | 1426 | 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) | 1427 | if (ioapic_entries) |
1396 | free_ioapic_entries(ioapic_entries); | 1428 | free_ioapic_entries(ioapic_entries); |
1429 | |||
1430 | if (!ret) | ||
1431 | return; | ||
1432 | |||
1433 | ir_failed: | ||
1434 | if (x2apic_preenabled) | ||
1435 | panic("x2apic enabled by bios. But IR enabling failed"); | ||
1436 | else if (cpu_has_x2apic) | ||
1437 | pr_info("Not enabling x2apic,Intr-remapping\n"); | ||
1397 | #else | 1438 | #else |
1398 | if (!cpu_has_x2apic) | 1439 | if (!cpu_has_x2apic) |
1399 | return; | 1440 | return; |
1400 | 1441 | ||
1401 | if (x2apic_preenabled) | 1442 | if (x2apic_preenabled) |
1402 | panic("x2apic enabled prior OS handover," | 1443 | panic("x2apic enabled prior OS handover," |
1403 | " enable CONFIG_INTR_REMAP"); | 1444 | " 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 | 1445 | #endif |
1408 | 1446 | ||
1409 | return; | 1447 | return; |
1410 | } | 1448 | } |
1411 | #endif /* CONFIG_X86_X2APIC */ | 1449 | |
1412 | 1450 | ||
1413 | #ifdef CONFIG_X86_64 | 1451 | #ifdef CONFIG_X86_64 |
1414 | /* | 1452 | /* |
@@ -1425,7 +1463,6 @@ static int __init detect_init_APIC(void) | |||
1425 | } | 1463 | } |
1426 | 1464 | ||
1427 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | 1465 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; |
1428 | boot_cpu_physical_apicid = 0; | ||
1429 | return 0; | 1466 | return 0; |
1430 | } | 1467 | } |
1431 | #else | 1468 | #else |
@@ -1539,32 +1576,42 @@ void __init early_init_lapic_mapping(void) | |||
1539 | */ | 1576 | */ |
1540 | void __init init_apic_mappings(void) | 1577 | void __init init_apic_mappings(void) |
1541 | { | 1578 | { |
1542 | if (x2apic) { | 1579 | unsigned int new_apicid; |
1580 | |||
1581 | if (x2apic_mode) { | ||
1543 | boot_cpu_physical_apicid = read_apic_id(); | 1582 | boot_cpu_physical_apicid = read_apic_id(); |
1544 | return; | 1583 | return; |
1545 | } | 1584 | } |
1546 | 1585 | ||
1547 | /* | 1586 | /* If no local APIC can be found return early */ |
1548 | * If no local APIC can be found then set up a fake all | ||
1549 | * zeroes page to simulate the local APIC and another | ||
1550 | * one for the IO-APIC. | ||
1551 | */ | ||
1552 | if (!smp_found_config && detect_init_APIC()) { | 1587 | if (!smp_found_config && detect_init_APIC()) { |
1553 | apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | 1588 | /* lets NOP'ify apic operations */ |
1554 | apic_phys = __pa(apic_phys); | 1589 | pr_info("APIC: disable apic facility\n"); |
1555 | } else | 1590 | apic_disable(); |
1591 | } else { | ||
1556 | apic_phys = mp_lapic_addr; | 1592 | apic_phys = mp_lapic_addr; |
1557 | 1593 | ||
1558 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 1594 | /* |
1559 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | 1595 | * acpi lapic path already maps that address in |
1560 | APIC_BASE, apic_phys); | 1596 | * acpi_register_lapic_address() |
1597 | */ | ||
1598 | if (!acpi_lapic) | ||
1599 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | ||
1600 | |||
1601 | apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", | ||
1602 | APIC_BASE, apic_phys); | ||
1603 | } | ||
1561 | 1604 | ||
1562 | /* | 1605 | /* |
1563 | * Fetch the APIC ID of the BSP in case we have a | 1606 | * Fetch the APIC ID of the BSP in case we have a |
1564 | * default configuration (or the MP table is broken). | 1607 | * default configuration (or the MP table is broken). |
1565 | */ | 1608 | */ |
1566 | if (boot_cpu_physical_apicid == -1U) | 1609 | new_apicid = read_apic_id(); |
1567 | boot_cpu_physical_apicid = read_apic_id(); | 1610 | if (boot_cpu_physical_apicid != new_apicid) { |
1611 | boot_cpu_physical_apicid = new_apicid; | ||
1612 | apic_version[new_apicid] = | ||
1613 | GET_APIC_VERSION(apic_read(APIC_LVR)); | ||
1614 | } | ||
1568 | } | 1615 | } |
1569 | 1616 | ||
1570 | /* | 1617 | /* |
@@ -1733,8 +1780,7 @@ void __init connect_bsp_APIC(void) | |||
1733 | */ | 1780 | */ |
1734 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " | 1781 | apic_printk(APIC_VERBOSE, "leaving PIC mode, " |
1735 | "enabling APIC mode.\n"); | 1782 | "enabling APIC mode.\n"); |
1736 | outb(0x70, 0x22); | 1783 | imcr_pic_to_apic(); |
1737 | outb(0x01, 0x23); | ||
1738 | } | 1784 | } |
1739 | #endif | 1785 | #endif |
1740 | if (apic->enable_apic_mode) | 1786 | if (apic->enable_apic_mode) |
@@ -1762,8 +1808,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
1762 | */ | 1808 | */ |
1763 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " | 1809 | apic_printk(APIC_VERBOSE, "disabling APIC mode, " |
1764 | "entering PIC mode.\n"); | 1810 | "entering PIC mode.\n"); |
1765 | outb(0x70, 0x22); | 1811 | imcr_apic_to_pic(); |
1766 | outb(0x00, 0x23); | ||
1767 | return; | 1812 | return; |
1768 | } | 1813 | } |
1769 | #endif | 1814 | #endif |
@@ -1969,10 +2014,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state) | |||
1969 | 2014 | ||
1970 | local_irq_save(flags); | 2015 | local_irq_save(flags); |
1971 | disable_local_APIC(); | 2016 | disable_local_APIC(); |
1972 | #ifdef CONFIG_INTR_REMAP | 2017 | |
1973 | if (intr_remapping_enabled) | 2018 | if (intr_remapping_enabled) |
1974 | disable_intr_remapping(); | 2019 | disable_intr_remapping(); |
1975 | #endif | 2020 | |
1976 | local_irq_restore(flags); | 2021 | local_irq_restore(flags); |
1977 | return 0; | 2022 | return 0; |
1978 | } | 2023 | } |
@@ -1982,8 +2027,6 @@ static int lapic_resume(struct sys_device *dev) | |||
1982 | unsigned int l, h; | 2027 | unsigned int l, h; |
1983 | unsigned long flags; | 2028 | unsigned long flags; |
1984 | int maxlvt; | 2029 | int maxlvt; |
1985 | |||
1986 | #ifdef CONFIG_INTR_REMAP | ||
1987 | int ret; | 2030 | int ret; |
1988 | struct IO_APIC_route_entry **ioapic_entries = NULL; | 2031 | struct IO_APIC_route_entry **ioapic_entries = NULL; |
1989 | 2032 | ||
@@ -1991,7 +2034,7 @@ static int lapic_resume(struct sys_device *dev) | |||
1991 | return 0; | 2034 | return 0; |
1992 | 2035 | ||
1993 | local_irq_save(flags); | 2036 | local_irq_save(flags); |
1994 | if (x2apic) { | 2037 | if (intr_remapping_enabled) { |
1995 | ioapic_entries = alloc_ioapic_entries(); | 2038 | ioapic_entries = alloc_ioapic_entries(); |
1996 | if (!ioapic_entries) { | 2039 | if (!ioapic_entries) { |
1997 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2040 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); |
@@ -2007,17 +2050,10 @@ static int lapic_resume(struct sys_device *dev) | |||
2007 | 2050 | ||
2008 | mask_IO_APIC_setup(ioapic_entries); | 2051 | mask_IO_APIC_setup(ioapic_entries); |
2009 | mask_8259A(); | 2052 | mask_8259A(); |
2010 | enable_x2apic(); | ||
2011 | } | 2053 | } |
2012 | #else | ||
2013 | if (!apic_pm_state.active) | ||
2014 | return 0; | ||
2015 | 2054 | ||
2016 | local_irq_save(flags); | 2055 | if (x2apic_mode) |
2017 | if (x2apic) | ||
2018 | enable_x2apic(); | 2056 | enable_x2apic(); |
2019 | #endif | ||
2020 | |||
2021 | else { | 2057 | else { |
2022 | /* | 2058 | /* |
2023 | * Make sure the APICBASE points to the right address | 2059 | * Make sure the APICBASE points to the right address |
@@ -2055,20 +2091,15 @@ static int lapic_resume(struct sys_device *dev) | |||
2055 | apic_write(APIC_ESR, 0); | 2091 | apic_write(APIC_ESR, 0); |
2056 | apic_read(APIC_ESR); | 2092 | apic_read(APIC_ESR); |
2057 | 2093 | ||
2058 | #ifdef CONFIG_INTR_REMAP | 2094 | if (intr_remapping_enabled) { |
2059 | if (intr_remapping_enabled) | 2095 | reenable_intr_remapping(x2apic_mode); |
2060 | reenable_intr_remapping(EIM_32BIT_APIC_ID); | ||
2061 | |||
2062 | if (x2apic) { | ||
2063 | unmask_8259A(); | 2096 | unmask_8259A(); |
2064 | restore_IO_APIC_setup(ioapic_entries); | 2097 | restore_IO_APIC_setup(ioapic_entries); |
2065 | free_ioapic_entries(ioapic_entries); | 2098 | free_ioapic_entries(ioapic_entries); |
2066 | } | 2099 | } |
2067 | #endif | ||
2068 | 2100 | ||
2069 | local_irq_restore(flags); | 2101 | local_irq_restore(flags); |
2070 | 2102 | ||
2071 | |||
2072 | return 0; | 2103 | return 0; |
2073 | } | 2104 | } |
2074 | 2105 | ||
@@ -2117,31 +2148,14 @@ static void apic_pm_activate(void) { } | |||
2117 | #endif /* CONFIG_PM */ | 2148 | #endif /* CONFIG_PM */ |
2118 | 2149 | ||
2119 | #ifdef CONFIG_X86_64 | 2150 | #ifdef CONFIG_X86_64 |
2120 | /* | 2151 | |
2121 | * apic_is_clustered_box() -- Check if we can expect good TSC | 2152 | 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 | { | 2153 | { |
2131 | int i, clusters, zeros; | 2154 | int i, clusters, zeros; |
2132 | unsigned id; | 2155 | unsigned id; |
2133 | u16 *bios_cpu_apicid; | 2156 | u16 *bios_cpu_apicid; |
2134 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); | 2157 | DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS); |
2135 | 2158 | ||
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); | 2159 | bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid); |
2146 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); | 2160 | bitmap_zero(clustermap, NUM_APIC_CLUSTERS); |
2147 | 2161 | ||
@@ -2177,18 +2191,67 @@ __cpuinit int apic_is_clustered_box(void) | |||
2177 | ++zeros; | 2191 | ++zeros; |
2178 | } | 2192 | } |
2179 | 2193 | ||
2180 | /* ScaleMP vSMPowered boxes have one cluster per board and TSCs are | 2194 | return clusters; |
2181 | * not guaranteed to be synced between boards | 2195 | } |
2182 | */ | 2196 | |
2183 | if (is_vsmp_box() && clusters > 1) | 2197 | static int __cpuinitdata multi_checked; |
2198 | static int __cpuinitdata multi; | ||
2199 | |||
2200 | static int __cpuinit set_multi(const struct dmi_system_id *d) | ||
2201 | { | ||
2202 | if (multi) | ||
2203 | return 0; | ||
2204 | pr_info("APIC: %s detected, Multi Chassis\n", d->ident); | ||
2205 | multi = 1; | ||
2206 | return 0; | ||
2207 | } | ||
2208 | |||
2209 | static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { | ||
2210 | { | ||
2211 | .callback = set_multi, | ||
2212 | .ident = "IBM System Summit2", | ||
2213 | .matches = { | ||
2214 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
2215 | DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"), | ||
2216 | }, | ||
2217 | }, | ||
2218 | {} | ||
2219 | }; | ||
2220 | |||
2221 | static void __cpuinit dmi_check_multi(void) | ||
2222 | { | ||
2223 | if (multi_checked) | ||
2224 | return; | ||
2225 | |||
2226 | dmi_check_system(multi_dmi_table); | ||
2227 | multi_checked = 1; | ||
2228 | } | ||
2229 | |||
2230 | /* | ||
2231 | * apic_is_clustered_box() -- Check if we can expect good TSC | ||
2232 | * | ||
2233 | * Thus far, the major user of this is IBM's Summit2 series: | ||
2234 | * Clustered boxes may have unsynced TSC problems if they are | ||
2235 | * multi-chassis. | ||
2236 | * Use DMI to check them | ||
2237 | */ | ||
2238 | __cpuinit int apic_is_clustered_box(void) | ||
2239 | { | ||
2240 | dmi_check_multi(); | ||
2241 | if (multi) | ||
2184 | return 1; | 2242 | return 1; |
2185 | 2243 | ||
2244 | if (!is_vsmp_box()) | ||
2245 | return 0; | ||
2246 | |||
2186 | /* | 2247 | /* |
2187 | * If clusters > 2, then should be multi-chassis. | 2248 | * ScaleMP vSMPowered boxes have one cluster per board and TSCs are |
2188 | * May have to revisit this when multi-core + hyperthreaded CPUs come | 2249 | * not guaranteed to be synced between boards |
2189 | * out, but AFAIK this will work even for them. | ||
2190 | */ | 2250 | */ |
2191 | return (clusters > 2); | 2251 | if (apic_cluster_num() > 1) |
2252 | return 1; | ||
2253 | |||
2254 | return 0; | ||
2192 | } | 2255 | } |
2193 | #endif | 2256 | #endif |
2194 | 2257 | ||