diff options
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 117 |
1 files changed, 51 insertions, 66 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fabf01eff771..b961af86bfea 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -505,7 +505,7 @@ static void __cpuinit setup_APIC_timer(void) | |||
505 | { | 505 | { |
506 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | 506 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
507 | 507 | ||
508 | if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_ARAT)) { | 508 | if (this_cpu_has(X86_FEATURE_ARAT)) { |
509 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP; | 509 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP; |
510 | /* Make LAPIC timer preferrable over percpu HPET */ | 510 | /* Make LAPIC timer preferrable over percpu HPET */ |
511 | lapic_clockevent.rating = 150; | 511 | lapic_clockevent.rating = 150; |
@@ -1237,6 +1237,17 @@ void __cpuinit setup_local_APIC(void) | |||
1237 | /* always use the value from LDR */ | 1237 | /* always use the value from LDR */ |
1238 | early_per_cpu(x86_cpu_to_logical_apicid, cpu) = | 1238 | early_per_cpu(x86_cpu_to_logical_apicid, cpu) = |
1239 | logical_smp_processor_id(); | 1239 | logical_smp_processor_id(); |
1240 | |||
1241 | /* | ||
1242 | * Some NUMA implementations (NUMAQ) don't initialize apicid to | ||
1243 | * node mapping during NUMA init. Now that logical apicid is | ||
1244 | * guaranteed to be known, give it another chance. This is already | ||
1245 | * a bit too late - percpu allocation has already happened without | ||
1246 | * proper NUMA affinity. | ||
1247 | */ | ||
1248 | if (apic->x86_32_numa_cpu_node) | ||
1249 | set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu), | ||
1250 | apic->x86_32_numa_cpu_node(cpu)); | ||
1240 | #endif | 1251 | #endif |
1241 | 1252 | ||
1242 | /* | 1253 | /* |
@@ -1450,7 +1461,6 @@ int __init enable_IR(void) | |||
1450 | void __init enable_IR_x2apic(void) | 1461 | void __init enable_IR_x2apic(void) |
1451 | { | 1462 | { |
1452 | unsigned long flags; | 1463 | unsigned long flags; |
1453 | struct IO_APIC_route_entry **ioapic_entries; | ||
1454 | int ret, x2apic_enabled = 0; | 1464 | int ret, x2apic_enabled = 0; |
1455 | int dmar_table_init_ret; | 1465 | int dmar_table_init_ret; |
1456 | 1466 | ||
@@ -1458,13 +1468,7 @@ void __init enable_IR_x2apic(void) | |||
1458 | if (dmar_table_init_ret && !x2apic_supported()) | 1468 | if (dmar_table_init_ret && !x2apic_supported()) |
1459 | return; | 1469 | return; |
1460 | 1470 | ||
1461 | ioapic_entries = alloc_ioapic_entries(); | 1471 | ret = save_ioapic_entries(); |
1462 | if (!ioapic_entries) { | ||
1463 | pr_err("Allocate ioapic_entries failed\n"); | ||
1464 | goto out; | ||
1465 | } | ||
1466 | |||
1467 | ret = save_IO_APIC_setup(ioapic_entries); | ||
1468 | if (ret) { | 1472 | if (ret) { |
1469 | pr_info("Saving IO-APIC state failed: %d\n", ret); | 1473 | pr_info("Saving IO-APIC state failed: %d\n", ret); |
1470 | goto out; | 1474 | goto out; |
@@ -1472,7 +1476,7 @@ void __init enable_IR_x2apic(void) | |||
1472 | 1476 | ||
1473 | local_irq_save(flags); | 1477 | local_irq_save(flags); |
1474 | legacy_pic->mask_all(); | 1478 | legacy_pic->mask_all(); |
1475 | mask_IO_APIC_setup(ioapic_entries); | 1479 | mask_ioapic_entries(); |
1476 | 1480 | ||
1477 | if (dmar_table_init_ret) | 1481 | if (dmar_table_init_ret) |
1478 | ret = 0; | 1482 | ret = 0; |
@@ -1503,14 +1507,11 @@ void __init enable_IR_x2apic(void) | |||
1503 | 1507 | ||
1504 | nox2apic: | 1508 | nox2apic: |
1505 | if (!ret) /* IR enabling failed */ | 1509 | if (!ret) /* IR enabling failed */ |
1506 | restore_IO_APIC_setup(ioapic_entries); | 1510 | restore_ioapic_entries(); |
1507 | legacy_pic->restore_mask(); | 1511 | legacy_pic->restore_mask(); |
1508 | local_irq_restore(flags); | 1512 | local_irq_restore(flags); |
1509 | 1513 | ||
1510 | out: | 1514 | out: |
1511 | if (ioapic_entries) | ||
1512 | free_ioapic_entries(ioapic_entries); | ||
1513 | |||
1514 | if (x2apic_enabled) | 1515 | if (x2apic_enabled) |
1515 | return; | 1516 | return; |
1516 | 1517 | ||
@@ -1812,30 +1813,41 @@ void smp_spurious_interrupt(struct pt_regs *regs) | |||
1812 | */ | 1813 | */ |
1813 | void smp_error_interrupt(struct pt_regs *regs) | 1814 | void smp_error_interrupt(struct pt_regs *regs) |
1814 | { | 1815 | { |
1815 | u32 v, v1; | 1816 | u32 v0, v1; |
1817 | u32 i = 0; | ||
1818 | static const char * const error_interrupt_reason[] = { | ||
1819 | "Send CS error", /* APIC Error Bit 0 */ | ||
1820 | "Receive CS error", /* APIC Error Bit 1 */ | ||
1821 | "Send accept error", /* APIC Error Bit 2 */ | ||
1822 | "Receive accept error", /* APIC Error Bit 3 */ | ||
1823 | "Redirectable IPI", /* APIC Error Bit 4 */ | ||
1824 | "Send illegal vector", /* APIC Error Bit 5 */ | ||
1825 | "Received illegal vector", /* APIC Error Bit 6 */ | ||
1826 | "Illegal register address", /* APIC Error Bit 7 */ | ||
1827 | }; | ||
1816 | 1828 | ||
1817 | exit_idle(); | 1829 | exit_idle(); |
1818 | irq_enter(); | 1830 | irq_enter(); |
1819 | /* First tickle the hardware, only then report what went on. -- REW */ | 1831 | /* First tickle the hardware, only then report what went on. -- REW */ |
1820 | v = apic_read(APIC_ESR); | 1832 | v0 = apic_read(APIC_ESR); |
1821 | apic_write(APIC_ESR, 0); | 1833 | apic_write(APIC_ESR, 0); |
1822 | v1 = apic_read(APIC_ESR); | 1834 | v1 = apic_read(APIC_ESR); |
1823 | ack_APIC_irq(); | 1835 | ack_APIC_irq(); |
1824 | atomic_inc(&irq_err_count); | 1836 | atomic_inc(&irq_err_count); |
1825 | 1837 | ||
1826 | /* | 1838 | apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)", |
1827 | * Here is what the APIC error bits mean: | 1839 | smp_processor_id(), v0 , v1); |
1828 | * 0: Send CS error | 1840 | |
1829 | * 1: Receive CS error | 1841 | v1 = v1 & 0xff; |
1830 | * 2: Send accept error | 1842 | while (v1) { |
1831 | * 3: Receive accept error | 1843 | if (v1 & 0x1) |
1832 | * 4: Reserved | 1844 | apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]); |
1833 | * 5: Send illegal vector | 1845 | i++; |
1834 | * 6: Received illegal vector | 1846 | v1 >>= 1; |
1835 | * 7: Illegal register address | 1847 | }; |
1836 | */ | 1848 | |
1837 | pr_debug("APIC error on CPU%d: %02x(%02x)\n", | 1849 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); |
1838 | smp_processor_id(), v , v1); | 1850 | |
1839 | irq_exit(); | 1851 | irq_exit(); |
1840 | } | 1852 | } |
1841 | 1853 | ||
@@ -2003,21 +2015,6 @@ void default_init_apic_ldr(void) | |||
2003 | apic_write(APIC_LDR, val); | 2015 | apic_write(APIC_LDR, val); |
2004 | } | 2016 | } |
2005 | 2017 | ||
2006 | #ifdef CONFIG_X86_32 | ||
2007 | int default_x86_32_numa_cpu_node(int cpu) | ||
2008 | { | ||
2009 | #ifdef CONFIG_NUMA | ||
2010 | int apicid = early_per_cpu(x86_cpu_to_apicid, cpu); | ||
2011 | |||
2012 | if (apicid != BAD_APICID) | ||
2013 | return __apicid_to_node[apicid]; | ||
2014 | return NUMA_NO_NODE; | ||
2015 | #else | ||
2016 | return 0; | ||
2017 | #endif | ||
2018 | } | ||
2019 | #endif | ||
2020 | |||
2021 | /* | 2018 | /* |
2022 | * Power management | 2019 | * Power management |
2023 | */ | 2020 | */ |
@@ -2088,28 +2085,20 @@ static void lapic_resume(void) | |||
2088 | { | 2085 | { |
2089 | unsigned int l, h; | 2086 | unsigned int l, h; |
2090 | unsigned long flags; | 2087 | unsigned long flags; |
2091 | int maxlvt, ret; | 2088 | int maxlvt; |
2092 | struct IO_APIC_route_entry **ioapic_entries = NULL; | ||
2093 | 2089 | ||
2094 | if (!apic_pm_state.active) | 2090 | if (!apic_pm_state.active) |
2095 | return; | 2091 | return; |
2096 | 2092 | ||
2097 | local_irq_save(flags); | 2093 | local_irq_save(flags); |
2098 | if (intr_remapping_enabled) { | 2094 | if (intr_remapping_enabled) { |
2099 | ioapic_entries = alloc_ioapic_entries(); | 2095 | /* |
2100 | if (!ioapic_entries) { | 2096 | * IO-APIC and PIC have their own resume routines. |
2101 | WARN(1, "Alloc ioapic_entries in lapic resume failed."); | 2097 | * We just mask them here to make sure the interrupt |
2102 | goto restore; | 2098 | * subsystem is completely quiet while we enable x2apic |
2103 | } | 2099 | * and interrupt-remapping. |
2104 | 2100 | */ | |
2105 | ret = save_IO_APIC_setup(ioapic_entries); | 2101 | mask_ioapic_entries(); |
2106 | if (ret) { | ||
2107 | WARN(1, "Saving IO-APIC state failed: %d\n", ret); | ||
2108 | free_ioapic_entries(ioapic_entries); | ||
2109 | goto restore; | ||
2110 | } | ||
2111 | |||
2112 | mask_IO_APIC_setup(ioapic_entries); | ||
2113 | legacy_pic->mask_all(); | 2102 | legacy_pic->mask_all(); |
2114 | } | 2103 | } |
2115 | 2104 | ||
@@ -2152,13 +2141,9 @@ static void lapic_resume(void) | |||
2152 | apic_write(APIC_ESR, 0); | 2141 | apic_write(APIC_ESR, 0); |
2153 | apic_read(APIC_ESR); | 2142 | apic_read(APIC_ESR); |
2154 | 2143 | ||
2155 | if (intr_remapping_enabled) { | 2144 | if (intr_remapping_enabled) |
2156 | reenable_intr_remapping(x2apic_mode); | 2145 | reenable_intr_remapping(x2apic_mode); |
2157 | legacy_pic->restore_mask(); | 2146 | |
2158 | restore_IO_APIC_setup(ioapic_entries); | ||
2159 | free_ioapic_entries(ioapic_entries); | ||
2160 | } | ||
2161 | restore: | ||
2162 | local_irq_restore(flags); | 2147 | local_irq_restore(flags); |
2163 | } | 2148 | } |
2164 | 2149 | ||