]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/io_apic.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / io_apic.c
index a466b04ad5a42272c4c4d2ffbeb93bf3d5bbdb99..7a3f2028e2eb9e01a757a93b0de5b2e4f77f3634 100644 (file)
@@ -41,6 +41,7 @@
 #endif
 #include <linux/bootmem.h>
 #include <linux/dmar.h>
+#include <linux/hpet.h>
 
 #include <asm/idle.h>
 #include <asm/io.h>
@@ -56,6 +57,9 @@
 #include <asm/hypertransport.h>
 #include <asm/setup.h>
 #include <asm/irq_remapping.h>
+#include <asm/hpet.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/uv_irq.h>
 
 #include <mach_ipi.h>
 #include <mach_apic.h>
@@ -72,13 +76,6 @@ int sis_apic_bug = -1;
 static DEFINE_SPINLOCK(ioapic_lock);
 static DEFINE_SPINLOCK(vector_lock);
 
-int first_free_entry;
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-int pin_map_size;
-
 /*
  * # of IRQ routing registers
  */
@@ -110,11 +107,9 @@ static int __init parse_noapic(char *str)
 }
 early_param("noapic", parse_noapic);
 
-struct irq_cfg;
 struct irq_pin_list;
 struct irq_cfg {
        unsigned int irq;
-       struct irq_cfg *next;
        struct irq_pin_list *irq_2_pin;
        cpumask_t domain;
        cpumask_t old_domain;
@@ -124,7 +119,7 @@ struct irq_cfg {
 };
 
 /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
-static struct irq_cfg irq_cfg_legacy[] __initdata = {
+static struct irq_cfg irq_cfgx[NR_IRQS] = {
        [0]  = { .irq =  0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR,  },
        [1]  = { .irq =  1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR,  },
        [2]  = { .irq =  2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR,  },
@@ -143,144 +138,26 @@ static struct irq_cfg irq_cfg_legacy[] __initdata = {
        [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
 };
 
-static struct irq_cfg irq_cfg_init = { .irq =  -1U, };
-/* need to be biger than size of irq_cfg_legacy */
-static int nr_irq_cfg = 32;
-
-static int __init parse_nr_irq_cfg(char *arg)
-{
-       if (arg) {
-               nr_irq_cfg = simple_strtoul(arg, NULL, 0);
-               if (nr_irq_cfg < 32)
-                       nr_irq_cfg = 32;
-       }
-       return 0;
-}
-
-early_param("nr_irq_cfg", parse_nr_irq_cfg);
-
-static void init_one_irq_cfg(struct irq_cfg *cfg)
-{
-       memcpy(cfg, &irq_cfg_init, sizeof(struct irq_cfg));
-}
-
-static struct irq_cfg *irq_cfgx;
-static struct irq_cfg *irq_cfgx_free;
-static void __init init_work(void *data)
-{
-       struct dyn_array *da = data;
-       struct irq_cfg *cfg;
-       int legacy_count;
-       int i;
-
-       cfg = *da->name;
-
-       memcpy(cfg, irq_cfg_legacy, sizeof(irq_cfg_legacy));
-
-       legacy_count = sizeof(irq_cfg_legacy)/sizeof(irq_cfg_legacy[0]);
-       for (i = legacy_count; i < *da->nr; i++)
-               init_one_irq_cfg(&cfg[i]);
-
-       for (i = 1; i < *da->nr; i++)
-               cfg[i-1].next = &cfg[i];
-
-       irq_cfgx_free = &irq_cfgx[legacy_count];
-       irq_cfgx[legacy_count - 1].next = NULL;
-}
-
-#define for_each_irq_cfg(cfg)          \
-       for (cfg = irq_cfgx; cfg; cfg = cfg->next)
-
-DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
+#define for_each_irq_cfg(irq, cfg)             \
+       for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)
 
 static struct irq_cfg *irq_cfg(unsigned int irq)
 {
-       struct irq_cfg *cfg;
-
-       cfg = irq_cfgx;
-       while (cfg) {
-               if (cfg->irq == irq)
-                       return cfg;
-
-               cfg = cfg->next;
-       }
-
-       return NULL;
+       return irq < nr_irqs ? irq_cfgx + irq : NULL;
 }
 
 static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
 {
-       struct irq_cfg *cfg, *cfg_pri;
-       int i;
-       int count = 0;
-
-       cfg_pri = cfg = irq_cfgx;
-       while (cfg) {
-               if (cfg->irq == irq)
-                       return cfg;
-
-               cfg_pri = cfg;
-               cfg = cfg->next;
-               count++;
-       }
-
-       if (!irq_cfgx_free) {
-               unsigned long phys;
-               unsigned long total_bytes;
-               /*
-                *  we run out of pre-allocate ones, allocate more
-                */
-               printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
-
-               total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
-               if (after_bootmem)
-                       cfg = kzalloc(total_bytes, GFP_ATOMIC);
-               else
-                       cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
-
-               if (!cfg)
-                       panic("please boot with nr_irq_cfg= %d\n", count * 2);
-
-               phys = __pa(cfg);
-               printk(KERN_DEBUG "irq_irq ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
-
-               for (i = 0; i < nr_irq_cfg; i++)
-                       init_one_irq_cfg(&cfg[i]);
-
-               for (i = 1; i < nr_irq_cfg; i++)
-                       cfg[i-1].next = &cfg[i];
-
-               irq_cfgx_free = cfg;
-       }
-
-       cfg = irq_cfgx_free;
-       irq_cfgx_free = irq_cfgx_free->next;
-       cfg->next = NULL;
-       if (cfg_pri)
-               cfg_pri->next = cfg;
-       else
-               irq_cfgx = cfg;
-       cfg->irq = irq;
-       printk(KERN_DEBUG "found new irq_cfg for irq %d\n", cfg->irq);
-#ifdef CONFIG_HAVE_SPARSE_IRQ_DEBUG
-       {
-               /* dump the results */
-               struct irq_cfg *cfg;
-               unsigned long phys;
-               unsigned long bytes = sizeof(struct irq_cfg);
-
-               printk(KERN_DEBUG "=========================== %d\n", irq);
-               printk(KERN_DEBUG "irq_cfg dump after get that for %d\n", irq);
-               for_each_irq_cfg(cfg) {
-                       phys = __pa(cfg);
-                       printk(KERN_DEBUG "irq_cfg %d ==> [%#lx - %#lx]\n", cfg->irq, phys, phys + bytes);
-               }
-               printk(KERN_DEBUG "===========================\n");
-       }
-#endif
-       return cfg;
+       return irq_cfg(irq);
 }
 
+/*
+ * Rough estimation of how many shared IRQs there are, can be changed
+ * anytime.
+ */
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
+#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -293,59 +170,29 @@ struct irq_pin_list {
        struct irq_pin_list *next;
 };
 
-static struct irq_pin_list *irq_2_pin_head;
-/* fill one page ? */
-static int nr_irq_2_pin = 0x100;
+static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];
 static struct irq_pin_list *irq_2_pin_ptr;
-static void __init irq_2_pin_init_work(void *data)
+
+static void __init irq_2_pin_init(void)
 {
-       struct dyn_array *da = data;
-       struct irq_pin_list *pin;
+       struct irq_pin_list *pin = irq_2_pin_head;
        int i;
 
-       pin = *da->name;
-
-       for (i = 1; i < *da->nr; i++)
+       for (i = 1; i < PIN_MAP_SIZE; i++)
                pin[i-1].next = &pin[i];
 
        irq_2_pin_ptr = &pin[0];
 }
-DEFINE_DYN_ARRAY(irq_2_pin_head, sizeof(struct irq_pin_list), nr_irq_2_pin, PAGE_SIZE, irq_2_pin_init_work);
 
 static struct irq_pin_list *get_one_free_irq_2_pin(void)
 {
-       struct irq_pin_list *pin;
-       int i;
-
-       pin = irq_2_pin_ptr;
-
-       if (pin) {
-               irq_2_pin_ptr = pin->next;
-               pin->next = NULL;
-               return pin;
-       }
-
-       /*
-        *  we run out of pre-allocate ones, allocate more
-        */
-       printk(KERN_DEBUG "try to get more irq_2_pin %d\n", nr_irq_2_pin);
-
-       if (after_bootmem)
-               pin = kzalloc(sizeof(struct irq_pin_list)*nr_irq_2_pin,
-                                GFP_ATOMIC);
-       else
-               pin = __alloc_bootmem_nopanic(sizeof(struct irq_pin_list) *
-                               nr_irq_2_pin, PAGE_SIZE, 0);
+       struct irq_pin_list *pin = irq_2_pin_ptr;
 
        if (!pin)
                panic("can not get more irq_2_pin\n");
 
-       for (i = 1; i < nr_irq_2_pin; i++)
-               pin[i-1].next = &pin[i];
-
        irq_2_pin_ptr = pin->next;
        pin->next = NULL;
-
        return pin;
 }
 
@@ -384,8 +231,9 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
 static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
 {
        struct io_apic __iomem *io_apic = io_apic_base(apic);
-        if (sis_apic_bug)
-                writel(reg, &io_apic->index);
+
+       if (sis_apic_bug)
+               writel(reg, &io_apic->index);
        writel(value, &io_apic->data);
 }
 
@@ -562,7 +410,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
                cfg->irq_2_pin = entry;
                entry->apic = apic;
                entry->pin = pin;
-               printk(KERN_DEBUG " 0 add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
                return;
        }
 
@@ -578,7 +425,6 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
        entry = entry->next;
        entry->apic = apic;
        entry->pin = pin;
-       printk(KERN_DEBUG " x add_pin_to_irq: irq %d --> apic %d pin %d\n", irq, apic, pin);
 }
 
 /*
@@ -608,65 +454,66 @@ static void __init replace_pin_at_irq(unsigned int irq,
                add_pin_to_irq(irq, newapic, newpin);
 }
 
-#define __DO_ACTION(R, ACTION_ENABLE, ACTION_DISABLE, FINAL)           \
-                                                                       \
-{                                                                      \
-       int pin;                                                        \
-       struct irq_cfg *cfg;                                            \
-       struct irq_pin_list *entry;                                     \
-                                                                       \
-       cfg = irq_cfg(irq);                                             \
-       entry = cfg->irq_2_pin;                                         \
-       for (;;) {                                                      \
-               unsigned int reg;                                       \
-               if (!entry)                                             \
-                       break;                                          \
-               pin = entry->pin;                                       \
-               reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
-               reg ACTION_DISABLE;                                     \
-               reg ACTION_ENABLE;                                      \
-               io_apic_modify(entry->apic, 0x10 + R + pin*2, reg);     \
-               FINAL;                                                  \
-               if (!entry->next)                                       \
-                       break;                                          \
-               entry = entry->next;                                    \
-       }                                                               \
-}
-
-#define DO_ACTION(name,R, ACTION_ENABLE, ACTION_DISABLE, FINAL)                \
-                                                                       \
-       static void name##_IO_APIC_irq (unsigned int irq)               \
-       __DO_ACTION(R, ACTION_ENABLE, ACTION_DISABLE, FINAL)
-
-/* mask = 0 */
-DO_ACTION(__unmask,    0, |= 0, &= ~IO_APIC_REDIR_MASKED, )
+static inline void io_apic_modify_irq(unsigned int irq,
+                               int mask_and, int mask_or,
+                               void (*final)(struct irq_pin_list *entry))
+{
+       int pin;
+       struct irq_cfg *cfg;
+       struct irq_pin_list *entry;
+
+       cfg = irq_cfg(irq);
+       for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
+               unsigned int reg;
+               pin = entry->pin;
+               reg = io_apic_read(entry->apic, 0x10 + pin * 2);
+               reg &= mask_and;
+               reg |= mask_or;
+               io_apic_modify(entry->apic, 0x10 + pin * 2, reg);
+               if (final)
+                       final(entry);
+       }
+}
+
+static void __unmask_IO_APIC_irq(unsigned int irq)
+{
+       io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL);
+}
 
 #ifdef CONFIG_X86_64
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
+void io_apic_sync(struct irq_pin_list *entry)
 {
-       struct io_apic __iomem *io_apic = io_apic_base(apic);
+       /*
+        * Synchronize the IO-APIC and the CPU by doing
+        * a dummy read from the IO-APIC
+        */
+       struct io_apic __iomem *io_apic;
+       io_apic = io_apic_base(entry->apic);
        readl(&io_apic->data);
 }
 
