Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / kernel / acpi / boot.c
index a54d714..79c14db 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/dmi.h>
 #include <linux/irq.h>
+#include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -62,7 +63,6 @@ EXPORT_SYMBOL(acpi_disabled);
 int acpi_noirq;                                /* skip ACPI IRQ initialization */
 int acpi_pci_disabled;         /* skip ACPI PCI scan and IRQ initialization */
 EXPORT_SYMBOL(acpi_pci_disabled);
-int acpi_ht __initdata = 1;    /* enable HT */
 
 int acpi_lapic;
 int acpi_ioapic;
@@ -70,12 +70,18 @@ int acpi_strict;
 
 u8 acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
+#ifndef CONFIG_XEN
 int acpi_skip_timer_override __initdata;
 int acpi_use_timer_override __initdata;
+int acpi_fix_pin2_polarity __initdata;
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
+#else
+#define acpi_skip_timer_override 0
+#define acpi_fix_pin2_polarity 0
+#endif
 
 #ifndef __HAVE_ARCH_CMPXCHG
 #warning ACPI uses CMPXCHG, i486 and later hardware
@@ -93,6 +99,53 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
 
 
 /*
+ * ISA irqs by default are the first 16 gsis but can be
+ * any gsi as specified by an interrupt source override.
+ */
+static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static unsigned int gsi_to_irq(unsigned int gsi)
+{
+       unsigned int irq = gsi + NR_IRQS_LEGACY;
+       unsigned int i;
+
+       for (i = 0; i < NR_IRQS_LEGACY; i++) {
+               if (isa_irq_to_gsi[i] == gsi) {
+                       return i;
+               }
+       }
+
+       /* Provide an identity mapping of gsi == irq
+        * except on truly weird platforms that have
+        * non isa irqs in the first 16 gsis.
+        */
+       if (gsi >= NR_IRQS_LEGACY)
+               irq = gsi;
+       else
+               irq = gsi_top + gsi;
+
+       return irq;
+}
+
+static u32 irq_to_gsi(int irq)
+{
+       unsigned int gsi;
+
+       if (irq < NR_IRQS_LEGACY)
+               gsi = isa_irq_to_gsi[irq];
+       else if (irq < gsi_top)
+               gsi = irq;
+       else if (irq < (gsi_top + NR_IRQS_LEGACY))
+               gsi = irq - gsi_top;
+       else
+               gsi = 0xffffffff;
+
+       return gsi;
+}
+
+/*
  * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
  * to map the target physical address. The problem is that set_fixmap()
  * provides a single page, and it is possible that the page is not
@@ -134,6 +187,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
                return -ENODEV;
        }
 
+#ifndef CONFIG_XEN
        if (madt->address) {
                acpi_lapic_addr = (u64) madt->address;
 
@@ -143,14 +197,21 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
 
        default_acpi_madt_oem_check(madt->header.oem_id,
                                    madt->header.oem_table_id);
+#endif
 
        return 0;
 }
 
 static void __cpuinit acpi_register_lapic(int id, u8 enabled)
 {
+#ifndef CONFIG_XEN
        unsigned int ver = 0;
 
+       if (id >= (MAX_LOCAL_APIC-1)) {
+               printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
+               return;
+       }
+
        if (!enabled) {
                ++disabled_cpus;
                return;
@@ -160,12 +221,15 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled)
                ver = apic_version[boot_cpu_physical_apicid];
 
        generic_processor_info(id, ver);
+#endif
 }
 
 static int __init
 acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
 {
        struct acpi_madt_local_x2apic *processor = NULL;
+       int apic_id;
+       u8 enabled;
 
        processor = (struct acpi_madt_local_x2apic *)header;
 
@@ -174,6 +238,8 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
 
        acpi_table_print_madt_entry(header);
 
+       apic_id = processor->local_apic_id;
+       enabled = processor->lapic_flags & ACPI_MADT_ENABLED;
 #ifdef CONFIG_X86_X2APIC
        /*
         * We need to register disabled CPU as well to permit
@@ -182,9 +248,11 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
         * to not preallocating memory for all NR_CPUS
         * when we use CPU hotplug.
         */
