AMD IOMMU: add device detach function for IOMMU API
[safe/jmp/linux-2.6] / arch / x86 / kernel / acpi / boot.c
index 91bb9a9..65d0b72 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
+#include <asm/genapic.h>
 #include <asm/io.h>
 #include <asm/mpspec.h>
 #include <asm/smp.h>
@@ -57,7 +58,6 @@ EXPORT_SYMBOL(acpi_disabled);
 #ifdef CONFIG_X86_64
 
 #include <asm/proto.h>
-#include <asm/genapic.h>
 
 #else                          /* X86 */
 
@@ -106,21 +106,6 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
  */
 enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
 
-#ifdef CONFIG_X86_64
-
-/* rely on all ACPI tables being in the direct mapping */
-char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
-{
-       if (!phys_addr || !size)
-               return NULL;
-
-       if (phys_addr+size <= (max_pfn_mapped << PAGE_SHIFT) + PAGE_SIZE)
-               return __va(phys_addr);
-
-       return NULL;
-}
-
-#else
 
 /*
  * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
@@ -139,11 +124,15 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
        unsigned long base, offset, mapped_size;
        int idx;
 
-       if (phys + size < 8 * 1024 * 1024)
+       if (!phys || !size)
+               return NULL;
+
+       if (phys+size <= (max_low_pfn_mapped << PAGE_SHIFT))
                return __va(phys);
 
        offset = phys & (PAGE_SIZE - 1);
        mapped_size = PAGE_SIZE - offset;
+       clear_fixmap(FIX_ACPI_END);
        set_fixmap(FIX_ACPI_END, phys);
        base = fix_to_virt(FIX_ACPI_END);
 
@@ -155,19 +144,30 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
                if (--idx < FIX_ACPI_BEGIN)
                        return NULL;    /* cannot handle this */
                phys += PAGE_SIZE;
+               clear_fixmap(idx);
                set_fixmap(idx, phys);
                mapped_size += PAGE_SIZE;
        }
 
        return ((unsigned char *)base + offset);
 }
-#endif
 
 #ifdef CONFIG_PCI_MMCONFIG
+
+static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
+
 /* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
 struct acpi_mcfg_allocation *pci_mmcfg_config;
 int pci_mmcfg_config_num;
 
+static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
+{
+       if (!strcmp(mcfg->header.oem_id, "SGI"))
+               acpi_mcfg_64bit_base_addr = TRUE;
+
+       return 0;
+}
+
 int __init acpi_parse_mcfg(struct acpi_table_header *header)
 {
        struct acpi_table_mcfg *mcfg;
@@ -200,8 +200,12 @@ int __init acpi_parse_mcfg(struct acpi_table_header *header)
        }
 
        memcpy(pci_mmcfg_config, &mcfg[1], config_size);
+
+       acpi_mcfg_oem_check(mcfg);
+
        for (i = 0; i < pci_mmcfg_config_num; ++i) {
-               if (pci_mmcfg_config[i].address > 0xFFFFFFFF) {
+               if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
+                   !acpi_mcfg_64bit_base_addr) {
                        printk(KERN_ERR PREFIX
                               "MMCONFIG not in low 4GB of memory\n");
                        kfree(pci_mmcfg_config);
@@ -249,10 +253,8 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled)
                return;
        }
 
-#ifdef CONFIG_X86_32
        if (boot_cpu_physical_apicid != -1U)
                ver = apic_version[boot_cpu_physical_apicid];
-#endif
 
        generic_processor_info(id, ver);
 }
@@ -512,8 +514,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
         * Make sure all (legacy) PCI IRQs are set as level-triggered.
         */
        if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
-               extern void eisa_set_level_irq(unsigned int irq);
-
                if (triggering == ACPI_LEVEL_SENSITIVE)
                        eisa_set_level_irq(gsi);
        }
@@ -773,11 +773,9 @@ static void __init acpi_register_lapic_address(unsigned long address)
 
        set_fixmap_nocache(FIX_APIC_BASE, address);
        if (boot_cpu_physical_apicid == -1U) {
-               boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
-#ifdef CONFIG_X86_32
+               boot_cpu_physical_apicid  = read_apic_id();
                apic_version[boot_cpu_physical_apicid] =
                         GET_APIC_VERSION(apic_read(APIC_LVR));
-#endif
        }
 }
 
@@ -1033,7 +1031,7 @@ void __init mp_config_acpi_legacy_irqs(void)
        mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
 #endif
        set_bit(MP_ISA_BUS, mp_bus_not_pci);