-/* mask = 1 */
-DO_ACTION(__mask,      0, |= IO_APIC_REDIR_MASKED, &= ~0, io_apic_sync(entry->apic))
-
-#else
-
-/* mask = 1 */
-DO_ACTION(__mask,      0, |= IO_APIC_REDIR_MASKED, &= ~0, )
-
-/* mask = 1, trigger = 0 */
-DO_ACTION(__mask_and_edge, 0, |= IO_APIC_REDIR_MASKED, &= ~IO_APIC_REDIR_LEVEL_TRIGGER, )
+static void __mask_IO_APIC_irq(unsigned int irq)
+{
+       io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
+}
+#else /* CONFIG_X86_32 */
+static void __mask_IO_APIC_irq(unsigned int irq)
+{
+       io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL);
+}
 
-/* mask = 0, trigger = 1 */
-DO_ACTION(__unmask_and_level, 0, |= IO_APIC_REDIR_LEVEL_TRIGGER, &= ~IO_APIC_REDIR_MASKED, )
+static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
+{
+       io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER,
+                       IO_APIC_REDIR_MASKED, NULL);
+}
 
-#endif
+static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
+{
+       io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED,
+                       IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
+}
+#endif /* CONFIG_X86_32 */
 
 static void mask_IO_APIC_irq (unsigned int irq)
 {
@@ -795,7 +642,7 @@ int save_mask_IO_APIC_setup(void)
                        kzalloc(sizeof(struct IO_APIC_route_entry) *
                                nr_ioapic_registers[apic], GFP_KERNEL);
                if (!early_ioapic_entries[apic])
-                       return -ENOMEM;
+                       goto nomem;
        }
 
        for (apic = 0; apic < nr_ioapics; apic++)