-       acpi_register_lapic(processor->local_apic_id,   /* APIC ID */
-                           processor->lapic_flags & ACPI_MADT_ENABLED);
-#else
+       if (!apic->apic_id_valid(apic_id) && enabled)
+               printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
+       else
+               acpi_register_lapic(apic_id, enabled);
+#elif !defined(CONFIG_XEN)
        printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
 #endif
 
@@ -238,6 +306,7 @@ static int __init
 acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
                          const unsigned long end)
 {
+#ifndef CONFIG_XEN
        struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
 
        lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
@@ -246,6 +315,7 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
                return -EINVAL;
 
        acpi_lapic_addr = lapic_addr_ovr->address;
+#endif
 
        return 0;
 }
@@ -312,7 +382,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 /*
  * Parse Interrupt Source Override for the ACPI SCI
  */
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi)
 {
        if (trigger == 0)       /* compatible SCI trigger is level */
                trigger = 3;
@@ -332,7 +402,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
         * If GSI is < 16, this will update its flags,
         * else it will create a new mp_irqs[] entry.
         */
-       mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+       mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
 
        /*
         * stash over-ride to indicate we've been here
@@ -356,16 +426,22 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
        acpi_table_print_madt_entry(header);
 
        if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
-               acpi_sci_ioapic_setup(intsrc->global_irq,
+               acpi_sci_ioapic_setup(intsrc->source_irq,
                                      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
-                                     (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
+                                     (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
+                                     intsrc->global_irq);
                return 0;
        }
 
-       if (acpi_skip_timer_override &&
-           intsrc->source_irq == 0 && intsrc->global_irq == 2) {
-               printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
-               return 0;
+       if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
+               if (acpi_skip_timer_override) {
+                       printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+                       return 0;
+               }
+               if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
+                       intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
+                       printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
+               }
        }
 
        mp_override_legacy_irq(intsrc->source_irq,
@@ -447,7 +523,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
-       *irq = gsi;
+       *irq = gsi_to_irq(gsi);
 
 #ifdef CONFIG_X86_IO_APIC
        if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
@@ -456,42 +532,80 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
-/*
- * success: return IRQ number (>=0)
- * failure: return < 0
- */
-int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
 {
-       unsigned int irq;
-       unsigned int plat_gsi = gsi;
+       if (isa_irq >= 16)
+               return -1;
+       *gsi = irq_to_gsi(isa_irq);
+       return 0;
+}
 
+static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
+                                int trigger, int polarity)
+{
 #ifdef CONFIG_PCI
        /*
         * Make sure all (legacy) PCI IRQs are set as level-triggered.
         */
-       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
-               if (trigger == ACPI_LEVEL_SENSITIVE)
-                       eisa_set_level_irq(gsi);
-       }
+       if (trigger == ACPI_LEVEL_SENSITIVE)
+               eisa_set_level_irq(gsi);
 #endif
 
+       return gsi;
+}
+
+static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
+                                   int trigger, int polarity)
+{
 #ifdef CONFIG_X86_IO_APIC
-       if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
-               plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
-       }
+       gsi = mp_register_gsi(dev, gsi, trigger, polarity);
 #endif
-       irq = plat_gsi;
+
+       return gsi;
+}
+
+int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
+                          int trigger, int polarity) = acpi_register_gsi_pic;
+
+/*
+ * success: return IRQ number (>=0)
+ * failure: return < 0
+ */
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+{
+       unsigned int irq;
+       unsigned int plat_gsi = gsi;
+
+       plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
+       irq = gsi_to_irq(plat_gsi);
 
        return irq;
 }
 
