aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c114
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
1174static void __init enable_IO_APIC(void) 1176void __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
1568static void setup_nmi (void) 1570static 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 */
1657static inline void check_timer(void) 1659static 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
1789void __init setup_IO_APIC(void) 1791void __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
1852static struct sysdev_class ioapic_sysdev_class = { 1857static 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
2298static struct resource *ioapic_resources;
2299
2300static 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
2333void __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
2362static 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. */
2383late_initcall(ioapic_insert_resources);
2384