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.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 08540bc4ba3e..35eb8e29c485 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -573,12 +573,14 @@ static int balanced_irq(void *unused)
573 for ( ; ; ) { 573 for ( ; ; ) {
574 set_current_state(TASK_INTERRUPTIBLE); 574 set_current_state(TASK_INTERRUPTIBLE);
575 time_remaining = schedule_timeout(time_remaining); 575 time_remaining = schedule_timeout(time_remaining);
576 try_to_freeze(PF_FREEZE); 576 try_to_freeze();
577 if (time_after(jiffies, 577 if (time_after(jiffies,
578 prev_balance_time+balanced_irq_interval)) { 578 prev_balance_time+balanced_irq_interval)) {
579 preempt_disable();
579 do_irq_balance(); 580 do_irq_balance();
580 prev_balance_time = jiffies; 581 prev_balance_time = jiffies;
581 time_remaining = balanced_irq_interval; 582 time_remaining = balanced_irq_interval;
583 preempt_enable();
582 } 584 }
583 } 585 }
584 return 0; 586 return 0;
@@ -630,10 +632,8 @@ static int __init balanced_irq_init(void)
630 printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); 632 printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
631failed: 633failed:
632 for (i = 0; i < NR_CPUS; i++) { 634 for (i = 0; i < NR_CPUS; i++) {
633 if(irq_cpu_data[i].irq_delta) 635 kfree(irq_cpu_data[i].irq_delta);
634 kfree(irq_cpu_data[i].irq_delta); 636 kfree(irq_cpu_data[i].last_irq);
635 if(irq_cpu_data[i].last_irq)
636 kfree(irq_cpu_data[i].last_irq);
637 } 637 }
638 return 0; 638 return 0;
639} 639}
@@ -1634,12 +1634,43 @@ static void __init enable_IO_APIC(void)
1634 */ 1634 */
1635void disable_IO_APIC(void) 1635void disable_IO_APIC(void)
1636{ 1636{
1637 int pin;
1637 /* 1638 /*
1638 * Clear the IO-APIC before rebooting: 1639 * Clear the IO-APIC before rebooting:
1639 */ 1640 */
1640 clear_IO_APIC(); 1641 clear_IO_APIC();
1641 1642
1642 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);
1643} 1674}
1644 1675
1645/* 1676/*