+void __init acpi_set_irq_model_pic(void)
+{
+       acpi_irq_model = ACPI_IRQ_MODEL_PIC;
+       __acpi_register_gsi = acpi_register_gsi_pic;
+       acpi_ioapic = 0;
+}
+
+void __init acpi_set_irq_model_ioapic(void)
+{
+       acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
+       __acpi_register_gsi = acpi_register_gsi_ioapic;
+       acpi_ioapic = 1;
+}
+
 /*
  *  ACPI based hotplug support for CPU
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
+#include <acpi/processor.h>
 
-static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
+#ifndef CONFIG_XEN
+static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
        int nid;
@@ -499,14 +613,8 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
        nid = acpi_get_node(handle);
        if (nid == -1 || !node_online(nid))
                return;
-#ifdef CONFIG_X86_64
-       apicid_to_node[physid] = nid;
+       set_apicid_to_node(physid, nid);
        numa_set_node(cpu, nid);
-#else /* CONFIG_X86_32 */
-       apicid_2_node[physid] = nid;
-       cpu_to_node_map[cpu] = nid;
-#endif
-
 #endif
 }
 
@@ -546,6 +654,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
        kfree(buffer.pointer);
        buffer.length = ACPI_ALLOCATE_BUFFER;
        buffer.pointer = NULL;
+       lapic = NULL;
 
        if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
                goto out;
@@ -554,7 +663,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
                goto free_tmp_map;
 
        cpumask_copy(tmp_map, cpu_present_mask);
-       acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
+       acpi_register_lapic(physid, ACPI_MADT_ENABLED);
 
        /*
         * If mp_register_lapic successfully generates a new logical cpu
@@ -567,6 +676,8 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
                goto free_new_map;
        }
 
+       acpi_processor_set_pdc(handle);
+
        cpu = cpumask_first(new_map);
        acpi_map_cpu2node(handle, cpu, physid);
 
@@ -580,6 +691,9 @@ free_tmp_map:
 out:
        return retval;
 }
+#else
+#define _acpi_map_lsapic(h, p) (-EINVAL)
+#endif
 
 /* wrapper to silence section mismatch warning */
 int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
@@ -590,9 +704,11 @@ EXPORT_SYMBOL(acpi_map_lsapic);
 
 int acpi_unmap_lsapic(int cpu)
 {
+#ifndef CONFIG_XEN
        per_cpu(x86_cpu_to_apicid, cpu) = -1;
        set_cpu_present(cpu, false);
        num_processors--;
+#endif
 
        return (0);
 }
@@ -761,18 +877,6 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
  * returns 0 on success, < 0 on error
  */
 
-static void __init acpi_register_lapic_address(unsigned long address)
-{
-       mp_lapic_addr = address;
-
-       set_fixmap_nocache(FIX_APIC_BASE, address);
-       if (boot_cpu_physical_apicid == -1U) {
-               boot_cpu_physical_apicid  = read_apic_id();
-               apic_version[boot_cpu_physical_apicid] =
-                        GET_APIC_VERSION(apic_read(APIC_LVR));
-       }
-}
-
 static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
 {
        int count;
@@ -794,7 +898,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
                return count;
        }
 
-       acpi_register_lapic_address(acpi_lapic_addr);
+       register_lapic_address(acpi_lapic_addr);
 
        return count;
 }
@@ -821,16 +925,16 @@ static int __init acpi_parse_madt_lapic_entries(void)
                return count;
        }
 
-       acpi_register_lapic_address(acpi_lapic_addr);
+       register_lapic_address(acpi_lapic_addr);
 
        count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
-                                     acpi_parse_sapic, MAX_APICS);
+                                     acpi_parse_sapic, MAX_LOCAL_APIC);
 
        if (!count) {
                x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
-                                               acpi_parse_x2apic, MAX_APICS);
+                                       acpi_parse_x2apic, MAX_LOCAL_APIC);
                count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
