linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / i386 / kernel / io_apic.c
index 4fb32c5..39d9a5f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/config.h>
 #include <linux/smp_lock.h>
 #include <linux/mc146818rtc.h>
 #include <linux/compiler.h>
@@ -37,7 +38,6 @@
 #include <asm/desc.h>
 #include <asm/timer.h>
 #include <asm/i8259.h>
-#include <asm/nmi.h>
 
 #include <mach_apic.h>
 
@@ -50,7 +50,6 @@ atomic_t irq_mis_count;
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
 static DEFINE_SPINLOCK(ioapic_lock);
-static DEFINE_SPINLOCK(vector_lock);
 
 int timer_over_8254 __initdata = 1;
 
@@ -268,7 +267,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 # include <linux/slab.h>               /* kmalloc() */
 # include <linux/timer.h>      /* time_after() */
  
-#ifdef CONFIG_BALANCED_IRQ_DEBUG
+# ifdef CONFIG_BALANCED_IRQ_DEBUG
 #  define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
 #  define Dprintk(x...) do { TDprintk(x); } while (0)
 # else
@@ -276,15 +275,10 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 #  define Dprintk(x...) 
 # endif
 
-#define IRQBALANCE_CHECK_ARCH -999
-#define MAX_BALANCED_IRQ_INTERVAL      (5*HZ)
-#define MIN_BALANCED_IRQ_INTERVAL      (HZ/2)
-#define BALANCED_IRQ_MORE_DELTA                (HZ/10)
-#define BALANCED_IRQ_LESS_DELTA                (HZ)
 
