Merge branch 'upstream'
[sfrench/cifs-2.6.git] / arch / x86_64 / kernel / io_apic.c
index fd1e7c36dc23f3a86625dfbb1e984accdbf16f3b..ffed464e6b12274ff62ce9fa0a76e5dca9852663 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
 #include <linux/sysdev.h>
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+#endif
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -47,6 +50,8 @@ static int no_timer_check;
 
 int disable_timer_pin_1 __initdata;
 
+int timer_over_8254 __initdata = 1;
+
 /* Where if anywhere is the i8259 connect in external int mode */
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
@@ -248,6 +253,20 @@ static int __init enable_ioapic_setup(char *str)
 __setup("noapic", disable_ioapic_setup);
 __setup("apic", enable_ioapic_setup);
 
+static int __init setup_disable_8254_timer(char *s)
+{
+       timer_over_8254 = -1;
+       return 1;
+}
+static int __init setup_enable_8254_timer(char *s)
+{
+       timer_over_8254 = 2;
+       return 1;
+}
+
+__setup("disable_8254_timer", setup_disable_8254_timer);
+__setup("enable_8254_timer", setup_enable_8254_timer);
+
 #include <asm/pci-direct.h>
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
@@ -260,6 +279,8 @@ __setup("apic", enable_ioapic_setup);
 
    And another hack to disable the IOMMU on VIA chipsets.
 
+   ... and others. Really should move this somewhere else.
+
    Kludge-O-Rama. */
 void __init check_ioapic(void) 
 { 
@@ -304,8 +325,20 @@ void __init check_ioapic(void)
 #endif
                                        /* RED-PEN skip them on mptables too? */
                                        return;
+
+                               /* This should be actually default, but
+                                  for 2.6.16 let's do it for ATI only where
+                                  it's really needed. */
+                               case PCI_VENDOR_ID_ATI:
+                                       if (timer_over_8254 == 1) {     
+                                               timer_over_8254 = 0;    
+                                       printk(KERN_INFO
+               "ATI board detected. Disabling timer routing over 8254.\n");
+                                       }       
+                                       return;
                                } 
 
+
                                /* No multi-function device? */
                                type = read_pci_config_byte(num,slot,func,
                                                            PCI_HEADER_TYPE);
@@ -910,7 +943,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
        disable_8259A_irq(0);
 
        /* mask LVT0 */
-       apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 
        /*
         * We use logical delivery to get the timer IRQ
@@ -1635,7 +1668,7 @@ static void enable_lapic_irq (unsigned int irq)
        unsigned long v;
 
        v = apic_read(APIC_LVT0);
-       apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
+       apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
 static void disable_lapic_irq (unsigned int irq)
@@ -1643,7 +1676,7 @@ static void disable_lapic_irq (unsigned int irq)
        unsigned long v;
 
        v = apic_read(APIC_LVT0);
-       apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+       apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 }
 
 static void ack_lapic_irq (unsigned int irq)
@@ -1749,6 +1782,8 @@ static inline void unlock_ExtINT_logic(void)
  * a wide range of boards and BIOS bugs.  Fortunately only the timer IRQ
  * is so screwy.  Thanks to Brian Perkins for testing/hacking this beast
  * fanatically on his truly buggy board.
+ *
+ * FIXME: really need to revamp this for modern platforms only.
  */
 static inline void check_timer(void)
 {
@@ -1769,9 +1804,10 @@ static inline void check_timer(void)
         * the 8259A which implies the virtual wire has to be
         * disabled in the local APIC.
         */
-       apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
        init_8259A(1);
-       enable_8259A_irq(0);
+       if (timer_over_8254 > 0)
+               enable_8259A_irq(0);
 
        pin1  = find_isa_irq_pin(0, mp_INT);
        apic1 = find_isa_irq_apic(0, mp_INT);
@@ -1826,7 +1862,7 @@ static inline void check_timer(void)
        }
        printk(" failed.\n");
 
-       if (nmi_watchdog) {
+       if (nmi_watchdog == NMI_IO_APIC) {
                printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
                nmi_watchdog = 0;
        }
@@ -1835,21 +1871,21 @@ static inline void check_timer(void)
 
        disable_8259A_irq(0);
        irq_desc[0].handler = &lapic_irq_type;
-       apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);   /* Fixed mode */
+       apic_write(APIC_LVT0, APIC_DM_FIXED | vector);  /* Fixed mode */
        enable_8259A_irq(0);
 
        if (timer_irq_works()) {
                apic_printk(APIC_QUIET, " works.\n");
                return;
        }
-       apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
        apic_printk(APIC_VERBOSE," failed.\n");
 
        apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
 
        init_8259A(0);
        make_8259A_irq(0);
-       apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+       apic_write(APIC_LVT0, APIC_DM_EXTINT);
 
        unlock_ExtINT_logic();
 
@@ -2027,7 +2063,7 @@ int __init io_apic_get_redir_entries (int ioapic)
 }
 
 
-int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low)
+int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
 {
        struct IO_APIC_route_entry entry;
        unsigned long flags;
@@ -2049,8 +2085,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
        entry.delivery_mode = INT_DELIVERY_MODE;
        entry.dest_mode = INT_DEST_MODE;
        entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
-       entry.trigger = edge_level;
-       entry.polarity = active_high_low;
+       entry.trigger = triggering;
+       entry.polarity = polarity;
        entry.mask = 1;                                  /* Disabled (masked) */
 
        irq = gsi_irq_sharing(irq);
@@ -2065,9 +2101,9 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
        apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
                "IRQ %d Mode:%i Active:%i)\n", ioapic, 
               mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
-              edge_level, active_high_low);
+              triggering, polarity);
 
-       ioapic_register_intr(irq, entry.vector, edge_level);
+       ioapic_register_intr(irq, entry.vector, triggering);
 
        if (!ioapic && (irq < 16))
                disable_8259A_irq(irq);