-                                             acpi_parse_lapic, MAX_APICS);
+                                       acpi_parse_lapic, MAX_LOCAL_APIC);
        }
        if (!count && !x2count) {
                printk(KERN_ERR PREFIX "No LAPIC entries present\n");
@@ -863,55 +967,6 @@ static int __init acpi_parse_madt_lapic_entries(void)
 extern int es7000_plat;
 #endif
 
-int __init acpi_probe_gsi(void)
-{
-       int idx;
-       int gsi;
-       int max_gsi = 0;
-
-       if (acpi_disabled)
-               return 0;
-
-       if (!acpi_ioapic)
-               return 0;
-
-       max_gsi = 0;
-       for (idx = 0; idx < nr_ioapics; idx++) {
-               gsi = mp_gsi_routing[idx].gsi_end;
-
-               if (gsi > max_gsi)
-                       max_gsi = gsi;
-       }
-
-       return max_gsi + 1;
-}
-
-static void assign_to_mp_irq(struct mpc_intsrc *m,
-                                   struct mpc_intsrc *mp_irq)
-{
-       memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
-                               struct mpc_intsrc *m)
-{
-       return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
-}
-
-static void save_mp_irq(struct mpc_intsrc *m)
-{
-       int i;
-
-       for (i = 0; i < mp_irq_entries; i++) {
-               if (!mp_irq_cmp(&mp_irqs[i], m))
-                       return;
-       }
-
-       assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
-       if (++mp_irq_entries == MAX_IRQ_SOURCES)
-               panic("Max # of irq sources exceeded!!\n");
-}
-
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
        int ioapic;
@@ -939,17 +994,17 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
        mp_irq.irqflag = (trigger << 2) | polarity;
        mp_irq.srcbus = MP_ISA_BUS;
        mp_irq.srcbusirq = bus_irq;     /* IRQ */
-       mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
+       mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
        mp_irq.dstirq = pin;    /* INTIN# */
 
-       save_mp_irq(&mp_irq);
+       mp_save_irq(&mp_irq);
+
+       isa_irq_to_gsi[bus_irq] = gsi;
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
 {
        int i;
-       int ioapic;
-       unsigned int dstapic;
        struct mpc_intsrc mp_irq;
 
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
@@ -970,19 +1025,27 @@ void __init mp_config_acpi_legacy_irqs(void)
 #endif
 
        /*
-        * Locate the IOAPIC that manages the ISA IRQs (0-15).
-        */
-       ioapic = mp_find_ioapic(0);
-       if (ioapic < 0)
-               return;
-       dstapic = mp_ioapics[ioapic].apicid;
-
-       /*
         * Use the default configuration for the IRQs 0-15.  Unless
         * overridden by (MADT) interrupt source override entries.
         */
        for (i = 0; i < 16; i++) {
+               int ioapic, pin;
+               unsigned int dstapic;
                int idx;
+               u32 gsi;
+
+               /* Locate the gsi that irq i maps to. */
+               if (acpi_isa_irq_to_gsi(i, &gsi))
+                       continue;
+
+               /*
+                * Locate the IOAPIC that manages the ISA IRQ.
+                */
+               ioapic = mp_find_ioapic(gsi);
+               if (ioapic < 0)
+                       continue;
+               pin = mp_find_ioapic_pin(ioapic, gsi);
+               dstapic = mpc_ioapic_id(ioapic);
 
                for (idx = 0; idx < mp_irq_entries; idx++) {
                        struct mpc_intsrc *irq = mp_irqs + idx;
@@ -992,7 +1055,7 @@ void __init mp_config_acpi_legacy_irqs(void)
                                break;
 
                        /* Do we already have a mapping for this IOAPIC pin */
-                       if (irq->dstapic == dstapic && irq->dstirq == i)
+                       if (irq->dstapic == dstapic && irq->dstirq == pin)
                                break;
                }
 
@@ -1007,9 +1070,9 @@ void __init mp_config_acpi_legacy_irqs(void)
                mp_irq.dstapic = dstapic;
                mp_irq.irqtype = mp_INT;
                mp_irq.srcbusirq = i; /* Identity mapped */
-               mp_irq.dstirq = i;
+               mp_irq.dstirq = pin;
 
-               save_mp_irq(&mp_irq);
+               mp_save_irq(&mp_irq);
        }
 }
 
@@ -1043,10 +1106,10 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
        mp_irq.srcbus = number;
        mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
        ioapic = mp_find_ioapic(gsi);
-       mp_irq.dstapic = mp_ioapics[ioapic].apicid;
+       mp_irq.dstapic = mpc_ioapic_id(ioapic);
        mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
 
-       save_mp_irq(&mp_irq);
+       mp_save_irq(&mp_irq);
 #endif
        return 0;
 }
@@ -1072,14 +1135,9 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 
        ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
 
