diff options
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r-- | arch/x86/kernel/io_apic_64.c | 282 |
1 files changed, 162 insertions, 120 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index ef1a8dfcc529..6510cde36b35 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c | |||
@@ -61,7 +61,7 @@ struct irq_cfg { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ | 63 | /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */ |
64 | struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { | 64 | static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { |
65 | [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, | 65 | [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, }, |
66 | [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, | 66 | [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, }, |
67 | [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, | 67 | [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, }, |
@@ -82,6 +82,10 @@ struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = { | |||
82 | 82 | ||
83 | static int assign_irq_vector(int irq, cpumask_t mask); | 83 | static int assign_irq_vector(int irq, cpumask_t mask); |
84 | 84 | ||
85 | int first_system_vector = 0xfe; | ||
86 | |||
87 | char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE}; | ||
88 | |||
85 | #define __apicdebuginit __init | 89 | #define __apicdebuginit __init |
86 | 90 | ||
87 | int sis_apic_bug; /* not actually supported, dummy for compile */ | 91 | int sis_apic_bug; /* not actually supported, dummy for compile */ |
@@ -90,7 +94,7 @@ static int no_timer_check; | |||
90 | 94 | ||
91 | static int disable_timer_pin_1 __initdata; | 95 | static int disable_timer_pin_1 __initdata; |
92 | 96 | ||
93 | int timer_over_8254 __initdata = 1; | 97 | int timer_through_8259 __initdata; |
94 | 98 | ||
95 | /* Where if anywhere is the i8259 connect in external int mode */ | 99 | /* Where if anywhere is the i8259 connect in external int mode */ |
96 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; | 100 | static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; |
@@ -104,15 +108,17 @@ DEFINE_SPINLOCK(vector_lock); | |||
104 | int nr_ioapic_registers[MAX_IO_APICS]; | 108 | int nr_ioapic_registers[MAX_IO_APICS]; |
105 | 109 | ||
106 | /* I/O APIC entries */ | 110 | /* I/O APIC entries */ |
107 | struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; | 111 | struct mp_config_ioapic mp_ioapics[MAX_IO_APICS]; |
108 | int nr_ioapics; | 112 | int nr_ioapics; |
109 | 113 | ||
110 | /* MP IRQ source entries */ | 114 | /* MP IRQ source entries */ |
111 | struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; | 115 | struct mp_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; |
112 | 116 | ||
113 | /* # of MP IRQ source entries */ | 117 | /* # of MP IRQ source entries */ |
114 | int mp_irq_entries; | 118 | int mp_irq_entries; |
115 | 119 | ||
120 | DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES); | ||
121 | |||
116 | /* | 122 | /* |
117 | * Rough estimation of how many shared IRQs there are, can | 123 | * Rough estimation of how many shared IRQs there are, can |
118 | * be changed anytime. | 124 | * be changed anytime. |
@@ -140,7 +146,7 @@ struct io_apic { | |||
140 | static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) | 146 | static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx) |
141 | { | 147 | { |
142 | return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx) | 148 | return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx) |
143 | + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK); | 149 | + (mp_ioapics[idx].mp_apicaddr & ~PAGE_MASK); |
144 | } | 150 | } |
145 | 151 | ||
146 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | 152 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) |
@@ -183,7 +189,7 @@ static bool io_apic_level_ack_pending(unsigned int irq) | |||
183 | break; | 189 | break; |
184 | reg = io_apic_read(entry->apic, 0x10 + pin*2); | 190 | reg = io_apic_read(entry->apic, 0x10 + pin*2); |
185 | /* Is the remote IRR bit set? */ | 191 | /* Is the remote IRR bit set? */ |
186 | if ((reg >> 14) & 1) { | 192 | if (reg & IO_APIC_REDIR_REMOTE_IRR) { |
187 | spin_unlock_irqrestore(&ioapic_lock, flags); | 193 | spin_unlock_irqrestore(&ioapic_lock, flags); |
188 | return true; | 194 | return true; |
189 | } | 195 | } |
@@ -298,7 +304,7 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector) | |||
298 | break; | 304 | break; |
299 | io_apic_write(apic, 0x11 + pin*2, dest); | 305 | io_apic_write(apic, 0x11 + pin*2, dest); |
300 | reg = io_apic_read(apic, 0x10 + pin*2); | 306 | reg = io_apic_read(apic, 0x10 + pin*2); |
301 | reg &= ~0x000000ff; | 307 | reg &= ~IO_APIC_REDIR_VECTOR_MASK; |
302 | reg |= vector; | 308 | reg |= vector; |
303 | io_apic_modify(apic, reg); | 309 | io_apic_modify(apic, reg); |
304 | if (!entry->next) | 310 | if (!entry->next) |
@@ -360,16 +366,37 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin) | |||
360 | entry->pin = pin; | 366 | entry->pin = pin; |
361 | } | 367 | } |
362 | 368 | ||
369 | /* | ||
370 | * Reroute an IRQ to a different pin. | ||
371 | */ | ||
372 | static void __init replace_pin_at_irq(unsigned int irq, | ||
373 | int oldapic, int oldpin, | ||
374 | int newapic, int newpin) | ||
375 | { | ||
376 | struct irq_pin_list *entry = irq_2_pin + irq; | ||
377 | |||
378 | while (1) { | ||
379 | if (entry->apic == oldapic && entry->pin == oldpin) { | ||
380 | entry->apic = newapic; | ||
381 | entry->pin = newpin; | ||
382 | } | ||
383 | if (!entry->next) | ||
384 | break; | ||
385 | entry = irq_2_pin + entry->next; | ||
386 | } | ||
387 | } | ||
388 | |||
363 | 389 | ||
364 | #define DO_ACTION(name,R,ACTION, FINAL) \ | 390 | #define DO_ACTION(name,R,ACTION, FINAL) \ |
365 | \ | 391 | \ |
366 | static void name##_IO_APIC_irq (unsigned int irq) \ | 392 | static void name##_IO_APIC_irq (unsigned int irq) \ |
367 | __DO_ACTION(R, ACTION, FINAL) | 393 | __DO_ACTION(R, ACTION, FINAL) |
368 | 394 | ||
369 | DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) | 395 | /* mask = 1 */ |
370 | /* mask = 1 */ | 396 | DO_ACTION(__mask, 0, |= IO_APIC_REDIR_MASKED, io_apic_sync(entry->apic)) |
371 | DO_ACTION( __unmask, 0, &= 0xfffeffff, ) | 397 | |
372 | /* mask = 0 */ | 398 | /* mask = 0 */ |
399 | DO_ACTION(__unmask, 0, &= ~IO_APIC_REDIR_MASKED, ) | ||
373 | 400 | ||
374 | static void mask_IO_APIC_irq (unsigned int irq) | 401 | static void mask_IO_APIC_irq (unsigned int irq) |
375 | { | 402 | { |
@@ -430,20 +457,6 @@ static int __init disable_timer_pin_setup(char *arg) | |||
430 | } | 457 | } |
431 | __setup("disable_timer_pin_1", disable_timer_pin_setup); | 458 | __setup("disable_timer_pin_1", disable_timer_pin_setup); |
432 | 459 | ||
433 | static int __init setup_disable_8254_timer(char *s) | ||
434 | { | ||
435 | timer_over_8254 = -1; | ||
436 | return 1; | ||
437 | } | ||
438 | static int __init setup_enable_8254_timer(char *s) | ||
439 | { | ||
440 | timer_over_8254 = 2; | ||
441 | return 1; | ||
442 | } | ||
443 | |||
444 | __setup("disable_8254_timer", setup_disable_8254_timer); | ||
445 | __setup("enable_8254_timer", setup_enable_8254_timer); | ||
446 | |||
447 | 460 | ||
448 | /* | 461 | /* |
449 | * Find the IRQ entry number of a certain pin. | 462 | * Find the IRQ entry number of a certain pin. |
@@ -453,10 +466,10 @@ static int find_irq_entry(int apic, int pin, int type) | |||
453 | int i; | 466 | int i; |
454 | 467 | ||
455 | for (i = 0; i < mp_irq_entries; i++) | 468 | for (i = 0; i < mp_irq_entries; i++) |
456 | if (mp_irqs[i].mpc_irqtype == type && | 469 | if (mp_irqs[i].mp_irqtype == type && |
457 | (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid || | 470 | (mp_irqs[i].mp_dstapic == mp_ioapics[apic].mp_apicid || |
458 | mp_irqs[i].mpc_dstapic == MP_APIC_ALL) && | 471 | mp_irqs[i].mp_dstapic == MP_APIC_ALL) && |
459 | mp_irqs[i].mpc_dstirq == pin) | 472 | mp_irqs[i].mp_dstirq == pin) |
460 | return i; | 473 | return i; |
461 | 474 | ||
462 | return -1; | 475 | return -1; |
@@ -470,13 +483,13 @@ static int __init find_isa_irq_pin(int irq, int type) | |||
470 | int i; | 483 | int i; |
471 | 484 | ||
472 | for (i = 0; i < mp_irq_entries; i++) { | 485 | for (i = 0; i < mp_irq_entries; i++) { |
473 | int lbus = mp_irqs[i].mpc_srcbus; | 486 | int lbus = mp_irqs[i].mp_srcbus; |
474 | 487 | ||
475 | if (test_bit(lbus, mp_bus_not_pci) && | 488 | if (test_bit(lbus, mp_bus_not_pci) && |
476 | (mp_irqs[i].mpc_irqtype == type) && | 489 | (mp_irqs[i].mp_irqtype == type) && |
477 | (mp_irqs[i].mpc_srcbusirq == irq)) | 490 | (mp_irqs[i].mp_srcbusirq == irq)) |
478 | 491 | ||
479 | return mp_irqs[i].mpc_dstirq; | 492 | return mp_irqs[i].mp_dstirq; |
480 | } | 493 | } |
481 | return -1; | 494 | return -1; |
482 | } | 495 | } |
@@ -486,17 +499,17 @@ static int __init find_isa_irq_apic(int irq, int type) | |||
486 | int i; | 499 | int i; |
487 | 500 | ||
488 | for (i = 0; i < mp_irq_entries; i++) { | 501 | for (i = 0; i < mp_irq_entries; i++) { |
489 | int lbus = mp_irqs[i].mpc_srcbus; | 502 | int lbus = mp_irqs[i].mp_srcbus; |
490 | 503 | ||
491 | if (test_bit(lbus, mp_bus_not_pci) && | 504 | if (test_bit(lbus, mp_bus_not_pci) && |
492 | (mp_irqs[i].mpc_irqtype == type) && | 505 | (mp_irqs[i].mp_irqtype == type) && |
493 | (mp_irqs[i].mpc_srcbusirq == irq)) | 506 | (mp_irqs[i].mp_srcbusirq == irq)) |
494 | break; | 507 | break; |
495 | } | 508 | } |
496 | if (i < mp_irq_entries) { | 509 | if (i < mp_irq_entries) { |
497 | int apic; | 510 | int apic; |
498 | for(apic = 0; apic < nr_ioapics; apic++) { | 511 | for(apic = 0; apic < nr_ioapics; apic++) { |
499 | if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic) | 512 | if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic) |
500 | return apic; | 513 | return apic; |
501 | } | 514 | } |
502 | } | 515 | } |
@@ -516,28 +529,28 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) | |||
516 | 529 | ||
517 | apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", | 530 | apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", |
518 | bus, slot, pin); | 531 | bus, slot, pin); |
519 | if (mp_bus_id_to_pci_bus[bus] == -1) { | 532 | if (test_bit(bus, mp_bus_not_pci)) { |
520 | apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus); | 533 | apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus); |
521 | return -1; | 534 | return -1; |
522 | } | 535 | } |
523 | for (i = 0; i < mp_irq_entries; i++) { | 536 | for (i = 0; i < mp_irq_entries; i++) { |
524 | int lbus = mp_irqs[i].mpc_srcbus; | 537 | int lbus = mp_irqs[i].mp_srcbus; |
525 | 538 | ||
526 | for (apic = 0; apic < nr_ioapics; apic++) | 539 | for (apic = 0; apic < nr_ioapics; apic++) |
527 | if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic || | 540 | if (mp_ioapics[apic].mp_apicid == mp_irqs[i].mp_dstapic || |
528 | mp_irqs[i].mpc_dstapic == MP_APIC_ALL) | 541 | mp_irqs[i].mp_dstapic == MP_APIC_ALL) |
529 | break; | 542 | break; |
530 | 543 | ||
531 | if (!test_bit(lbus, mp_bus_not_pci) && | 544 | if (!test_bit(lbus, mp_bus_not_pci) && |
532 | !mp_irqs[i].mpc_irqtype && | 545 | !mp_irqs[i].mp_irqtype && |
533 | (bus == lbus) && | 546 | (bus == lbus) && |
534 | (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) { | 547 | (slot == ((mp_irqs[i].mp_srcbusirq >> 2) & 0x1f))) { |
535 | int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq); | 548 | int irq = pin_2_irq(i,apic,mp_irqs[i].mp_dstirq); |
536 | 549 | ||
537 | if (!(apic || IO_APIC_IRQ(irq))) | 550 | if (!(apic || IO_APIC_IRQ(irq))) |
538 | continue; | 551 | continue; |
539 | 552 | ||
540 | if (pin == (mp_irqs[i].mpc_srcbusirq & 3)) | 553 | if (pin == (mp_irqs[i].mp_srcbusirq & 3)) |
541 | return irq; | 554 | return irq; |
542 | /* | 555 | /* |
543 | * Use the first all-but-pin matching entry as a | 556 | * Use the first all-but-pin matching entry as a |
@@ -565,13 +578,13 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) | |||
565 | 578 | ||
566 | static int MPBIOS_polarity(int idx) | 579 | static int MPBIOS_polarity(int idx) |
567 | { | 580 | { |
568 | int bus = mp_irqs[idx].mpc_srcbus; | 581 | int bus = mp_irqs[idx].mp_srcbus; |
569 | int polarity; | 582 | int polarity; |
570 | 583 | ||
571 | /* | 584 | /* |
572 | * Determine IRQ line polarity (high active or low active): | 585 | * Determine IRQ line polarity (high active or low active): |
573 | */ | 586 | */ |
574 | switch (mp_irqs[idx].mpc_irqflag & 3) | 587 | switch (mp_irqs[idx].mp_irqflag & 3) |
575 | { | 588 | { |
576 | case 0: /* conforms, ie. bus-type dependent polarity */ | 589 | case 0: /* conforms, ie. bus-type dependent polarity */ |
577 | if (test_bit(bus, mp_bus_not_pci)) | 590 | if (test_bit(bus, mp_bus_not_pci)) |
@@ -607,13 +620,13 @@ static int MPBIOS_polarity(int idx) | |||
607 | 620 | ||
608 | static int MPBIOS_trigger(int idx) | 621 | static int MPBIOS_trigger(int idx) |
609 | { | 622 | { |
610 | int bus = mp_irqs[idx].mpc_srcbus; | 623 | int bus = mp_irqs[idx].mp_srcbus; |
611 | int trigger; | 624 | int trigger; |
612 | 625 | ||
613 | /* | 626 | /* |
614 | * Determine IRQ trigger mode (edge or level sensitive): | 627 | * Determine IRQ trigger mode (edge or level sensitive): |
615 | */ | 628 | */ |
616 | switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) | 629 | switch ((mp_irqs[idx].mp_irqflag>>2) & 3) |
617 | { | 630 | { |
618 | case 0: /* conforms, ie. bus-type dependent */ | 631 | case 0: /* conforms, ie. bus-type dependent */ |
619 | if (test_bit(bus, mp_bus_not_pci)) | 632 | if (test_bit(bus, mp_bus_not_pci)) |
@@ -660,16 +673,16 @@ static inline int irq_trigger(int idx) | |||
660 | static int pin_2_irq(int idx, int apic, int pin) | 673 | static int pin_2_irq(int idx, int apic, int pin) |
661 | { | 674 | { |
662 | int irq, i; | 675 | int irq, i; |
663 | int bus = mp_irqs[idx].mpc_srcbus; | 676 | int bus = mp_irqs[idx].mp_srcbus; |
664 | 677 | ||
665 | /* | 678 | /* |
666 | * Debugging check, we are in big trouble if this message pops up! | 679 | * Debugging check, we are in big trouble if this message pops up! |
667 | */ | 680 | */ |
668 | if (mp_irqs[idx].mpc_dstirq != pin) | 681 | if (mp_irqs[idx].mp_dstirq != pin) |
669 | printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); | 682 | printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); |
670 | 683 | ||
671 | if (test_bit(bus, mp_bus_not_pci)) { | 684 | if (test_bit(bus, mp_bus_not_pci)) { |
672 | irq = mp_irqs[idx].mpc_srcbusirq; | 685 | irq = mp_irqs[idx].mp_srcbusirq; |
673 | } else { | 686 | } else { |
674 | /* | 687 | /* |
675 | * PCI IRQs are mapped in order | 688 | * PCI IRQs are mapped in order |
@@ -730,7 +743,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask) | |||
730 | offset = current_offset; | 743 | offset = current_offset; |
731 | next: | 744 | next: |
732 | vector += 8; | 745 | vector += 8; |
733 | if (vector >= FIRST_SYSTEM_VECTOR) { | 746 | if (vector >= first_system_vector) { |
734 | /* If we run out of vectors on large boxen, must share them. */ | 747 | /* If we run out of vectors on large boxen, must share them. */ |
735 | offset = (offset + 1) % 8; | 748 | offset = (offset + 1) % 8; |
736 | vector = FIRST_DEVICE_VECTOR + offset; | 749 | vector = FIRST_DEVICE_VECTOR + offset; |
@@ -788,7 +801,7 @@ static void __clear_irq_vector(int irq) | |||
788 | cpus_clear(cfg->domain); | 801 | cpus_clear(cfg->domain); |
789 | } | 802 | } |
790 | 803 | ||
791 | void __setup_vector_irq(int cpu) | 804 | static void __setup_vector_irq(int cpu) |
792 | { | 805 | { |
793 | /* Initialize vector_irq on a new cpu */ | 806 | /* Initialize vector_irq on a new cpu */ |
794 | /* This function must be called with vector_lock held */ | 807 | /* This function must be called with vector_lock held */ |
@@ -811,6 +824,13 @@ void __setup_vector_irq(int cpu) | |||
811 | } | 824 | } |
812 | } | 825 | } |
813 | 826 | ||
827 | void setup_vector_irq(int cpu) | ||
828 | { | ||
829 | spin_lock(&vector_lock); | ||
830 | __setup_vector_irq(smp_processor_id()); | ||
831 | spin_unlock(&vector_lock); | ||
832 | } | ||
833 | |||
814 | 834 | ||
815 | static struct irq_chip ioapic_chip; | 835 | static struct irq_chip ioapic_chip; |
816 | 836 | ||
@@ -846,7 +866,7 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, | |||
846 | apic_printk(APIC_VERBOSE,KERN_DEBUG | 866 | apic_printk(APIC_VERBOSE,KERN_DEBUG |
847 | "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " | 867 | "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> " |
848 | "IRQ %d Mode:%i Active:%i)\n", | 868 | "IRQ %d Mode:%i Active:%i)\n", |
849 | apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector, | 869 | apic, mp_ioapics[apic].mp_apicid, pin, cfg->vector, |
850 | irq, trigger, polarity); | 870 | irq, trigger, polarity); |
851 | 871 | ||
852 | /* | 872 | /* |
@@ -887,10 +907,10 @@ static void __init setup_IO_APIC_irqs(void) | |||
887 | idx = find_irq_entry(apic,pin,mp_INT); | 907 | idx = find_irq_entry(apic,pin,mp_INT); |
888 | if (idx == -1) { | 908 | if (idx == -1) { |
889 | if (first_notcon) { | 909 | if (first_notcon) { |
890 | apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin); | 910 | apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin); |
891 | first_notcon = 0; | 911 | first_notcon = 0; |
892 | } else | 912 | } else |
893 | apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin); | 913 | apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin); |
894 | continue; | 914 | continue; |
895 | } | 915 | } |
896 | if (!first_notcon) { | 916 | if (!first_notcon) { |
@@ -911,26 +931,21 @@ static void __init setup_IO_APIC_irqs(void) | |||
911 | } | 931 | } |
912 | 932 | ||
913 | /* | 933 | /* |
914 | * Set up the 8259A-master output pin as broadcast to all | 934 | * Set up the timer pin, possibly with the 8259A-master behind. |
915 | * CPUs. | ||
916 | */ | 935 | */ |
917 | static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) | 936 | static void __init setup_timer_IRQ0_pin(unsigned int apic, unsigned int pin, |
937 | int vector) | ||
918 | { | 938 | { |
919 | struct IO_APIC_route_entry entry; | 939 | struct IO_APIC_route_entry entry; |
920 | 940 | ||
921 | memset(&entry, 0, sizeof(entry)); | 941 | memset(&entry, 0, sizeof(entry)); |
922 | 942 | ||
923 | disable_8259A_irq(0); | ||
924 | |||
925 | /* mask LVT0 */ | ||
926 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); | ||
927 | |||
928 | /* | 943 | /* |
929 | * We use logical delivery to get the timer IRQ | 944 | * We use logical delivery to get the timer IRQ |
930 | * to the first CPU. | 945 | * to the first CPU. |
931 | */ | 946 | */ |
932 | entry.dest_mode = INT_DEST_MODE; | 947 | entry.dest_mode = INT_DEST_MODE; |
933 | entry.mask = 0; /* unmask IRQ now */ | 948 | entry.mask = 1; /* mask IRQ now */ |
934 | entry.dest = cpu_mask_to_apicid(TARGET_CPUS); | 949 | entry.dest = cpu_mask_to_apicid(TARGET_CPUS); |
935 | entry.delivery_mode = INT_DELIVERY_MODE; | 950 | entry.delivery_mode = INT_DELIVERY_MODE; |
936 | entry.polarity = 0; | 951 | entry.polarity = 0; |
@@ -939,7 +954,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in | |||
939 | 954 | ||
940 | /* | 955 | /* |
941 | * The timer IRQ doesn't have to know that behind the | 956 | * The timer IRQ doesn't have to know that behind the |
942 | * scene we have a 8259A-master in AEOI mode ... | 957 | * scene we may have a 8259A-master in AEOI mode ... |
943 | */ | 958 | */ |
944 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); | 959 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); |
945 | 960 | ||
@@ -947,8 +962,6 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in | |||
947 | * Add it to the IO-APIC irq-routing table: | 962 | * Add it to the IO-APIC irq-routing table: |
948 | */ | 963 | */ |
949 | ioapic_write_entry(apic, pin, entry); | 964 | ioapic_write_entry(apic, pin, entry); |
950 | |||
951 | enable_8259A_irq(0); | ||
952 | } | 965 | } |
953 | 966 | ||
954 | void __apicdebuginit print_IO_APIC(void) | 967 | void __apicdebuginit print_IO_APIC(void) |
@@ -965,7 +978,7 @@ void __apicdebuginit print_IO_APIC(void) | |||
965 | printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); | 978 | printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); |
966 | for (i = 0; i < nr_ioapics; i++) | 979 | for (i = 0; i < nr_ioapics; i++) |
967 | printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", | 980 | printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", |
968 | mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]); | 981 | mp_ioapics[i].mp_apicid, nr_ioapic_registers[i]); |
969 | 982 | ||
970 | /* | 983 | /* |
971 | * We are a bit conservative about what we expect. We have to | 984 | * We are a bit conservative about what we expect. We have to |
@@ -983,7 +996,7 @@ void __apicdebuginit print_IO_APIC(void) | |||
983 | spin_unlock_irqrestore(&ioapic_lock, flags); | 996 | spin_unlock_irqrestore(&ioapic_lock, flags); |
984 | 997 | ||
985 | printk("\n"); | 998 | printk("\n"); |
986 | printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); | 999 | printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mp_apicid); |
987 | printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); | 1000 | printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); |
988 | printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); | 1001 | printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); |
989 | 1002 | ||
@@ -1077,6 +1090,7 @@ void __apicdebuginit print_local_APIC(void * dummy) | |||
1077 | 1090 | ||
1078 | printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", | 1091 | printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n", |
1079 | smp_processor_id(), hard_smp_processor_id()); | 1092 | smp_processor_id(), hard_smp_processor_id()); |
1093 | v = apic_read(APIC_ID); | ||
1080 | printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id())); | 1094 | printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(read_apic_id())); |
1081 | v = apic_read(APIC_LVR); | 1095 | v = apic_read(APIC_LVR); |
1082 | printk(KERN_INFO "... APIC VERSION: %08x\n", v); | 1096 | printk(KERN_INFO "... APIC VERSION: %08x\n", v); |
@@ -1146,7 +1160,7 @@ void __apicdebuginit print_local_APIC(void * dummy) | |||
1146 | 1160 | ||
1147 | void print_all_local_APICs (void) | 1161 | void print_all_local_APICs (void) |
1148 | { | 1162 | { |
1149 | on_each_cpu(print_local_APIC, NULL, 1, 1); | 1163 | on_each_cpu(print_local_APIC, NULL, 1); |
1150 | } | 1164 | } |
1151 | 1165 | ||
1152 | void __apicdebuginit print_PIC(void) | 1166 | void __apicdebuginit print_PIC(void) |
@@ -1540,7 +1554,7 @@ static inline void init_IO_APIC_traps(void) | |||
1540 | } | 1554 | } |
1541 | } | 1555 | } |
1542 | 1556 | ||
1543 | static void enable_lapic_irq (unsigned int irq) | 1557 | static void unmask_lapic_irq(unsigned int irq) |
1544 | { | 1558 | { |
1545 | unsigned long v; | 1559 | unsigned long v; |
1546 | 1560 | ||
@@ -1548,7 +1562,7 @@ static void enable_lapic_irq (unsigned int irq) | |||
1548 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); | 1562 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); |
1549 | } | 1563 | } |
1550 | 1564 | ||
1551 | static void disable_lapic_irq (unsigned int irq) | 1565 | static void mask_lapic_irq(unsigned int irq) |
1552 | { | 1566 | { |
1553 | unsigned long v; | 1567 | unsigned long v; |
1554 | 1568 | ||
@@ -1561,19 +1575,20 @@ static void ack_lapic_irq (unsigned int irq) | |||
1561 | ack_APIC_irq(); | 1575 | ack_APIC_irq(); |
1562 | } | 1576 | } |
1563 | 1577 | ||
1564 | static void end_lapic_irq (unsigned int i) { /* nothing */ } | 1578 | static struct irq_chip lapic_chip __read_mostly = { |
1565 | 1579 | .name = "local-APIC", | |
1566 | static struct hw_interrupt_type lapic_irq_type __read_mostly = { | 1580 | .mask = mask_lapic_irq, |
1567 | .name = "local-APIC", | 1581 | .unmask = unmask_lapic_irq, |
1568 | .typename = "local-APIC-edge", | 1582 | .ack = ack_lapic_irq, |
1569 | .startup = NULL, /* startup_irq() not used for IRQ0 */ | ||
1570 | .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ | ||
1571 | .enable = enable_lapic_irq, | ||
1572 | .disable = disable_lapic_irq, | ||
1573 | .ack = ack_lapic_irq, | ||
1574 | .end = end_lapic_irq, | ||
1575 | }; | 1583 | }; |
1576 | 1584 | ||
1585 | static void lapic_register_intr(int irq) | ||
1586 | { | ||
1587 | irq_desc[irq].status &= ~IRQ_LEVEL; | ||
1588 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, | ||
1589 | "edge"); | ||
1590 | } | ||
1591 | |||
1577 | static void __init setup_nmi(void) | 1592 | static void __init setup_nmi(void) |
1578 | { | 1593 | { |
1579 | /* | 1594 | /* |
@@ -1659,6 +1674,7 @@ static inline void __init check_timer(void) | |||
1659 | struct irq_cfg *cfg = irq_cfg + 0; | 1674 | struct irq_cfg *cfg = irq_cfg + 0; |
1660 | int apic1, pin1, apic2, pin2; | 1675 | int apic1, pin1, apic2, pin2; |
1661 | unsigned long flags; | 1676 | unsigned long flags; |
1677 | int no_pin1 = 0; | ||
1662 | 1678 | ||
1663 | local_irq_save(flags); | 1679 | local_irq_save(flags); |
1664 | 1680 | ||
@@ -1669,16 +1685,11 @@ static inline void __init check_timer(void) | |||
1669 | assign_irq_vector(0, TARGET_CPUS); | 1685 | assign_irq_vector(0, TARGET_CPUS); |
1670 | 1686 | ||
1671 | /* | 1687 | /* |
1672 | * Subtle, code in do_timer_interrupt() expects an AEOI | 1688 | * As IRQ0 is to be enabled in the 8259A, the virtual |
1673 | * mode for the 8259A whenever interrupts are routed | 1689 | * wire has to be disabled in the local APIC. |
1674 | * through I/O APICs. Also IRQ0 has to be enabled in | ||
1675 | * the 8259A which implies the virtual wire has to be | ||
1676 | * disabled in the local APIC. | ||
1677 | */ | 1690 | */ |
1678 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); | 1691 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); |
1679 | init_8259A(1); | 1692 | init_8259A(1); |
1680 | if (timer_over_8254 > 0) | ||
1681 | enable_8259A_irq(0); | ||
1682 | 1693 | ||
1683 | pin1 = find_isa_irq_pin(0, mp_INT); | 1694 | pin1 = find_isa_irq_pin(0, mp_INT); |
1684 | apic1 = find_isa_irq_apic(0, mp_INT); | 1695 | apic1 = find_isa_irq_apic(0, mp_INT); |
@@ -1688,15 +1699,33 @@ static inline void __init check_timer(void) | |||
1688 | apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", | 1699 | apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", |
1689 | cfg->vector, apic1, pin1, apic2, pin2); | 1700 | cfg->vector, apic1, pin1, apic2, pin2); |
1690 | 1701 | ||
1702 | /* | ||
1703 | * Some BIOS writers are clueless and report the ExtINTA | ||
1704 | * I/O APIC input from the cascaded 8259A as the timer | ||
1705 | * interrupt input. So just in case, if only one pin | ||
1706 | * was found above, try it both directly and through the | ||
1707 | * 8259A. | ||
1708 | */ | ||
1709 | if (pin1 == -1) { | ||
1710 | pin1 = pin2; | ||
1711 | apic1 = apic2; | ||
1712 | no_pin1 = 1; | ||
1713 | } else if (pin2 == -1) { | ||
1714 | pin2 = pin1; | ||
1715 | apic2 = apic1; | ||
1716 | } | ||
1717 | |||
1691 | if (pin1 != -1) { | 1718 | if (pin1 != -1) { |
1692 | /* | 1719 | /* |
1693 | * Ok, does IRQ0 through the IOAPIC work? | 1720 | * Ok, does IRQ0 through the IOAPIC work? |
1694 | */ | 1721 | */ |
1722 | if (no_pin1) { | ||
1723 | add_pin_to_irq(0, apic1, pin1); | ||
1724 | setup_timer_IRQ0_pin(apic1, pin1, cfg->vector); | ||
1725 | } | ||
1695 | unmask_IO_APIC_irq(0); | 1726 | unmask_IO_APIC_irq(0); |
1696 | if (!no_timer_check && timer_irq_works()) { | 1727 | if (!no_timer_check && timer_irq_works()) { |
1697 | nmi_watchdog_default(); | ||
1698 | if (nmi_watchdog == NMI_IO_APIC) { | 1728 | if (nmi_watchdog == NMI_IO_APIC) { |
1699 | disable_8259A_irq(0); | ||
1700 | setup_nmi(); | 1729 | setup_nmi(); |
1701 | enable_8259A_irq(0); | 1730 | enable_8259A_irq(0); |
1702 | } | 1731 | } |
@@ -1705,43 +1734,48 @@ static inline void __init check_timer(void) | |||
1705 | goto out; | 1734 | goto out; |
1706 | } | 1735 | } |
1707 | clear_IO_APIC_pin(apic1, pin1); | 1736 | clear_IO_APIC_pin(apic1, pin1); |
1708 | apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not " | 1737 | if (!no_pin1) |
1709 | "connected to IO-APIC\n"); | 1738 | apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: " |
1710 | } | 1739 | "8254 timer not connected to IO-APIC\n"); |
1711 | 1740 | ||
1712 | apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) " | 1741 | apic_printk(APIC_VERBOSE,KERN_INFO |
1713 | "through the 8259A ... "); | 1742 | "...trying to set up timer (IRQ0) " |
1714 | if (pin2 != -1) { | 1743 | "through the 8259A ... "); |
1715 | apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", | 1744 | apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", |
1716 | apic2, pin2); | 1745 | apic2, pin2); |
1717 | /* | 1746 | /* |
1718 | * legacy devices should be connected to IO APIC #0 | 1747 | * legacy devices should be connected to IO APIC #0 |
1719 | */ | 1748 | */ |
1720 | setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector); | 1749 | replace_pin_at_irq(0, apic1, pin1, apic2, pin2); |
1750 | setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); | ||
1751 | unmask_IO_APIC_irq(0); | ||
1752 | enable_8259A_irq(0); | ||
1721 | if (timer_irq_works()) { | 1753 | if (timer_irq_works()) { |
1722 | apic_printk(APIC_VERBOSE," works.\n"); | 1754 | apic_printk(APIC_VERBOSE," works.\n"); |
1723 | nmi_watchdog_default(); | 1755 | timer_through_8259 = 1; |
1724 | if (nmi_watchdog == NMI_IO_APIC) { | 1756 | if (nmi_watchdog == NMI_IO_APIC) { |
1757 | disable_8259A_irq(0); | ||
1725 | setup_nmi(); | 1758 | setup_nmi(); |
1759 | enable_8259A_irq(0); | ||
1726 | } | 1760 | } |
1727 | goto out; | 1761 | goto out; |
1728 | } | 1762 | } |
1729 | /* | 1763 | /* |
1730 | * Cleanup, just in case ... | 1764 | * Cleanup, just in case ... |
1731 | */ | 1765 | */ |
1766 | disable_8259A_irq(0); | ||
1732 | clear_IO_APIC_pin(apic2, pin2); | 1767 | clear_IO_APIC_pin(apic2, pin2); |
1768 | apic_printk(APIC_VERBOSE," failed.\n"); | ||
1733 | } | 1769 | } |
1734 | apic_printk(APIC_VERBOSE," failed.\n"); | ||
1735 | 1770 | ||
1736 | if (nmi_watchdog == NMI_IO_APIC) { | 1771 | if (nmi_watchdog == NMI_IO_APIC) { |
1737 | printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); | 1772 | printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); |
1738 | nmi_watchdog = 0; | 1773 | nmi_watchdog = NMI_NONE; |
1739 | } | 1774 | } |
1740 | 1775 | ||
1741 | apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); | 1776 | apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); |
1742 | 1777 | ||
1743 | disable_8259A_irq(0); | 1778 | lapic_register_intr(0); |
1744 | irq_desc[0].chip = &lapic_irq_type; | ||
1745 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ | 1779 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ |
1746 | enable_8259A_irq(0); | 1780 | enable_8259A_irq(0); |
1747 | 1781 | ||
@@ -1749,6 +1783,7 @@ static inline void __init check_timer(void) | |||
1749 | apic_printk(APIC_VERBOSE," works.\n"); | 1783 | apic_printk(APIC_VERBOSE," works.\n"); |
1750 | goto out; | 1784 | goto out; |
1751 | } | 1785 | } |
1786 | disable_8259A_irq(0); | ||
1752 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); | 1787 | apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); |
1753 | apic_printk(APIC_VERBOSE," failed.\n"); | 1788 | apic_printk(APIC_VERBOSE," failed.\n"); |
1754 | 1789 | ||
@@ -1778,11 +1813,21 @@ static int __init notimercheck(char *s) | |||
1778 | __setup("no_timer_check", notimercheck); | 1813 | __setup("no_timer_check", notimercheck); |
1779 | 1814 | ||
1780 | /* | 1815 | /* |
1781 | * | 1816 | * Traditionally ISA IRQ2 is the cascade IRQ, and is not available |
1782 | * IRQs that are handled by the PIC in the MPS IOAPIC case. | 1817 | * to devices. However there may be an I/O APIC pin available for |
1783 | * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ. | 1818 | * this interrupt regardless. The pin may be left unconnected, but |
1784 | * Linux doesn't really care, as it's not actually used | 1819 | * typically it will be reused as an ExtINT cascade interrupt for |
1785 | * for any interrupt handling anyway. | 1820 | * the master 8259A. In the MPS case such a pin will normally be |
1821 | * reported as an ExtINT interrupt in the MP table. With ACPI | ||
1822 | * there is no provision for ExtINT interrupts, and in the absence | ||
1823 | * of an override it would be treated as an ordinary ISA I/O APIC | ||
1824 | * interrupt, that is edge-triggered and unmasked by default. We | ||
1825 | * used to do this, but it caused problems on some systems because | ||
1826 | * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using | ||
1827 | * the same ExtINT cascade interrupt to drive the local APIC of the | ||
1828 | * bootstrap processor. Therefore we refrain from routing IRQ2 to | ||
1829 | * the I/O APIC in all cases now. No actual device should request | ||
1830 | * it anyway. --macro | ||
1786 | */ | 1831 | */ |
1787 | #define PIC_IRQS (1<<2) | 1832 | #define PIC_IRQS (1<<2) |
1788 | 1833 | ||
@@ -1793,10 +1838,7 @@ void __init setup_IO_APIC(void) | |||
1793 | * calling enable_IO_APIC() is moved to setup_local_APIC for BP | 1838 | * calling enable_IO_APIC() is moved to setup_local_APIC for BP |
1794 | */ | 1839 | */ |
1795 | 1840 | ||
1796 | if (acpi_ioapic) | 1841 | io_apic_irqs = ~PIC_IRQS; |
1797 | io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ | ||
1798 | else | ||
1799 | io_apic_irqs = ~PIC_IRQS; | ||
1800 | 1842 | ||
1801 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); | 1843 | apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n"); |
1802 | 1844 | ||
@@ -1841,8 +1883,8 @@ static int ioapic_resume(struct sys_device *dev) | |||
1841 | 1883 | ||
1842 | spin_lock_irqsave(&ioapic_lock, flags); | 1884 | spin_lock_irqsave(&ioapic_lock, flags); |
1843 | reg_00.raw = io_apic_read(dev->id, 0); | 1885 | reg_00.raw = io_apic_read(dev->id, 0); |
1844 | if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) { | 1886 | if (reg_00.bits.ID != mp_ioapics[dev->id].mp_apicid) { |
1845 | reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; | 1887 | reg_00.bits.ID = mp_ioapics[dev->id].mp_apicid; |
1846 | io_apic_write(dev->id, 0, reg_00.raw); | 1888 | io_apic_write(dev->id, 0, reg_00.raw); |
1847 | } | 1889 | } |
1848 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1890 | spin_unlock_irqrestore(&ioapic_lock, flags); |
@@ -2242,8 +2284,8 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) | |||
2242 | return -1; | 2284 | return -1; |
2243 | 2285 | ||
2244 | for (i = 0; i < mp_irq_entries; i++) | 2286 | for (i = 0; i < mp_irq_entries; i++) |
2245 | if (mp_irqs[i].mpc_irqtype == mp_INT && | 2287 | if (mp_irqs[i].mp_irqtype == mp_INT && |
2246 | mp_irqs[i].mpc_srcbusirq == bus_irq) | 2288 | mp_irqs[i].mp_srcbusirq == bus_irq) |
2247 | break; | 2289 | break; |
2248 | if (i >= mp_irq_entries) | 2290 | if (i >= mp_irq_entries) |
2249 | return -1; | 2291 | return -1; |
@@ -2336,7 +2378,7 @@ void __init ioapic_init_mappings(void) | |||
2336 | ioapic_res = ioapic_setup_resources(); | 2378 | ioapic_res = ioapic_setup_resources(); |
2337 | for (i = 0; i < nr_ioapics; i++) { | 2379 | for (i = 0; i < nr_ioapics; i++) { |
2338 | if (smp_found_config) { | 2380 | if (smp_found_config) { |
2339 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; | 2381 | ioapic_phys = mp_ioapics[i].mp_apicaddr; |
2340 | } else { | 2382 | } else { |
2341 | ioapic_phys = (unsigned long) | 2383 | ioapic_phys = (unsigned long) |
2342 | alloc_bootmem_pages(PAGE_SIZE); | 2384 | alloc_bootmem_pages(PAGE_SIZE); |