@@ -809,17 +656,31 @@ int save_mask_IO_APIC_setup(void)
                                ioapic_write_entry(apic, pin, entry);
                        }
                }
+
        return 0;
+
+nomem:
+       while (apic >= 0)
+               kfree(early_ioapic_entries[apic--]);
+       memset(early_ioapic_entries, 0,
+               ARRAY_SIZE(early_ioapic_entries));
+
+       return -ENOMEM;
 }
 
 void restore_IO_APIC_setup(void)
 {
        int apic, pin;
 
-       for (apic = 0; apic < nr_ioapics; apic++)
+       for (apic = 0; apic < nr_ioapics; apic++) {
+               if (!early_ioapic_entries[apic])
+                       break;
                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
                        ioapic_write_entry(apic, pin,
                                           early_ioapic_entries[apic][pin]);
+               kfree(early_ioapic_entries[apic]);
+               early_ioapic_entries[apic] = NULL;
+       }
 }
 
 void reinit_intr_remapped_IO_APIC(int intr_remapping)
@@ -1131,11 +992,11 @@ static int pin_2_irq(int idx, int apic, int pin)
                while (i < apic)
                        irq += nr_ioapic_registers[i++];
                irq += pin;
-                /*
+               /*
                  * For MPS mode, so far only needed by ES7000 platform
                  */