-static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
-static int physical_balance __read_mostly;
-static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
+#define IRQBALANCE_CHECK_ARCH -999
+static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
+static int physical_balance = 0;
 
 static struct irq_cpu_info {
        unsigned long * last_irq;
@@ -303,14 +297,12 @@ static struct irq_cpu_info {
 
 #define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
 
-static cpumask_t balance_irq_affinity[NR_IRQS] = {
-       [0 ... NR_IRQS-1] = CPU_MASK_ALL
-};
+#define MAX_BALANCED_IRQ_INTERVAL      (5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL      (HZ/2)
+#define BALANCED_IRQ_MORE_DELTA                (HZ/10)
+#define BALANCED_IRQ_LESS_DELTA                (HZ)
 
-void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
-{
-       balance_irq_affinity[irq] = mask;
-}
+static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
 
 static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
                        unsigned long now, int direction)
@@ -348,7 +340,7 @@ static inline void balance_irq(int cpu, int irq)
        if (irqbalance_disabled)
                return; 
 
-       cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
+       cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
        new_cpu = move(cpu, allowed_mask, now, 1);
        if (cpu != new_cpu) {
                set_pending_irq(irq, cpumask_of_cpu(new_cpu));
@@ -359,8 +351,8 @@ static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
 {
        int i, j;
        Dprintk("Rotating IRQs among CPUs.\n");
-       for_each_online_cpu(i) {
-               for (j = 0; j < NR_IRQS; j++) {
+       for (i = 0; i < NR_CPUS; i++) {
+               for (j = 0; cpu_online(i) && (j < NR_IRQS); j++) {
                        if (!irq_desc[j].action)
                                continue;
                        /* Is it a significant load ?  */
@@ -389,7 +381,7 @@ static void do_irq_balance(void)
        unsigned long imbalance = 0;
        cpumask_t allowed_mask, target_cpu_mask, tmp;
 
-       for_each_possible_cpu(i) {
+       for (i = 0; i < NR_CPUS; i++) {
                int package_index;
                CPU_IRQ(i) = 0;
                if (!cpu_online(i))
@@ -430,7 +422,9 @@ static void do_irq_balance(void)
                }
        }
        /* Find the least loaded processor package */
-       for_each_online_cpu(i) {
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!cpu_online(i))
+                       continue;
                if (i != CPU_TO_PACKAGEINDEX(i))
                        continue;
                if (min_cpu_irq > CPU_IRQ(i)) {
@@ -447,7 +441,9 @@ tryanothercpu:
         */
        tmp_cpu_irq = 0;
        tmp_loaded = -1;
-       for_each_online_cpu(i) {
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!cpu_online(i))
+                       continue;
                if (i != CPU_TO_PACKAGEINDEX(i))
                        continue;
                if (max_cpu_irq <= CPU_IRQ(i)) 
@@ -537,9 +533,7 @@ tryanotherirq:
                }
        }
 
-       cpus_and(allowed_mask,
-               cpu_online_map,
-               balance_irq_affinity[selected_irq]);
+       cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
        target_cpu_mask = cpumask_of_cpu(min_loaded);
        cpus_and(tmp, target_cpu_mask, allowed_mask);
 
@@ -580,7 +574,7 @@ static int balanced_irq(void *unused)
        
        /* push everything to CPU 0 to give us a starting point.  */
        for (i = 0 ; i < NR_IRQS ; i++) {
-               irq_desc[i].pending_mask = cpumask_of_cpu(0);
+               pending_irq_cpumask[i] = cpumask_of_cpu(0);
                set_pending_irq(i, cpumask_of_cpu(0));
        }
 
@@ -625,7 +619,9 @@ static int __init balanced_irq_init(void)
        if (smp_num_siblings > 1 && !cpus_empty(tmp))
                physical_balance = 1;
 
-       for_each_online_cpu(i) {
+       for (i = 0; i < NR_CPUS; i++) {
+               if (!cpu_online(i))
+                       continue;
                irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
                irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL);
                if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) {
@@ -642,11 +638,9 @@ static int __init balanced_irq_init(void)
        else 
                printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
 failed:
-       for_each_possible_cpu(i) {
+       for (i = 0; i < NR_CPUS; i++) {
                kfree(irq_cpu_data[i].irq_delta);
-               irq_cpu_data[i].irq_delta = NULL;
                kfree(irq_cpu_data[i].last_irq);
-               irq_cpu_data[i].last_irq = NULL;
        }
        return 0;
 }
@@ -654,7 +648,7 @@ failed:
 int __init irqbalance_disable(char *str)
 {
        irqbalance_disabled = 1;
-       return 1;
+       return 0;
 }
 
 __setup("noirqbalance", irqbalance_disable);
@@ -1162,17 +1156,10 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 int assign_irq_vector(int irq)
 {
        static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
-       unsigned long flags;
-       int vector;
 
-       BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
-
-       spin_lock_irqsave(&vector_lock, flags);
-
-       if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
-               spin_unlock_irqrestore(&vector_lock, flags);
+       BUG_ON(irq >= NR_IRQ_VECTORS);
+       if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
                return IO_APIC_VECTOR(irq);
-       }
 next:
        current_vector += 8;
        if (current_vector == SYSCALL_VECTOR)
@@ -1180,21 +1167,16 @@ next:
 
        if (current_vector >= FIRST_SYSTEM_VECTOR) {
                offset++;
-               if (!(offset%8)) {
-                       spin_unlock_irqrestore(&vector_lock, flags);
+               if (!(offset%8))
                        return -ENOSPC;
-               }
                current_vector = FIRST_DEVICE_VECTOR + offset;
        }
 
-       vector = current_vector;
-       vector_irq[vector] = irq;
+       vector_irq[current_vector] = irq;
        if (irq != AUTO_ASSIGN)
-               IO_APIC_VECTOR(irq) = vector;
-
-       spin_unlock_irqrestore(&vector_lock, flags);
+               IO_APIC_VECTOR(irq) = current_vector;
 
-       return vector;
+       return current_vector;
 }
 
 static struct hw_interrupt_type ioapic_level_type;
@@ -1204,18 +1186,23 @@ static struct hw_interrupt_type ioapic_edge_type;
 #define IOAPIC_EDGE    0
 #define IOAPIC_LEVEL   1
 
-static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
+static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
 {
-       unsigned idx;
-
-       idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
-
-       if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-                       trigger == IOAPIC_LEVEL)
-               irq_desc[idx].chip = &ioapic_level_type;
-       else
-               irq_desc[idx].chip = &ioapic_edge_type;
-       set_intr_gate(vector, interrupt[idx]);
+       if (use_pci_vector() && !platform_legacy_irq(irq)) {
+               if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+                               trigger == IOAPIC_LEVEL)
+                       irq_desc[vector].handler = &ioapic_level_type;
+               else
+                       irq_desc[vector].handler = &ioapic_edge_type;
+               set_intr_gate(vector, interrupt[vector]);
+       } else  {
+               if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+                               trigger == IOAPIC_LEVEL)
+                       irq_desc[irq].handler = &ioapic_level_type;
+               else
+                       irq_desc[irq].handler = &ioapic_edge_type;
+               set_intr_gate(vector, interrupt[irq]);
+       }
 }
 
 static void __init setup_IO_APIC_irqs(void)
@@ -1326,7 +1313,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
         * The timer IRQ doesn't have to know that behind the
         * scene we have a 8259A-master in AEOI mode ...
         */
-       irq_desc[0].chip = &ioapic_edge_type;
+       irq_desc[0].handler = &ioapic_edge_type;
 
        /*
         * Add it to the IO-APIC irq-routing table:
@@ -1774,8 +1761,7 @@ static void __init setup_ioapic_ids_from_mpc(void)
         * Don't check I/O APIC IDs for xAPIC systems.  They have
         * no meaning without the serial APIC bus.
         */
-       if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
-               || APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+       if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 < 15))
                return;
        /*
         * This is broken; anything with a real cpu count has to
@@ -2070,13 +2056,6 @@ static void set_ioapic_affinity_vector (unsigned int vector,
 #endif
 #endif
 
-static int ioapic_retrigger(unsigned int irq)
-{
-       send_IPI_self(IO_APIC_VECTOR(irq));
-
-       return 1;
-}
-
 /*
  * Level and edge triggered IO-APIC interrupts need different handling,
  * so we use two separate IRQ descriptors. Edge triggered IRQs can be
@@ -2096,7 +2075,6 @@ static struct hw_interrupt_type ioapic_edge_type __read_mostly = {
 #ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity,
 #endif
-       .retrigger      = ioapic_retrigger,
 };
 
 static struct hw_interrupt_type ioapic_level_type __read_mostly = {
@@ -2110,7 +2088,6 @@ static struct hw_interrupt_type ioapic_level_type __read_mostly = {
 #ifdef CONFIG_SMP
        .set_affinity   = set_ioapic_affinity,
 #endif
-       .retrigger      = ioapic_retrigger,
 };
 
 static inline void init_IO_APIC_traps(void)
@@ -2145,7 +2122,7 @@ static inline void init_IO_APIC_traps(void)
                                make_8259A_irq(irq);
                        else
                                /* Strange. Oh, well.. */
-                               irq_desc[irq].chip = &no_irq_type;
+                               irq_desc[irq].handler = &no_irq_type;
                }
        }
 }
@@ -2264,8 +2241,6 @@ static inline void unlock_ExtINT_logic(void)
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-int timer_uses_ioapic_pin_0;
-
 /*
  * This code may look a bit paranoid, but it's supposed to cooperate with
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
@@ -2302,9 +2277,6 @@ static inline void check_timer(void)
        pin2  = ioapic_i8259.pin;
        apic2 = ioapic_i8259.apic;
 
-       if (pin1 == 0)
-               timer_uses_ioapic_pin_0 = 1;
-
        printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
                vector, apic1, pin1, apic2, pin2);
 
@@ -2361,7 +2333,7 @@ static inline void check_timer(void)
        printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
 
        disable_8259A_irq(0);
-       irq_desc[0].chip = &lapic_irq_type;
+       irq_desc[0].handler = &lapic_irq_type;
        apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);   /* Fixed mode */
        enable_8259A_irq(0);