aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c58
1 files changed, 46 insertions, 12 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7a324e8b86f9..6578f40bd501 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -31,12 +31,13 @@
31#include <linux/mc146818rtc.h> 31#include <linux/mc146818rtc.h>
32#include <linux/compiler.h> 32#include <linux/compiler.h>
33#include <linux/acpi.h> 33#include <linux/acpi.h>
34 34#include <linux/module.h>
35#include <linux/sysdev.h> 35#include <linux/sysdev.h>
36#include <asm/io.h> 36#include <asm/io.h>
37#include <asm/smp.h> 37#include <asm/smp.h>
38#include <asm/desc.h> 38#include <asm/desc.h>
39#include <asm/timer.h> 39#include <asm/timer.h>
40#include <asm/i8259.h>
40 41
41#include <mach_apic.h> 42#include <mach_apic.h>
42 43
@@ -573,12 +574,14 @@ static int balanced_irq(void *unused)
573 for ( ; ; ) { 574 for ( ; ; ) {
574 set_current_state(TASK_INTERRUPTIBLE); 575 set_current_state(TASK_INTERRUPTIBLE);
575 time_remaining = schedule_timeout(time_remaining); 576 time_remaining = schedule_timeout(time_remaining);
576 try_to_freeze(PF_FREEZE); 577 try_to_freeze();
577 if (time_after(jiffies, 578 if (time_after(jiffies,
578 prev_balance_time+balanced_irq_interval)) { 579 prev_balance_time+balanced_irq_interval)) {
580 preempt_disable();
579 do_irq_balance(); 581 do_irq_balance();
580 prev_balance_time = jiffies; 582 prev_balance_time = jiffies;
581 time_remaining = balanced_irq_interval; 583 time_remaining = balanced_irq_interval;
584 preempt_enable();
582 } 585 }
583 } 586 }
584 return 0; 587 return 0;
@@ -630,10 +633,8 @@ static int __init balanced_irq_init(void)
630 printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); 633 printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
631failed: 634failed:
632 for (i = 0; i < NR_CPUS; i++) { 635 for (i = 0; i < NR_CPUS; i++) {
633 if(irq_cpu_data[i].irq_delta) 636 kfree(irq_cpu_data[i].irq_delta);
634 kfree(irq_cpu_data[i].irq_delta); 637 kfree(irq_cpu_data[i].last_irq);
635 if(irq_cpu_data[i].last_irq)
636 kfree(irq_cpu_data[i].last_irq);
637 } 638 }
638 return 0; 639 return 0;
639} 640}
@@ -812,6 +813,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
812 } 813 }
813 return best_guess; 814 return best_guess;
814} 815}
816EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
815 817
816/* 818/*
817 * This function currently is only a helper for the i386 smp boot process where 819 * This function currently is only a helper for the i386 smp boot process where
@@ -1565,7 +1567,6 @@ void print_all_local_APICs (void)
1565 1567
1566void /*__init*/ print_PIC(void) 1568void /*__init*/ print_PIC(void)
1567{ 1569{
1568 extern spinlock_t i8259A_lock;
1569 unsigned int v; 1570 unsigned int v;
1570 unsigned long flags; 1571 unsigned long flags;
1571 1572
@@ -1633,12 +1634,43 @@ static void __init enable_IO_APIC(void)
1633 */ 1634 */
1634void disable_IO_APIC(void) 1635void disable_IO_APIC(void)
1635{ 1636{
1637 int pin;
1636 /* 1638 /*
1637 * Clear the IO-APIC before rebooting: 1639 * Clear the IO-APIC before rebooting:
1638 */ 1640 */
1639 clear_IO_APIC(); 1641 clear_IO_APIC();
1640 1642
1641 disconnect_bsp_APIC(); 1643 /*
1644 * If the i82559 is routed through an IOAPIC
1645 * Put that IOAPIC in virtual wire mode
1646 * so legacy interrups can be delivered.
1647 */
1648 pin = find_isa_irq_pin(0, mp_ExtINT);
1649 if (pin != -1) {
1650 struct IO_APIC_route_entry entry;
1651 unsigned long flags;
1652
1653 memset(&entry, 0, sizeof(entry));
1654 entry.mask = 0; /* Enabled */
1655 entry.trigger = 0; /* Edge */
1656 entry.irr = 0;
1657 entry.polarity = 0; /* High */
1658 entry.delivery_status = 0;
1659 entry.dest_mode = 0; /* Physical */
1660 entry.delivery_mode = 7; /* ExtInt */
1661 entry.vector = 0;
1662 entry.dest.physical.physical_dest = 0;
1663
1664
1665 /*
1666 * Add it to the IO-APIC irq-routing table:
1667 */
1668 spin_lock_irqsave(&ioapic_lock, flags);
1669 io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
1670 io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
1671 spin_unlock_irqrestore(&ioapic_lock, flags);
1672 }
1673 disconnect_bsp_APIC(pin != -1);
1642} 1674}
1643 1675
1644/* 1676/*
@@ -1659,6 +1691,12 @@ static void __init setup_ioapic_ids_from_mpc(void)
1659 unsigned long flags; 1691 unsigned long flags;
1660 1692
1661 /* 1693 /*
1694 * Don't check I/O APIC IDs for xAPIC systems. They have
1695 * no meaning without the serial APIC bus.
1696 */
1697 if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 < 15))
1698 return;
1699 /*
1662 * This is broken; anything with a real cpu count has to 1700 * This is broken; anything with a real cpu count has to
1663 * circumvent this idiocy regardless. 1701 * circumvent this idiocy regardless.
1664 */ 1702 */
@@ -1684,10 +1722,6 @@ static void __init setup_ioapic_ids_from_mpc(void)
1684 mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; 1722 mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
1685 } 1723 }
1686 1724
1687 /* Don't check I/O APIC IDs for some xAPIC systems. They have
1688 * no meaning without the serial APIC bus. */
1689 if (NO_IOAPIC_CHECK)
1690 continue;
1691 /* 1725 /*
1692 * Sanity check, is the ID really free? Every APIC in a 1726 * Sanity check, is the ID really free? Every APIC in a
1693 * system must have a unique ID or we get lots of nice 1727 * system must have a unique ID or we get lots of nice