-                if (ioapic_renumber_irq)
-                        irq = ioapic_renumber_irq(apic, irq);
+               if (ioapic_renumber_irq)
+                       irq = ioapic_renumber_irq(apic, irq);
        }
 
 #ifdef CONFIG_X86_32
@@ -1289,11 +1150,10 @@ void __setup_vector_irq(int cpu)
        struct irq_cfg *cfg;
 
        /* Mark the inuse vectors */
-       for_each_irq_cfg(cfg) {
+       for_each_irq_cfg(irq, cfg) {
                if (!cpu_isset(cpu, cfg->domain))
                        continue;
                vector = cfg->vector;
-               irq = cfg->irq;
                per_cpu(vector_irq, cpu)[vector] = irq;
        }
        /* Mark the free vectors */
@@ -1320,19 +1180,19 @@ static struct irq_chip ir_ioapic_chip;
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
 {
-        int apic, idx, pin;
+       int apic, idx, pin;
 
-        for (apic = 0; apic < nr_ioapics; apic++) {
-                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-                        idx = find_irq_entry(apic, pin, mp_INT);
-                        if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
-                                return irq_trigger(idx);
-                }
-        }
-        /*
+       for (apic = 0; apic < nr_ioapics; apic++) {
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+                       idx = find_irq_entry(apic, pin, mp_INT);
+                       if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+                               return irq_trigger(idx);
+               }
+       }
+       /*
          * nonexistent IRQs are edge default
          */
-        return 0;
+       return 0;
 }
 #else
 static inline int IO_APIC_irq_trigger(int irq)
@@ -1345,11 +1205,7 @@ static void ioapic_register_intr(int irq, unsigned long trigger)
 {
        struct irq_desc *desc;
 
-       /* first time to use this irq_desc */
-       if (irq < 16)
-               desc = irq_to_desc(irq);
-       else
-               desc = irq_to_desc_alloc(irq);
+       desc = irq_to_desc(irq);
 
        if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
            trigger == IOAPIC_LEVEL)