-       Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+       pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
 
 #ifdef CONFIG_X86_ES7000
        /*
@@ -1139,8 +1137,8 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
                return gsi;
        }
        if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
-               Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-                       mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+               pr_debug("Pin %d-%d already programmed\n",
+                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 #ifdef CONFIG_X86_32
                return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
 #else
@@ -1259,7 +1257,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
 
        count =
            acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
-                                 NR_IRQ_VECTORS);
+                                 nr_irqs);
        if (count < 0) {
                printk(KERN_ERR PREFIX
                       "Error parsing interrupt source overrides entry\n");
@@ -1279,7 +1277,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
 
        count =
            acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
-                                 NR_IRQ_VECTORS);
+                                 nr_irqs);
        if (count < 0) {
                printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
                /* TBD: Cleanup to allow fallback to MPS */
@@ -1345,11 +1343,12 @@ static void __init acpi_process_madt(void)
                        error = acpi_parse_madt_ioapic_entries();
                        if (!error) {
                                acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
-                               acpi_irq_balance_set(NULL);
                                acpi_ioapic = 1;
 
                                smp_found_config = 1;
+#ifdef CONFIG_X86_32
                                setup_apic_routing();
+#endif
                        }
                }
                if (error == -EINVAL) {
@@ -1361,12 +1360,21 @@ static void __init acpi_process_madt(void)
                        disable_acpi();
                }
        }
+
+       /*
+        * ACPI supports both logical (e.g. Hyper-Threading) and physical
+        * processors, where MPS only supports physical.
+        */
+       if (acpi_lapic && acpi_ioapic)
+               printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
+                      "information\n");
+       else if (acpi_lapic)
+               printk(KERN_INFO "Using ACPI for processor (LAPIC) "
+                      "configuration information\n");
 #endif
        return;
 }
 
-#ifdef __i386__
-
 static int __init disable_acpi_irq(const struct dmi_system_id *d)
 {
        if (!acpi_force) {
@@ -1417,6 +1425,24 @@ static int __init force_acpi_ht(const struct dmi_system_id *d)
 }
 
 /*
+ * Force ignoring BIOS IRQ0 pin2 override
+ */
+static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
+{
+       /*
+        * The ati_ixp4x0_rev() early PCI quirk should have set
+        * the acpi_skip_timer_override flag already:
+        */
+       if (!acpi_skip_timer_override) {
+               WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n");
+               pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n",
+                       d->ident);
+               acpi_skip_timer_override = 1;
+       }
+       return 0;
+}
+
+/*
  * If your system is blacklisted here, but you find that acpi=force
  * works for you, please contact acpi-devel@sourceforge.net
  */
@@ -1586,7 +1612,52 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
        {}
 };
 
-#endif                         /* __i386__ */
+/* second table for DMI checks that should run after early-quirks */
+static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
+       /*
+        * HP laptops which use a DSDT reporting as HP/SB400/10000,
+        * which includes some code which overrides all temperature
+        * trip points to 16C if the INTIN2 input of the I/O APIC
+        * is enabled.  This input is incorrectly designated the
+        * ISA IRQ 0 via an interrupt source override even though
+        * it is wired to the output of the master 8259A and INTIN0
+        * is not connected at all.  Force ignoring BIOS IRQ0 pin2
+        * override in that cases.
+        */
+       {
+        .callback = dmi_ignore_irq0_timer_override,
+        .ident = "HP nx6115 laptop",
+        .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6115"),
+                    },
+        },
+       {
+        .callback = dmi_ignore_irq0_timer_override,
+        .ident = "HP NX6125 laptop",
+        .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6125"),
+                    },
+        },
+       {
+        .callback = dmi_ignore_irq0_timer_override,
+        .ident = "HP NX6325 laptop",
+        .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
+                    },
+        },
+       {
+        .callback = dmi_ignore_irq0_timer_override,
+        .ident = "HP 6715b laptop",
+        .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
+                    },
+        },
+       {}
+};
 
 /*
  * acpi_boot_table_init() and acpi_boot_init()
@@ -1615,9 +1686,7 @@ int __init acpi_boot_table_init(void)
 {
        int error;
 
-#ifdef __i386__
        dmi_check_system(acpi_dmi_table);
-#endif
 
        /*
         * If acpi_disabled, bail out
@@ -1673,6 +1742,9 @@ int __init early_acpi_boot_init(void)
 
 int __init acpi_boot_init(void)
 {
+       /* those are executed after early-quirks are executed */
+       dmi_check_system(acpi_dmi_table_late);
+
        /*
         * If acpi_disabled, bail out
         * One exception: acpi=ht continues far enough to enumerate LAPICs
@@ -1742,6 +1814,20 @@ static int __init parse_pci(char *arg)
 }
 early_param("pci", parse_pci);
 
+int __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+       if (acpi_disabled || acpi_noirq) {
+               printk(KERN_WARNING "MPS support code is not built-in.\n"
+                      "Using acpi=off or acpi=noirq or pci=noacpi "
+                      "may have problem\n");
+               return 1;
+       }
+#endif
+       return 0;
+}
+
 #ifdef CONFIG_X86_IO_APIC
 static int __init parse_acpi_skip_timer_override(char *arg)
 {