-#ifdef CONFIG_X86_32
-       if (ioapic_renumber_irq)
-               gsi = ioapic_renumber_irq(ioapic, gsi);
-#endif
-
        if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
                printk(KERN_ERR "Invalid reference to IOAPIC pin "
-                      "%d-%d\n", mp_ioapics[ioapic].apicid,
+                      "%d-%d\n", mpc_ioapic_id(ioapic),
                       ioapic_pin);
                return gsi;
        }
@@ -1090,7 +1148,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
        set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
                             trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
                             polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-       io_apic_set_pci_routing(dev, gsi, &irq_attr);
+       io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
 
        return gsi;
 }
@@ -1150,7 +1208,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
         * pretend we got one so we can set the SCI flags.
         */
        if (!acpi_sci_override_gsi)
-               acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+               acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0,
+                                     acpi_gbl_FADT.sci_interrupt);
 
        /* Fill in identity legacy mappings where no override */
        mp_config_acpi_legacy_irqs();
@@ -1219,8 +1278,7 @@ static void __init acpi_process_madt(void)
                         */
                        error = acpi_parse_madt_ioapic_entries();
                        if (!error) {
-                               acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
-                               acpi_ioapic = 1;
+                               acpi_set_irq_model_ioapic();
 
                                smp_found_config = 1;
                        }
@@ -1292,23 +1350,7 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
        return 0;
 }
 
-/*
- * Limit ACPI to CPU enumeration for HT
- */
-static int __init force_acpi_ht(const struct dmi_system_id *d)
-{
-       if (!acpi_force) {
-               printk(KERN_NOTICE "%s detected: force use of acpi=ht\n",
-                      d->ident);
-               disable_acpi();
-               acpi_ht = 1;
-       } else {
-               printk(KERN_NOTICE
-                      "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
-       }
-       return 0;
-}
-
+#ifndef CONFIG_XEN
 /*
  * Force ignoring BIOS IRQ0 pin2 override
  */
@@ -1326,6 +1368,22 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
        }
        return 0;
 }
+#endif
+
+static int __init force_acpi_rsdt(const struct dmi_system_id *d)
+{
+       if (!acpi_force) {
+               printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
+                      d->ident);
+               acpi_rsdt_forced = 1;
+       } else {
+               printk(KERN_NOTICE
+                      "Warning: acpi=force overrules DMI blacklist: "
+                      "acpi=rsdt\n");
+       }
+       return 0;
+
+}
 
 /*
  * If your system is blacklisted here, but you find that acpi=force
@@ -1345,82 +1403,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
         },
 
        /*
-        * Boxes that need acpi=ht
-        */
-       {
-        .callback = force_acpi_ht,
-        .ident = "FSC Primergy T850",
-        .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "HP VISUALIZE NT Workstation",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "Compaq Workstation W8000",
-        .matches = {
-                    DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "ASUS CUR-DLS",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-                    DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "ABIT i440BX-W83977",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
-                    DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM Bladecenter",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eServer xSeries 360",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eserver xSeries 330",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
-                    },
-        },
-       {
-        .callback = force_acpi_ht,
-        .ident = "IBM eserver xSeries 440",
-        .matches = {
-                    DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
-                    DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
-                    },
-        },
-
-       /*
         * Boxes that need ACPI PCI IRQ routing disabled
         */
        {
@@ -1478,9 +1460,36 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
                     },
         },
+
+       /*
+        * Boxes that need RSDT as ACPI root table
+        */
+       {
+           .callback = force_acpi_rsdt,
+           .ident = "ThinkPad ", /* R40e, broken C-states */
+           .matches = {
+               DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+               DMI_MATCH(DMI_BIOS_VERSION, "1SET")},
+       },
+       {
+           .callback = force_acpi_rsdt,
+           .ident = "ThinkPad ", /* R50e, slow booting */
+           .matches = {
+               DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+               DMI_MATCH(DMI_BIOS_VERSION, "1WET")},
+       },
+       {
+           .callback = force_acpi_rsdt,
+           .ident = "ThinkPad ", /* T40, T40p, T41, T41p, T42, T42p
+                                    R50, R50p */
+           .matches = {
+               DMI_MATCH(DMI_BIOS_VENDOR, "IBM"),
+               DMI_MATCH(DMI_BIOS_VERSION, "1RET")},
+       },
        {}
 };
 