@@ -1484,41 +1340,49 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
 
 static void __init setup_IO_APIC_irqs(void)
 {
-       int apic, pin, idx, irq, first_notcon = 1;
+       int apic, pin, idx, irq;
+       int notcon = 0;
 
        apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
        for (apic = 0; apic < nr_ioapics; apic++) {
-       for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
-
-               idx = find_irq_entry(apic,pin,mp_INT);
-               if (idx == -1) {
-                       if (first_notcon) {
-                               apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mp_apicid, pin);
-                               first_notcon = 0;
-                       } else
-                               apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mp_apicid, pin);
-                       continue;
-               }
-               if (!first_notcon) {
-                       apic_printk(APIC_VERBOSE, " not connected.\n");
-                       first_notcon = 1;
-               }
+               for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+
+                       idx = find_irq_entry(apic, pin, mp_INT);
+                       if (idx == -1) {
+                               if (!notcon) {
+                                       notcon = 1;
+                                       apic_printk(APIC_VERBOSE,
+                                               KERN_DEBUG " %d-%d",
+                                               mp_ioapics[apic].mp_apicid,
+                                               pin);
+                               } else
+                                       apic_printk(APIC_VERBOSE, " %d-%d",
+                                               mp_ioapics[apic].mp_apicid,
+                                               pin);
+                               continue;
+                       }
+                       if (notcon) {
+                               apic_printk(APIC_VERBOSE,
+                                       " (apicid-pin) not connected\n");
+                               notcon = 0;
+                       }
 
-               irq = pin_2_irq(idx, apic, pin);
+                       irq = pin_2_irq(idx, apic, pin);
 #ifdef CONFIG_X86_32
-                if (multi_timer_check(apic, irq))
-                        continue;
+                       if (multi_timer_check(apic, irq))
+                               continue;
 #endif
-               add_pin_to_irq(irq, apic, pin);
+                       add_pin_to_irq(irq, apic, pin);
 
-               setup_IO_APIC_irq(apic, pin, irq,
-                                 irq_trigger(idx), irq_polarity(idx));
-       }
+                       setup_IO_APIC_irq(apic, pin, irq,
+                                       irq_trigger(idx), irq_polarity(idx));
+               }
        }
 
-       if (!first_notcon)
-               apic_printk(APIC_VERBOSE, " not connected.\n");
+       if (notcon)
+               apic_printk(APIC_VERBOSE,
+                       " (apicid-pin) not connected\n");
 }
 
 /*
@@ -1570,6 +1434,7 @@ __apicdebuginit(void) print_IO_APIC(void)
        union IO_APIC_reg_03 reg_03;
        unsigned long flags;
        struct irq_cfg *cfg;
+       unsigned int irq;
 
        if (apic_verbosity == APIC_QUIET)
                return;
@@ -1592,8 +1457,8 @@ __apicdebuginit(void) print_IO_APIC(void)
        reg_01.raw = io_apic_read(apic, 1);
        if (reg_01.bits.version >= 0x10)
                reg_02.raw = io_apic_read(apic, 2);
-        if (reg_01.bits.version >= 0x20)
-                reg_03.raw = io_apic_read(apic, 3);
+       if (reg_01.bits.version >= 0x20)
+               reg_03.raw = io_apic_read(apic, 3);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
        printk("\n");
@@ -1658,11 +1523,11 @@ __apicdebuginit(void) print_IO_APIC(void)
        }
        }
        printk(KERN_DEBUG "IRQ to pin mappings:\n");
-       for_each_irq_cfg(cfg) {
+       for_each_irq_cfg(irq, cfg) {
                struct irq_pin_list *entry = cfg->irq_2_pin;
                if (!entry)
                        continue;
-               printk(KERN_DEBUG "IRQ%d ", cfg->irq);
+               printk(KERN_DEBUG "IRQ%d ", irq);
                for (;;) {
                        printk("-> %d:%d", entry->apic, entry->pin);
                        if (!entry->next)
@@ -1719,21 +1584,30 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
        printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
        if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
-               v = apic_read(APIC_ARBPRI);
-               printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-                       v & APIC_ARBPRI_MASK);
+               if (!APIC_XAPIC(ver)) {
+                       v = apic_read(APIC_ARBPRI);
+                       printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+                              v & APIC_ARBPRI_MASK);
+               }
                v = apic_read(APIC_PROCPRI);
                printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
        }
 
-       v = apic_read(APIC_EOI);
-       printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
-       v = apic_read(APIC_RRR);
-       printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+       /*
+        * Remote read supported only in the 82489DX and local APIC for
+        * Pentium processors.
+        */
+       if (!APIC_INTEGRATED(ver) || maxlvt == 3) {
+               v = apic_read(APIC_RRR);
+               printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
+       }
+
        v = apic_read(APIC_LDR);
        printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
