diff options
author | Len Brown <len.brown@intel.com> | 2009-09-19 00:11:26 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-09-19 00:11:26 -0400 |
commit | c602c65b2f81d14456771d1e3f15d1381f4b7efa (patch) | |
tree | f1f833c8dd6c1519eeb101be32f7fe54a9605af5 /arch/x86/kernel/apic/apic.c | |
parent | 3834f47291df475be3f0f0fb7ccaa098967cc054 (diff) | |
parent | 78f28b7c555359c67c2a0d23f7436e915329421e (diff) |
Merge branch 'linus' into sfi-release
Conflicts:
arch/x86/kernel/setup.c
drivers/acpi/power.c
init/main.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 113 |
1 files changed, 61 insertions, 52 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 0a1c2830ec66..a34601f52987 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
37 | 37 | ||
38 | #include <asm/perf_counter.h> | 38 | #include <asm/perf_counter.h> |
39 | #include <asm/x86_init.h> | ||
39 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
40 | #include <asm/atomic.h> | 41 | #include <asm/atomic.h> |
41 | #include <asm/mpspec.h> | 42 | #include <asm/mpspec.h> |
@@ -49,6 +50,7 @@ | |||
49 | #include <asm/mtrr.h> | 50 | #include <asm/mtrr.h> |
50 | #include <asm/smp.h> | 51 | #include <asm/smp.h> |
51 | #include <asm/mce.h> | 52 | #include <asm/mce.h> |
53 | #include <asm/kvm_para.h> | ||
52 | 54 | ||
53 | unsigned int num_processors; | 55 | unsigned int num_processors; |
54 | 56 | ||
@@ -1361,52 +1363,80 @@ void enable_x2apic(void) | |||
1361 | } | 1363 | } |
1362 | #endif /* CONFIG_X86_X2APIC */ | 1364 | #endif /* CONFIG_X86_X2APIC */ |
1363 | 1365 | ||
1364 | void __init enable_IR_x2apic(void) | 1366 | int __init enable_IR(void) |
1365 | { | 1367 | { |
1366 | #ifdef CONFIG_INTR_REMAP | 1368 | #ifdef CONFIG_INTR_REMAP |
1367 | int ret; | ||
1368 | unsigned long flags; | ||
1369 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1370 | |||
1371 | ret = dmar_table_init(); | ||
1372 | if (ret) { | ||
1373 | pr_debug("dmar_table_init() failed with %d:\n", ret); | ||
1374 | goto ir_failed; | ||
1375 | } | ||
1376 | |||
1377 | if (!intr_remapping_supported()) { | 1369 | if (!intr_remapping_supported()) { |
1378 | pr_debug("intr-remapping not supported\n"); | 1370 | pr_debug("intr-remapping not supported\n"); |
1379 | goto ir_failed; | 1371 | return 0; |
1380 | } | 1372 | } |
1381 | 1373 | ||
1382 | |||
1383 | if (!x2apic_preenabled && skip_ioapic_setup) { | 1374 | if (!x2apic_preenabled && skip_ioapic_setup) { |
1384 | pr_info("Skipped enabling intr-remap because of skipping " | 1375 | pr_info("Skipped enabling intr-remap because of skipping " |
1385 | "io-apic setup\n"); | 1376 | "io-apic setup\n"); |
1386 | return; | 1377 | return 0; |
1387 | } | 1378 | } |
1388 | 1379 | ||
1380 | if (enable_intr_remapping(x2apic_supported())) | ||
1381 | return 0; | ||
1382 | |||
1383 | pr_info("Enabled Interrupt-remapping\n"); | ||
1384 | |||
1385 | return 1; | ||
1386 | |||
1387 | #endif | ||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | void __init enable_IR_x2apic(void) | ||
1392 | { | ||
1393 | unsigned long flags; | ||
1394 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
1395 | int ret, x2apic_enabled = 0; | ||
1396 | int dmar_table_init_ret = 0; | ||
1397 | |||
1398 | #ifdef CONFIG_INTR_REMAP | ||
1399 | dmar_table_init_ret = dmar_table_init(); | ||
1400 | if (dmar_table_init_ret) | ||
1401 | pr_debug("dmar_table_init() failed with %d:\n", | ||
1402 | dmar_table_init_ret); | ||
1403 | #endif | ||
1404 | |||
1389 | ioapic_entries = alloc_ioapic_entries(); | 1405 | ioapic_entries = alloc_ioapic_entries(); |
1390 | if (!ioapic_entries) { | 1406 | if (!ioapic_entries) { |
1391 | pr_info("Allocate ioapic_entries failed: %d\n", ret); | 1407 | pr_err("Allocate ioapic_entries failed\n"); |
1392 | goto end; | 1408 | goto out; |
1393 | } | 1409 | } |
1394 | 1410 | ||
1395 | ret = save_IO_APIC_setup(ioapic_entries); | 1411 | ret = save_IO_APIC_setup(ioapic_entries); |
1396 | if (ret) { | 1412 | if (ret) { |
1397 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1413 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1398 | goto end; | 1414 | goto out; |
1399 | } | 1415 | } |
1400 | 1416 | ||
1401 | local_irq_save(flags); | 1417 | local_irq_save(flags); |
1402 | mask_IO_APIC_setup(ioapic_entries); | ||
1403 | mask_8259A(); | 1418 | mask_8259A(); |
1419 | mask_IO_APIC_setup(ioapic_entries); | ||
1404 | 1420 | ||
1405 | ret = enable_intr_remapping(x2apic_supported()); | 1421 | if (dmar_table_init_ret) |
1406 | if (ret) | 1422 | ret = 0; |
1407 | goto end_restore; | 1423 | else |
1424 | ret = enable_IR(); | ||
1408 | 1425 | ||
1409 | pr_info("Enabled Interrupt-remapping\n"); | 1426 | if (!ret) { |
1427 | /* IR is required if there is APIC ID > 255 even when running | ||
1428 | * under KVM | ||
1429 | */ | ||
1430 | if (max_physical_apicid > 255 || !kvm_para_available()) | ||
1431 | goto nox2apic; | ||
1432 | /* | ||
1433 | * without IR all CPUs can be addressed by IOAPIC/MSI | ||
1434 | * only in physical mode | ||
1435 | */ | ||
1436 | x2apic_force_phys(); | ||
1437 | } | ||
1438 | |||
1439 | x2apic_enabled = 1; | ||
1410 | 1440 | ||
1411 | if (x2apic_supported() && !x2apic_mode) { | 1441 | if (x2apic_supported() && !x2apic_mode) { |
1412 | x2apic_mode = 1; | 1442 | x2apic_mode = 1; |
@@ -1414,41 +1444,25 @@ void __init enable_IR_x2apic(void) | |||
1414 | pr_info("Enabled x2apic\n"); | 1444 | pr_info("Enabled x2apic\n"); |
1415 | } | 1445 | } |
1416 | 1446 | ||
1417 | end_restore: | 1447 | nox2apic: |
1418 | if (ret) | 1448 | if (!ret) /* IR enabling failed */ |
1419 | /* | ||
1420 | * IR enabling failed | ||
1421 | */ | ||
1422 | restore_IO_APIC_setup(ioapic_entries); | 1449 | restore_IO_APIC_setup(ioapic_entries); |
1423 | |||
1424 | unmask_8259A(); | 1450 | unmask_8259A(); |
1425 | local_irq_restore(flags); | 1451 | local_irq_restore(flags); |
1426 | 1452 | ||
1427 | end: | 1453 | out: |
1428 | if (ioapic_entries) | 1454 | if (ioapic_entries) |
1429 | free_ioapic_entries(ioapic_entries); | 1455 | free_ioapic_entries(ioapic_entries); |
1430 | 1456 | ||
1431 | if (!ret) | 1457 | if (x2apic_enabled) |
1432 | return; | 1458 | return; |
1433 | 1459 | ||
1434 | ir_failed: | ||
1435 | if (x2apic_preenabled) | 1460 | if (x2apic_preenabled) |
1436 | panic("x2apic enabled by bios. But IR enabling failed"); | 1461 | panic("x2apic: enabled by BIOS but kernel init failed."); |
1437 | else if (cpu_has_x2apic) | 1462 | else if (cpu_has_x2apic) |
1438 | pr_info("Not enabling x2apic,Intr-remapping\n"); | 1463 | pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); |
1439 | #else | ||
1440 | if (!cpu_has_x2apic) | ||
1441 | return; | ||
1442 | |||
1443 | if (x2apic_preenabled) | ||
1444 | panic("x2apic enabled prior OS handover," | ||
1445 | " enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP"); | ||
1446 | #endif | ||
1447 | |||
1448 | return; | ||
1449 | } | 1464 | } |
1450 | 1465 | ||
1451 | |||
1452 | #ifdef CONFIG_X86_64 | 1466 | #ifdef CONFIG_X86_64 |
1453 | /* | 1467 | /* |
1454 | * Detect and enable local APICs on non-SMP boards. | 1468 | * Detect and enable local APICs on non-SMP boards. |
@@ -1549,8 +1563,6 @@ no_apic: | |||
1549 | #ifdef CONFIG_X86_64 | 1563 | #ifdef CONFIG_X86_64 |
1550 | void __init early_init_lapic_mapping(void) | 1564 | void __init early_init_lapic_mapping(void) |
1551 | { | 1565 | { |
1552 | unsigned long phys_addr; | ||
1553 | |||
1554 | /* | 1566 | /* |
1555 | * If no local APIC can be found then go out | 1567 | * If no local APIC can be found then go out |
1556 | * : it means there is no mpatable and MADT | 1568 | * : it means there is no mpatable and MADT |
@@ -1558,11 +1570,9 @@ void __init early_init_lapic_mapping(void) | |||
1558 | if (!smp_found_config) | 1570 | if (!smp_found_config) |
1559 | return; | 1571 | return; |
1560 | 1572 | ||
1561 | phys_addr = mp_lapic_addr; | 1573 | set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); |
1562 | |||
1563 | set_fixmap_nocache(FIX_APIC_BASE, phys_addr); | ||
1564 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", | 1574 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", |
1565 | APIC_BASE, phys_addr); | 1575 | APIC_BASE, mp_lapic_addr); |
1566 | 1576 | ||
1567 | /* | 1577 | /* |
1568 | * Fetch the APIC ID of the BSP in case we have a | 1578 | * Fetch the APIC ID of the BSP in case we have a |
@@ -1651,7 +1661,6 @@ int __init APIC_init_uniprocessor(void) | |||
1651 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { | 1661 | APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { |
1652 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", | 1662 | pr_err("BIOS bug, local APIC 0x%x not detected!...\n", |
1653 | boot_cpu_physical_apicid); | 1663 | boot_cpu_physical_apicid); |
1654 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1655 | return -1; | 1664 | return -1; |
1656 | } | 1665 | } |
1657 | #endif | 1666 | #endif |
@@ -1701,7 +1710,7 @@ int __init APIC_init_uniprocessor(void) | |||
1701 | localise_nmi_watchdog(); | 1710 | localise_nmi_watchdog(); |
1702 | #endif | 1711 | #endif |
1703 | 1712 | ||
1704 | setup_boot_clock(); | 1713 | x86_init.timers.setup_percpu_clockev(); |
1705 | #ifdef CONFIG_X86_64 | 1714 | #ifdef CONFIG_X86_64 |
1706 | check_nmi_watchdog(); | 1715 | check_nmi_watchdog(); |
1707 | #endif | 1716 | #endif |