+#ifndef CONFIG_XEN
 /* second table for DMI checks that should run after early-quirks */
 static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
        /*
@@ -1527,6 +1536,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
         },
        {}
 };
+#endif
 
 /*
  * acpi_boot_table_init() and acpi_boot_init()
@@ -1553,9 +1563,8 @@ void __init acpi_boot_table_init(void)
 
        /*
         * If acpi_disabled, bail out
-        * One exception: acpi=ht continues far enough to enumerate LAPICs
         */
-       if (acpi_disabled && !acpi_ht)
+       if (acpi_disabled)
                return; 
 
        /*
@@ -1586,9 +1595,8 @@ int __init early_acpi_boot_init(void)
 {
        /*
         * If acpi_disabled, bail out
-        * One exception: acpi=ht continues far enough to enumerate LAPICs
         */
-       if (acpi_disabled && !acpi_ht)
+       if (acpi_disabled)
                return 1;
 
        /*
@@ -1601,14 +1609,15 @@ int __init early_acpi_boot_init(void)
 
 int __init acpi_boot_init(void)
 {
+#ifndef CONFIG_XEN
        /* those are executed after early-quirks are executed */
        dmi_check_system(acpi_dmi_table_late);
+#endif
 
        /*
         * If acpi_disabled, bail out
-        * One exception: acpi=ht continues far enough to enumerate LAPICs
         */
-       if (acpi_disabled && !acpi_ht)
+       if (acpi_disabled)
                return 1;
 
        acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
@@ -1643,19 +1652,12 @@ static int __init parse_acpi(char *arg)
        /* acpi=force to over-ride black-list */
        else if (strcmp(arg, "force") == 0) {
                acpi_force = 1;
-               acpi_ht = 1;
                acpi_disabled = 0;
        }
        /* acpi=strict disables out-of-spec workarounds */
        else if (strcmp(arg, "strict") == 0) {
                acpi_strict = 1;
        }
-       /* Limit ACPI just to boot-time to enable HT */
-       else if (strcmp(arg, "ht") == 0) {
-               if (!acpi_force)
-                       disable_acpi();
-               acpi_ht = 1;
-       }
        /* acpi=rsdt use RSDT instead of XSDT */
        else if (strcmp(arg, "rsdt") == 0) {
                acpi_rsdt_forced = 1;
@@ -1663,6 +1665,10 @@ static int __init parse_acpi(char *arg)
        /* "acpi=noirq" disables ACPI interrupt routing */
        else if (strcmp(arg, "noirq") == 0) {
                acpi_noirq_set();
+       }
+       /* "acpi=copy_dsdt" copys DSDT */
+       else if (strcmp(arg, "copy_dsdt") == 0) {
+               acpi_gbl_copy_dsdt_locally = 1;
        } else {
                /* Core will printk when we return error. */
                return -EINVAL;
@@ -1671,6 +1677,18 @@ static int __init parse_acpi(char *arg)
 }
 early_param("acpi", parse_acpi);
 
+/* Alias for acpi=rsdt for compatibility with openSUSE 11.1 and SLE11 */
+static int __init parse_acpi_root_table(char *opt)
+{
+       if (!strcmp(opt, "rsdt")) {
+               acpi_rsdt_forced = 1;
+               printk(KERN_WARNING "acpi_root_table=rsdt is deprecated. "
+                      "Please use acpi=rsdt instead.\n");
+       }
+       return 0;
+}
+early_param("acpi_root_table", parse_acpi_root_table);
+
 /* FIXME: Using pci= for an ACPI parameter is a travesty. */
 static int __init parse_pci(char *arg)
 {
@@ -1694,7 +1712,7 @@ int __init acpi_mps_check(void)
        return 0;
 }
 
-#ifdef CONFIG_X86_IO_APIC
+#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_XEN)
 static int __init parse_acpi_skip_timer_override(char *arg)
 {
        acpi_skip_timer_override = 1;