-       v = apic_read(APIC_DFR);
-       printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+       if (!x2apic_enabled()) {
+               v = apic_read(APIC_DFR);
+               printk(KERN_DEBUG "... APIC DFR: %08x\n", v);
+       }
        v = apic_read(APIC_SPIV);
        printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
 
@@ -1753,8 +1627,8 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
        }
 
        icr = apic_icr_read();
-       printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
-       printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
+       printk(KERN_DEBUG "... APIC ICR: %08x\n", (u32)icr);
+       printk(KERN_DEBUG "... APIC ICR2: %08x\n", (u32)(icr >> 32));
 
        v = apic_read(APIC_LVTT);
        printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
@@ -1784,7 +1658,12 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
 
 __apicdebuginit(void) print_all_local_APICs(void)
 {
-       on_each_cpu(print_local_APIC, NULL, 1);
+       int cpu;
+
+       preempt_disable();
+       for_each_online_cpu(cpu)
+               smp_call_function_single(cpu, print_local_APIC, NULL, 1);
+       preempt_enable();
 }
 
 __apicdebuginit(void) print_PIC(void)
@@ -2040,6 +1919,8 @@ static void __init setup_ioapic_ids_from_mpc(void)
 
                reg_00.bits.ID = mp_ioapics[apic].mp_apicid;
                spin_lock_irqsave(&ioapic_lock, flags);
+               io_apic_write(apic, 0, reg_00.raw);
+               spin_unlock_irqrestore(&ioapic_lock, flags);
 
                /*
                 * Sanity check
@@ -2156,9 +2037,9 @@ static int ioapic_retrigger_irq(unsigned int irq)
 #else
 static int ioapic_retrigger_irq(unsigned int irq)
 {
-        send_IPI_self(irq_cfg(irq)->vector);
+       send_IPI_self(irq_cfg(irq)->vector);
 
-        return 1;
+       return 1;
 }
 #endif
 
@@ -2256,7 +2137,7 @@ static int migrate_irq_remapped_level(int irq)
 
        if (io_apic_level_ack_pending(irq)) {
                /*
-                * Interrupt in progress. Migrating irq now will change the
+                * Interrupt in progress. Migrating irq now will change the
                 * vector information in the IO-APIC RTE and that will confuse
                 * the EOI broadcast performed by cpu.
                 * So, delay the irq migration to the next instance.
@@ -2396,9 +2277,7 @@ static void ack_apic_edge(unsigned int irq)
        ack_APIC_irq();
 }
 
-#ifdef CONFIG_X86_32
 atomic_t irq_mis_count;
-#endif
 
 static void ack_apic_level(unsigned int irq)
 {
@@ -2493,28 +2372,28 @@ static void ack_apic_level(unsigned int irq)
 }
 
 static struct irq_chip ioapic_chip __read_mostly = {
-       .name           = "IO-APIC",
-       .startup        = startup_ioapic_irq,
-       .mask           = mask_IO_APIC_irq,
-       .unmask         = unmask_IO_APIC_irq,
-       .ack            = ack_apic_edge,
-       .eoi            = ack_apic_level,
+       .name           = "IO-APIC",
+       .startup        = startup_ioapic_irq,
+       .mask           = mask_IO_APIC_irq,
+       .unmask         = unmask_IO_APIC_irq,
+       .ack            = ack_apic_edge,
+       .eoi            = ack_apic_level,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_ioapic_affinity_irq,
+       .set_affinity   = set_ioapic_affinity_irq,
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
 
 #ifdef CONFIG_INTR_REMAP
 static struct irq_chip ir_ioapic_chip __read_mostly = {
-       .name           = "IR-IO-APIC",
-       .startup        = startup_ioapic_irq,
-       .mask           = mask_IO_APIC_irq,
-       .unmask         = unmask_IO_APIC_irq,
-       .ack            = ack_x2apic_edge,
-       .eoi            = ack_x2apic_level,
+       .name           = "IR-IO-APIC",
+       .startup        = startup_ioapic_irq,
+       .mask           = mask_IO_APIC_irq,
+       .unmask         = unmask_IO_APIC_irq,
+       .ack            = ack_x2apic_edge,
+       .eoi            = ack_x2apic_level,
 #ifdef CONFIG_SMP
-       .set_affinity   = set_ir_ioapic_affinity_irq,
+       .set_affinity   = set_ir_ioapic_affinity_irq,
 #endif
        .retrigger      = ioapic_retrigger_irq,
 };
@@ -2537,8 +2416,7 @@ static inline void init_IO_APIC_traps(void)
         * Also, we've got to be careful not to trash gate
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
-       for_each_irq_cfg(cfg) {
-               irq = cfg->irq;
+       for_each_irq_cfg(irq, cfg) {
                if (IO_APIC_IRQ(irq) && !cfg->vector) {
                        /*
                         * Hmm.. We don't have an entry for this,
@@ -2704,8 +2582,8 @@ static inline void __init check_timer(void)
 
        local_irq_save(flags);
 
-        ver = apic_read(APIC_LVR);
-        ver = GET_APIC_VERSION(ver);
+       ver = apic_read(APIC_LVR);
+       ver = GET_APIC_VERSION(ver);
 
        /*
         * get/set the timer IRQ vector:
@@ -2890,12 +2768,12 @@ void __init setup_IO_APIC(void)
        io_apic_irqs = ~PIC_IRQS;
 
        apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
-        /*
+       /*
          * Set up IO-APIC IRQ routing.
          */
 #ifdef CONFIG_X86_32
