]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/io_apic_32.c
x86: Add a debugfs interface to dump PAT memtype
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / io_apic_32.c
index fedb3b113acee3ac9fb80f12ee235c83402e6f5a..603261a5885cf2a1e1f55be2845197641e1a2d61 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/bootmem.h>
 #include <linux/mc146818rtc.h>
 #include <linux/compiler.h>
 #include <linux/acpi.h>
@@ -1207,6 +1208,11 @@ static int assign_irq_vector(int irq)
 
        return vector;
 }
+
+void setup_vector_irq(int cpu)
+{
+}
+
 static struct irq_chip ioapic_chip;
 
 #define IOAPIC_AUTO    -1
@@ -2014,7 +2020,7 @@ static inline void init_IO_APIC_traps(void)
  * The local APIC irq-chip implementation:
  */
 
-static void ack_apic(unsigned int irq)
+static void ack_lapic_irq(unsigned int irq)
 {
        ack_APIC_irq();
 }
@@ -2039,9 +2045,17 @@ static struct irq_chip lapic_chip __read_mostly = {
        .name           = "local-APIC",
        .mask           = mask_lapic_irq,
        .unmask         = unmask_lapic_irq,
-       .eoi            = ack_apic,
+       .ack            = ack_lapic_irq,
 };
 
+static void lapic_register_intr(int irq, int vector)
+{
+       irq_desc[irq].status &= ~IRQ_LEVEL;
+       set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+                                     "edge");
+       set_intr_gate(vector, interrupt[irq]);
+}
+
 static void __init setup_nmi(void)
 {
        /*
@@ -2241,8 +2255,7 @@ static inline void __init check_timer(void)
 
        printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
 
-       set_irq_chip_and_handler_name(0, &lapic_chip, handle_fasteoi_irq,
-                                     "fasteoi");
+       lapic_register_intr(0, vector);
        apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);   /* Fixed mode */
        enable_8259A_irq(0);
 
@@ -2274,11 +2287,21 @@ out:
 }
 
 /*
- *
- * IRQ's that are handled by the PIC in the MPS IOAPIC case.
- * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
- *   Linux doesn't really care, as it's not actually used
- *   for any interrupt handling anyway.
+ * Traditionally ISA IRQ2 is the cascade IRQ, and is not available
+ * to devices.  However there may be an I/O APIC pin available for
+ * this interrupt regardless.  The pin may be left unconnected, but
+ * typically it will be reused as an ExtINT cascade interrupt for
+ * the master 8259A.  In the MPS case such a pin will normally be
+ * reported as an ExtINT interrupt in the MP table.  With ACPI
+ * there is no provision for ExtINT interrupts, and in the absence
+ * of an override it would be treated as an ordinary ISA I/O APIC
+ * interrupt, that is edge-triggered and unmasked by default.  We
+ * used to do this, but it caused problems on some systems because
+ * of the NMI watchdog and sometimes IRQ0 of the 8254 timer using
+ * the same ExtINT cascade interrupt to drive the local APIC of the
+ * bootstrap processor.  Therefore we refrain from routing IRQ2 to
+ * the I/O APIC in all cases now.  No actual device should request
+ * it anyway.  --macro
  */
 #define PIC_IRQS       (1 << PIC_CASCADE_IR)
 
@@ -2292,10 +2315,7 @@ void __init setup_IO_APIC(void)
 
        enable_IO_APIC();
 
-       if (acpi_ioapic)
-               io_apic_irqs = ~0;      /* all IRQs go through IOAPIC */
-       else
-               io_apic_irqs = ~PIC_IRQS;
+       io_apic_irqs = ~PIC_IRQS;
 
        printk("ENABLING IO-APIC IRQs\n");
 
@@ -2847,3 +2867,34 @@ static int __init parse_noapic(char *arg)
        return 0;
 }
 early_param("noapic", parse_noapic);
+
+void __init ioapic_init_mappings(void)
+{
+       unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+       int i;
+
+       for (i = 0; i < nr_ioapics; i++) {
+               if (smp_found_config) {
+                       ioapic_phys = mp_ioapics[i].mp_apicaddr;
+                       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;
+                       }
+               } else {
+fake_ioapic_page:
+                       ioapic_phys = (unsigned long)
+                                     alloc_bootmem_pages(PAGE_SIZE);
+                       ioapic_phys = __pa(ioapic_phys);
+               }
+               set_fixmap_nocache(idx, ioapic_phys);
+               printk(KERN_DEBUG "mapped IOAPIC to %08lx (%08lx)\n",
+                      __fix_to_virt(idx), ioapic_phys);
+               idx++;
+       }
+}
+