diff options
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r-- | arch/x86/kernel/io_apic_64.c | 114 |
1 files changed, 104 insertions, 10 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index cbac1670c7c3..1627c0d53e0b 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c | |||
@@ -32,9 +32,11 @@ | |||
32 | #include <linux/msi.h> | 32 | #include <linux/msi.h> |
33 | #include <linux/htirq.h> | 33 | #include <linux/htirq.h> |
34 | #include <linux/dmar.h> | 34 | #include <linux/dmar.h> |
35 | #include <linux/jiffies.h> | ||
35 | #ifdef CONFIG_ACPI | 36 | #ifdef CONFIG_ACPI |
36 | #include <acpi/acpi_bus.h> | 37 | #include <acpi/acpi_bus.h> |
37 | #endif | 38 | #endif |
39 | #include <linux/bootmem.h> | ||
38 | 40 | ||
39 | #include <asm/idle.h> | 41 | #include <asm/idle.h> |
40 | #include <asm/io.h> | 42 | #include <asm/io.h> |
@@ -1069,7 +1071,7 @@ void __apicdebuginit print_local_APIC(void * dummy) | |||
1069 | v = apic_read(APIC_LVR); | 1071 | v = apic_read(APIC_LVR); |
1070 | printk(KERN_INFO "... APIC VERSION: %08x\n", v); | 1072 | printk(KERN_INFO "... APIC VERSION: %08x\n", v); |
1071 | ver = GET_APIC_VERSION(v); | 1073 | ver = GET_APIC_VERSION(v); |
1072 | maxlvt = get_maxlvt(); | 1074 | maxlvt = lapic_get_maxlvt(); |
1073 | 1075 | ||
1074 | v = apic_read(APIC_TASKPRI); | 1076 | v = apic_read(APIC_TASKPRI); |
1075 | printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK); | 1077 | printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK); |
@@ -1171,7 +1173,7 @@ void __apicdebuginit print_PIC(void) | |||
1171 | 1173 | ||
1172 | #endif /* 0 */ | 1174 | #endif /* 0 */ |
1173 | 1175 | ||
1174 | static void __init enable_IO_APIC(void) | 1176 | void __init enable_IO_APIC(void) |
1175 | { | 1177 | { |
1176 | union IO_APIC_reg_01 reg_01; | 1178 | union IO_APIC_reg_01 reg_01; |
1177 | int i8259_apic, i8259_pin; | 1179 | int i8259_apic, i8259_pin; |
@@ -1298,7 +1300,7 @@ static int __init timer_irq_works(void) | |||
1298 | */ | 1300 | */ |
1299 | 1301 | ||
1300 | /* jiffies wrap? */ | 1302 | /* jiffies wrap? */ |
1301 | if (jiffies - t1 > 4) | 1303 | if (time_after(jiffies, t1 + 4)) |
1302 | return 1; | 1304 | return 1; |
1303 | return 0; | 1305 | return 0; |
1304 | } | 1306 | } |
@@ -1411,7 +1413,7 @@ static void irq_complete_move(unsigned int irq) | |||
1411 | if (likely(!cfg->move_in_progress)) | 1413 | if (likely(!cfg->move_in_progress)) |
1412 | return; | 1414 | return; |
1413 | 1415 | ||
1414 | vector = ~get_irq_regs()->orig_rax; | 1416 | vector = ~get_irq_regs()->orig_ax; |
1415 | me = smp_processor_id(); | 1417 | me = smp_processor_id(); |
1416 | if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) { | 1418 | if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) { |
1417 | cpumask_t cleanup_mask; | 1419 | cpumask_t cleanup_mask; |
@@ -1438,7 +1440,7 @@ static void ack_apic_level(unsigned int irq) | |||
1438 | int do_unmask_irq = 0; | 1440 | int do_unmask_irq = 0; |
1439 | 1441 | ||
1440 | irq_complete_move(irq); | 1442 | irq_complete_move(irq); |
1441 | #if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) | 1443 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
1442 | /* If we are moving the irq we need to mask it */ | 1444 | /* If we are moving the irq we need to mask it */ |
1443 | if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) { | 1445 | if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) { |
1444 | do_unmask_irq = 1; | 1446 | do_unmask_irq = 1; |
@@ -1565,7 +1567,7 @@ static struct hw_interrupt_type lapic_irq_type __read_mostly = { | |||
1565 | .end = end_lapic_irq, | 1567 | .end = end_lapic_irq, |
1566 | }; | 1568 | }; |
1567 | 1569 | ||
1568 | static void setup_nmi (void) | 1570 | static void __init setup_nmi(void) |
1569 | { | 1571 | { |
1570 | /* | 1572 | /* |
1571 | * Dirty trick to enable the NMI watchdog ... | 1573 | * Dirty trick to enable the NMI watchdog ... |
@@ -1578,7 +1580,7 @@ static void setup_nmi (void) | |||
1578 | */ | 1580 | */ |
1579 | printk(KERN_INFO "activating NMI Watchdog ..."); | 1581 | printk(KERN_INFO "activating NMI Watchdog ..."); |
1580 | 1582 | ||
1581 | enable_NMI_through_LVT0(NULL); | 1583 | enable_NMI_through_LVT0(); |
1582 | 1584 | ||
1583 | printk(" done.\n"); | 1585 | printk(" done.\n"); |
1584 | } | 1586 | } |
@@ -1654,7 +1656,7 @@ static inline void unlock_ExtINT_logic(void) | |||
1654 | * | 1656 | * |
1655 | * FIXME: really need to revamp this for modern platforms only. | 1657 | * FIXME: really need to revamp this for modern platforms only. |
1656 | */ | 1658 | */ |
1657 | static inline void check_timer(void) | 1659 | static inline void __init check_timer(void) |
1658 | { | 1660 | { |
1659 | struct irq_cfg *cfg = irq_cfg + 0; | 1661 | struct irq_cfg *cfg = irq_cfg + 0; |
1660 | int apic1, pin1, apic2, pin2; | 1662 | int apic1, pin1, apic2, pin2; |
@@ -1788,7 +1790,10 @@ __setup("no_timer_check", notimercheck); | |||
1788 | 1790 | ||
1789 | void __init setup_IO_APIC(void) | 1791 | void __init setup_IO_APIC(void) |
1790 | { | 1792 | { |
1791 | enable_IO_APIC(); | 1793 | |
1794 | /* | ||
1795 | * calling enable_IO_APIC() is moved to setup_local_APIC for BP | ||
1796 | */ | ||
1792 | 1797 | ||
1793 | if (acpi_ioapic) | 1798 | if (acpi_ioapic) |
1794 | io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ | 1799 | io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ |
@@ -1850,7 +1855,7 @@ static int ioapic_resume(struct sys_device *dev) | |||
1850 | } | 1855 | } |
1851 | 1856 | ||
1852 | static struct sysdev_class ioapic_sysdev_class = { | 1857 | static struct sysdev_class ioapic_sysdev_class = { |
1853 | set_kset_name("ioapic"), | 1858 | .name = "ioapic", |
1854 | .suspend = ioapic_suspend, | 1859 | .suspend = ioapic_suspend, |
1855 | .resume = ioapic_resume, | 1860 | .resume = ioapic_resume, |
1856 | }; | 1861 | }; |
@@ -2288,3 +2293,92 @@ void __init setup_ioapic_dest(void) | |||
2288 | } | 2293 | } |
2289 | #endif | 2294 | #endif |
2290 | 2295 | ||
2296 | #define IOAPIC_RESOURCE_NAME_SIZE 11 | ||
2297 | |||
2298 | static struct resource *ioapic_resources; | ||
2299 | |||
2300 | static struct resource * __init ioapic_setup_resources(void) | ||
2301 | { | ||
2302 | unsigned long n; | ||
2303 | struct resource *res; | ||
2304 | char *mem; | ||
2305 | int i; | ||
2306 | |||
2307 | if (nr_ioapics <= 0) | ||
2308 | return NULL; | ||
2309 | |||
2310 | n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource); | ||
2311 | n *= nr_ioapics; | ||
2312 | |||
2313 | mem = alloc_bootmem(n); | ||
2314 | res = (void *)mem; | ||
2315 | |||
2316 | if (mem != NULL) { | ||
2317 | memset(mem, 0, n); | ||
2318 | mem += sizeof(struct resource) * nr_ioapics; | ||
2319 | |||
2320 | for (i = 0; i < nr_ioapics; i++) { | ||
2321 | res[i].name = mem; | ||
2322 | res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
2323 | sprintf(mem, "IOAPIC %u", i); | ||
2324 | mem += IOAPIC_RESOURCE_NAME_SIZE; | ||
2325 | } | ||
2326 | } | ||
2327 | |||
2328 | ioapic_resources = res; | ||
2329 | |||
2330 | return res; | ||
2331 | } | ||
2332 | |||
2333 | void __init ioapic_init_mappings(void) | ||
2334 | { | ||
2335 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | ||
2336 | struct resource *ioapic_res; | ||
2337 | int i; | ||
2338 | |||
2339 | ioapic_res = ioapic_setup_resources(); | ||
2340 | for (i = 0; i < nr_ioapics; i++) { | ||
2341 | if (smp_found_config) { | ||
2342 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; | ||
2343 | } else { | ||
2344 | ioapic_phys = (unsigned long) | ||
2345 | alloc_bootmem_pages(PAGE_SIZE); | ||
2346 | ioapic_phys = __pa(ioapic_phys); | ||
2347 | } | ||
2348 | set_fixmap_nocache(idx, ioapic_phys); | ||
2349 | apic_printk(APIC_VERBOSE, | ||
2350 | "mapped IOAPIC to %016lx (%016lx)\n", | ||
2351 | __fix_to_virt(idx), ioapic_phys); | ||
2352 | idx++; | ||
2353 | |||
2354 | if (ioapic_res != NULL) { | ||
2355 | ioapic_res->start = ioapic_phys; | ||
2356 | ioapic_res->end = ioapic_phys + (4 * 1024) - 1; | ||
2357 | ioapic_res++; | ||
2358 | } | ||
2359 | } | ||
2360 | } | ||
2361 | |||
2362 | static int __init ioapic_insert_resources(void) | ||
2363 | { | ||
2364 | int i; | ||
2365 | struct resource *r = ioapic_resources; | ||
2366 | |||
2367 | if (!r) { | ||
2368 | printk(KERN_ERR | ||
2369 | "IO APIC resources could be not be allocated.\n"); | ||
2370 | return -1; | ||
2371 | } | ||
2372 | |||
2373 | for (i = 0; i < nr_ioapics; i++) { | ||
2374 | insert_resource(&iomem_resource, r); | ||
2375 | r++; | ||
2376 | } | ||
2377 | |||
2378 | return 0; | ||
2379 | } | ||
2380 | |||
2381 | /* Insert the IO APIC resources after PCI initialization has occured to handle | ||
2382 | * IO APICS that are mapped in on a BAR in PCI space. */ | ||
2383 | late_initcall(ioapic_insert_resources); | ||
2384 | |||