-        if (!acpi_ioapic)
-                setup_ioapic_ids_from_mpc();
+       if (!acpi_ioapic)
+               setup_ioapic_ids_from_mpc();
 #endif
        sync_Arb_IDs();
        setup_IO_APIC_irqs();
@@ -2910,9 +2788,9 @@ void __init setup_IO_APIC(void)
 
 static int __init io_apic_bug_finalize(void)
 {
-        if (sis_apic_bug == -1)
-                sis_apic_bug = 0;
-        return 0;
+       if (sis_apic_bug == -1)
+               sis_apic_bug = 0;
+       return 0;
 }
 
 late_initcall(io_apic_bug_finalize);
@@ -3012,9 +2890,7 @@ unsigned int create_irq_nr(unsigned int irq_want)
        unsigned long flags;
        struct irq_cfg *cfg_new;
 
-#ifndef CONFIG_HAVE_SPARSE_IRQ
        irq_want = nr_irqs - 1;
-#endif
 
        irq = 0;
        spin_lock_irqsave(&vector_lock, flags);
@@ -3269,7 +3145,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
        if (index < 0) {
                printk(KERN_ERR
                       "Unable to allocate %d IRTE for PCI %s\n", nvec,
-                       pci_name(dev));
+                      pci_name(dev));
                return -ENOSPC;
        }
        return index;
@@ -3300,6 +3176,8 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
 #endif
                set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
+       dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
+
        return 0;
 }
 
@@ -3474,6 +3352,69 @@ int arch_setup_dmar_msi(unsigned int irq)
 }
 #endif
 
+#ifdef CONFIG_HPET_TIMER
+
+#ifdef CONFIG_SMP
+static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask)
+{
+       struct irq_cfg *cfg;
+       struct irq_desc *desc;
+       struct msi_msg msg;
+       unsigned int dest;
+       cpumask_t tmp;
+
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               return;
+
+       if (assign_irq_vector(irq, mask))
+               return;
+
+       cfg = irq_cfg(irq);
+       cpus_and(tmp, cfg->domain, mask);
+       dest = cpu_mask_to_apicid(tmp);
+
+       hpet_msi_read(irq, &msg);
+
+       msg.data &= ~MSI_DATA_VECTOR_MASK;
+       msg.data |= MSI_DATA_VECTOR(cfg->vector);
+       msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+       msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+       hpet_msi_write(irq, &msg);
+       desc = irq_to_desc(irq);
+       desc->affinity = mask;
+}
+#endif /* CONFIG_SMP */
+
+struct irq_chip hpet_msi_type = {
+       .name = "HPET_MSI",
+       .unmask = hpet_msi_unmask,
+       .mask = hpet_msi_mask,
+       .ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+       .set_affinity = hpet_msi_set_affinity,
+#endif
+       .retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_hpet_msi(unsigned int irq)
+{
+       int ret;
+       struct msi_msg msg;
+
+       ret = msi_compose_msg(NULL, irq, &msg);
+       if (ret < 0)
+               return ret;
+
+       hpet_msi_write(irq, &msg);
+       set_irq_chip_and_handler_name(irq, &hpet_msi_type, handle_edge_irq,
+               "edge");
+
+       return 0;
+}
+#endif
+
 #endif /* CONFIG_PCI_MSI */
 /*
  * Hypertransport interrupt support
@@ -3566,11 +3507,116 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
                set_irq_chip_and_handler_name(irq, &ht_irq_chip,
                                              handle_edge_irq, "edge");
+
+               dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
        }
        return err;
 }
 #endif /* CONFIG_HT_IRQ */
 
+#ifdef CONFIG_X86_64
+/*
+ * Re-target the irq to the specified CPU and enable the specified MMR located
+ * on the specified blade to allow the sending of MSIs to the specified CPU.
+ */
+int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
+                      unsigned long mmr_offset)
+{
+       const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
+       struct irq_cfg *cfg;
+       int mmr_pnode;
+       unsigned long mmr_value;
+       struct uv_IO_APIC_route_entry *entry;
+       unsigned long flags;
+       int err;
+
+       err = assign_irq_vector(irq, *eligible_cpu);
+       if (err != 0)
+               return err;
+
+       spin_lock_irqsave(&vector_lock, flags);
+       set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
+                                     irq_name);
+       spin_unlock_irqrestore(&vector_lock, flags);
+
+       cfg = irq_cfg(irq);
+
+       mmr_value = 0;
+       entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+       BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
+       entry->vector = cfg->vector;
+       entry->delivery_mode = INT_DELIVERY_MODE;
+       entry->dest_mode = INT_DEST_MODE;
+       entry->polarity = 0;
+       entry->trigger = 0;
+       entry->mask = 0;
+       entry->dest = cpu_mask_to_apicid(*eligible_cpu);
+
+       mmr_pnode = uv_blade_to_pnode(mmr_blade);
+       uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+
+       return irq;
+}
+
+/*
+ * Disable the specified MMR located on the specified blade so that MSIs are
+ * longer allowed to be sent.
+ */
+void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
+{
+       unsigned long mmr_value;
+       struct uv_IO_APIC_route_entry *entry;
+       int mmr_pnode;
+
+       mmr_value = 0;
+       entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
+       BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
+
+       entry->mask = 1;
+
+       mmr_pnode = uv_blade_to_pnode(mmr_blade);
+       uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
+}
+#endif /* CONFIG_X86_64 */
+
+int __init io_apic_get_redir_entries (int ioapic)
+{
+       union IO_APIC_reg_01    reg_01;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioapic_lock, flags);
+       reg_01.raw = io_apic_read(ioapic, 1);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+
+       return reg_01.bits.entries;
+}
+
+int __init probe_nr_irqs(void)
+{
+       int idx;
+       int nr = 0;
+#ifndef CONFIG_XEN
+       int nr_min = 32;
+#else
+       int nr_min = NR_IRQS;
+#endif
+
+       for (idx = 0; idx < nr_ioapics; idx++)
+               nr += io_apic_get_redir_entries(idx) + 1;
+
+       /* double it for hotplug and msi and nmi */
+       nr <<= 1;
+
+       /* something wrong ? */
+       if (nr < nr_min)
+               nr = nr_min;
+       if (WARN_ON(nr > NR_IRQS))
+               nr = NR_IRQS;
+
+       return nr;
+}
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -3665,19 +3711,6 @@ int __init io_apic_get_version(int ioapic)
 }
 #endif
 
-int __init io_apic_get_redir_entries (int ioapic)
-{
-       union IO_APIC_reg_01    reg_01;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       reg_01.raw = io_apic_read(ioapic, 1);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-
-       return reg_01.bits.entries;
-}
-
-
 int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
        if (!IO_APIC_IRQ(irq)) {
@@ -3800,23 +3833,24 @@ static struct resource * __init ioapic_setup_resources(void)
 void __init ioapic_init_mappings(void)
 {
        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-       int i;
        struct resource *ioapic_res;
+       int i;
 
+       irq_2_pin_init();
        ioapic_res = ioapic_setup_resources();
        for (i = 0; i < nr_ioapics; i++) {
                if (smp_found_config) {
                        ioapic_phys = mp_ioapics[i].mp_apicaddr;
 #ifdef CONFIG_X86_32
-                        if (!ioapic_phys) {
-                                printk(KERN_ERR
-                                       "WARNING: bogus zero IO-APIC "
-                                       "address found in MPTABLE, "
-                                       "disabling IO/APIC support!\n");
-                                smp_found_config = 0;
-                                skip_ioapic_setup = 1;
-                                goto fake_ioapic_page;
-                        }
+                       if (!ioapic_phys) {
+                               printk(KERN_ERR
+                                      "WARNING: bogus zero IO-APIC "
+                                      "address found in MPTABLE, "
+                                      "disabling IO/APIC support!\n");
+                               smp_found_config = 0;
+                               skip_ioapic_setup = 1;
+                               goto fake_ioapic_page;
+                       }
 #endif
                } else {
 #ifdef CONFIG_X86_32