Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Aug 2014 00:23:32 +0000 (18:23 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Aug 2014 00:23:32 +0000 (18:23 -0600)
Pull x86/apic updates from Thomas Gleixner:
 "This is a major overhaul to the x86 apic subsystem consisting of the
  following parts:

   - Remove obsolete APIC driver abstractions (David Rientjes)

   - Use the irqdomain facilities to dynamically allocate IRQs for
     IOAPICs.  This is a prerequisite to enable IOAPIC hotplug support,
     and it also frees up wasted vectors (Jiang Liu)

   - Misc fixlets.

  Despite the hickup in Ingos previous pull request - caused by the
  missing fixup for the suspend/resume issue reported by Borislav - I
  strongly recommend that this update finds its way into 3.17.  Some
  history for you:

  This is preparatory work for physical IOAPIC hotplug.  The first
  attempt to support this was done by Yinghai and I shot it down because
  it just added another layer of obscurity and complexity to the already
  existing mess without tackling the underlying shortcomings of the
  current implementation.

  After quite some on- and offlist discussions, I requested that the
  design of this functionality must use generic infrastructure, i.e.
  irq domains, which provide all the mechanisms to dynamically map linux
  interrupt numbers to physical interrupts.

  Jiang picked up the idea and did a great job of consolidating the
  existing interfaces to manage the x86 (IOAPIC) interrupt system by
  utilizing irq domains.

  The testing in tip, Linux-next and inside of Intel on various machines
  did not unearth any oddities until Borislav exposed it to one of his
  oddball machines.  The issue was resolved quickly, but unfortunately
  the fix fell through the cracks and did not hit the tip tree before
  Ingo sent the pull request.  Not entirely Ingos fault, I also assumed
  that the fix was already merged when Ingo asked me whether he could
  send it.

  Nevertheless this work has a proper design, has undergone several
  rounds of review and the final fallout after applying it to tip and
  integrating it into Linux-next has been more than moderate.  It's the
  ground work not only for IOAPIC hotplug, it will also allow us to move
  the lowlevel vector allocation into the irqdomain hierarchy, which
  will benefit other architectures as well.  Patches are posted already,
  but they are on hold for two weeks, see below.

  I really appreciate the competence and responsiveness Jiang has shown
  in course of this endavour.  So I'm sure that any fallout of this will
  be addressed in a timely manner.

  FYI, I'm vanishing for 2 weeks into my annual kids summer camp kitchen
  duty^Wvacation, while you folks are drooling at KS/LinuxCon :) But HPA
  will have a look at the hopefully zero fallout until I'm back"

* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (53 commits)
  x86, irq, PCI: Keep IRQ assignment for PCI devices during suspend/hibernation
  x86/apic/vsmp: Make is_vsmp_box() static
  x86, apic: Remove enable_apic_mode callback
  x86, apic: Remove setup_portio_remap callback
  x86, apic: Remove multi_timer_check callback
  x86, apic: Replace noop_check_apicid_used
  x86, apic: Remove check_apicid_present callback
  x86, apic: Remove mps_oem_check callback
  x86, apic: Remove smp_callin_clear_local_apic callback
  x86, apic: Replace trampoline physical addresses with defaults
  x86, apic: Remove x86_32_numa_cpu_node callback
  x86: intel-mid: Use the new io_apic interfaces
  x86, vsmp: Remove is_vsmp_box() from apic_is_clustered_box()
  x86, irq: Clean up irqdomain transition code
  x86, irq, devicetree: Release IOAPIC pin when PCI device is disabled
  x86, irq, SFI: Release IOAPIC pin when PCI device is disabled
  x86, irq, mpparse: Release IOAPIC pin when PCI device is disabled
  x86, irq, ACPI: Release IOAPIC pin when PCI device is disabled
  x86, irq: Introduce helper functions to release IOAPIC pin
  x86, irq: Simplify the way to handle ISA IRQ
  ...

1  2 
arch/x86/Kconfig
arch/x86/include/asm/apic.h
arch/x86/kernel/acpi/boot.c

diff --combined arch/x86/Kconfig
@@@ -21,7 -21,6 +21,7 @@@ config X86_6
  ### Arch settings
  config X86
        def_bool y
 +      select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
        select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
@@@ -55,6 -54,7 +55,6 @@@
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_GRAPH_FP_TEST
 -      select HAVE_FUNCTION_TRACE_MCOUNT_TEST
        select HAVE_SYSCALL_TRACEPOINTS
        select SYSCTL_EXCEPTION_TRACE
        select HAVE_KVM
@@@ -96,7 -96,6 +96,7 @@@
        select IRQ_FORCED_THREADING
        select HAVE_BPF_JIT if X86_64
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 +      select ARCH_HAS_SG_CHAIN
        select CLKEVT_I8253
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_IOMAP
        select CLOCKSOURCE_WATCHDOG
        select GENERIC_CLOCKEVENTS
        select ARCH_CLOCKSOURCE_DATA
 +      select CLOCKSOURCE_VALIDATE_LAST_CYCLE
        select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
        select GENERIC_TIME_VSYSCALL
 -      select KTIME_SCALAR if X86_32
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
        select HAVE_CC_STACKPROTECTOR
        select GENERIC_CPU_AUTOPROBE
        select HAVE_ARCH_AUDITSYSCALL
 +      select ARCH_SUPPORTS_ATOMIC_RMW
 +      select HAVE_ACPI_APEI if ACPI
 +      select HAVE_ACPI_APEI_NMI if ACPI
 +      select ACPI_LEGACY_TABLES_LOOKUP if ACPI
  
  config INSTRUCTION_DECODER
        def_bool y
@@@ -434,6 -429,7 +434,7 @@@ config X86_INTEL_C
        bool "CE4100 TV platform"
        depends on PCI
        depends on PCI_GODIRECT
+       depends on X86_IO_APIC
        depends on X86_32
        depends on X86_EXTENDED_PLATFORM
        select X86_REBOOTFIXUPS
@@@ -840,6 -836,7 +841,7 @@@ config X86_IO_API
        def_bool y
        depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
        select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
+       select IRQ_DOMAIN
  
  config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
        bool "Reroute for broken boot IRQs"
@@@ -1527,7 -1524,6 +1529,7 @@@ config EF
        bool "EFI runtime service support"
        depends on ACPI
        select UCS2_STRING
 +      select EFI_RUNTIME_WRAPPERS
        ---help---
          This enables the kernel to use EFI runtime services that are
          available (such as the EFI variable services).
  
  config EFI_STUB
         bool "EFI stub support"
 -       depends on EFI
 +       depends on EFI && !X86_USE_3DNOW
 +       select RELOCATABLE
         ---help---
            This kernel feature allows a bzImage to be loaded directly
          by EFI firmware without the use of a bootloader.
@@@ -1583,9 -1578,6 +1585,9 @@@ source kernel/Kconfig.h
  
  config KEXEC
        bool "kexec system call"
 +      select BUILD_BIN2C
 +      select CRYPTO
 +      select CRYPTO_SHA256
        ---help---
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
          interface is strongly in flux, so no good recommendation can be
          made.
  
 +config KEXEC_VERIFY_SIG
 +      bool "Verify kernel signature during kexec_file_load() syscall"
 +      depends on KEXEC
 +      ---help---
 +        This option makes kernel signature verification mandatory for
 +        kexec_file_load() syscall. If kernel is signature can not be
 +        verified, kexec_file_load() will fail.
 +
 +        This option enforces signature verification at generic level.
 +        One needs to enable signature verification for type of kernel
 +        image being loaded to make sure it works. For example, enable
 +        bzImage signature verification option to be able to load and
 +        verify signatures of bzImage. Otherwise kernel loading will fail.
 +
 +config KEXEC_BZIMAGE_VERIFY_SIG
 +      bool "Enable bzImage signature verification support"
 +      depends on KEXEC_VERIFY_SIG
 +      depends on SIGNED_PE_FILE_VERIFICATION
 +      select SYSTEM_TRUSTED_KEYRING
 +      ---help---
 +        Enable bzImage signature verification support.
 +
  config CRASH_DUMP
        bool "kernel crash dumps"
        depends on X86_64 || (X86_32 && HIGHMEM)
@@@ -2435,10 -2405,6 +2437,10 @@@ config IOSF_MB
        default m
        depends on PCI
  
 +config PMC_ATOM
 +      def_bool y
 +        depends on PCI
 +
  source "net/Kconfig"
  
  source "drivers/Kconfig"
@@@ -85,21 -85,13 +85,13 @@@ static inline bool apic_from_smp_config
  #include <asm/paravirt.h>
  #endif
  
- #ifdef CONFIG_X86_64
- extern int is_vsmp_box(void);
- #else
- static inline int is_vsmp_box(void)
- {
-       return 0;
- }
- #endif
  extern int setup_profiling_timer(unsigned int);
  
  static inline void native_apic_mem_write(u32 reg, u32 v)
  {
        volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
  
 -      alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
 +      alternative_io("movl %0, %1", "xchgl %0, %1", X86_BUG_11AP,
                       ASM_OUTPUT2("=r" (v), "=m" (*addr)),
                       ASM_OUTPUT2("0" (v), "m" (*addr)));
  }
@@@ -300,7 -292,6 +292,6 @@@ struct apic 
  
        int dest_logical;
        unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
-       unsigned long (*check_apicid_present)(int apicid);
  
        void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
                                         const struct cpumask *mask);
        void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
  
        void (*setup_apic_routing)(void);
-       int (*multi_timer_check)(int apic, int irq);
        int (*cpu_present_to_apicid)(int mps_cpu);
        void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
-       void (*setup_portio_remap)(void);
        int (*check_phys_apicid_present)(int phys_apicid);
-       void (*enable_apic_mode)(void);
        int (*phys_pkg_id)(int cpuid_apic, int index_msb);
  
-       /*
-        * When one of the next two hooks returns 1 the apic
-        * is switched to this. Essentially they are additional
-        * probe functions:
-        */
-       int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
        unsigned int (*get_apic_id)(unsigned long x);
        unsigned long (*set_apic_id)(unsigned int id);
        unsigned long apic_id_mask;
        /* wakeup_secondary_cpu */
        int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
  
-       int trampoline_phys_low;
-       int trampoline_phys_high;
        bool wait_for_init_deassert;
-       void (*smp_callin_clear_local_apic)(void);
        void (*inquire_remote_apic)(int apicid);
  
        /* apic ops */
         * won't be applied properly during early boot in this case.
         */
        int (*x86_32_early_logical_apicid)(int cpu);
-       /*
-        * Optional method called from setup_local_APIC() after logical
-        * apicid is guaranteed to be known to initialize apicid -> node
-        * mapping if NUMA initialization hasn't done so already.  Don't
-        * add new users.
-        */
-       int (*x86_32_numa_cpu_node)(int cpu);
  #endif
  };
  
@@@ -496,14 -465,12 +465,12 @@@ static inline unsigned default_get_apic
  }
  
  /*
-  * Warm reset vector default position:
+  * Warm reset vector position:
   */
- #define DEFAULT_TRAMPOLINE_PHYS_LOW           0x467
- #define DEFAULT_TRAMPOLINE_PHYS_HIGH          0x469
+ #define TRAMPOLINE_PHYS_LOW           0x467
+ #define TRAMPOLINE_PHYS_HIGH          0x469
  
  #ifdef CONFIG_X86_64
- extern int default_acpi_madt_oem_check(char *, char *);
  extern void apic_send_IPI_self(int vector);
  
  DECLARE_PER_CPU(int, x2apic_extra_bits);
@@@ -552,6 -519,8 +519,8 @@@ static inline int default_apic_id_valid
        return (apicid < 255);
  }
  
+ extern int default_acpi_madt_oem_check(char *, char *);
  extern void default_setup_apic_routing(void);
  
  extern struct apic apic_noop;
@@@ -635,11 -604,6 +604,6 @@@ static inline unsigned long default_che
        return physid_isset(apicid, *map);
  }
  
- static inline unsigned long default_check_apicid_present(int bit)
- {
-       return physid_isset(bit, phys_cpu_present_map);
- }
  static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
  {
        *retmap = *phys_map;
@@@ -31,6 -31,7 +31,7 @@@
  #include <linux/module.h>
  #include <linux/dmi.h>
  #include <linux/irq.h>
+ #include <linux/irqdomain.h>
  #include <linux/slab.h>
  #include <linux/bootmem.h>
  #include <linux/ioport.h>
@@@ -43,6 -44,7 +44,7 @@@
  #include <asm/io.h>
  #include <asm/mpspec.h>
  #include <asm/smp.h>
+ #include <asm/i8259.h>
  
  #include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
  static int __initdata acpi_force = 0;
@@@ -74,6 -76,10 +76,6 @@@ int acpi_fix_pin2_polarity __initdata
  static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
  #endif
  
 -#ifndef __HAVE_ARCH_CMPXCHG
 -#warning ACPI uses CMPXCHG, i486 and later hardware
 -#endif
 -
  /* --------------------------------------------------------------------------
                                Boot-time Configuration
     -------------------------------------------------------------------------- */
@@@ -93,44 -99,7 +95,7 @@@ static u32 isa_irq_to_gsi[NR_IRQS_LEGAC
        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;
- }
+ #define       ACPI_INVALID_GSI                INT_MIN
  
  /*
   * This is just a simple wrapper around early_ioremap(),
@@@ -341,11 -310,145 +306,145 @@@ acpi_parse_lapic_nmi(struct acpi_subtab
  #endif                                /*CONFIG_X86_LOCAL_APIC */
  
  #ifdef CONFIG_X86_IO_APIC
+ #define MP_ISA_BUS            0
+ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+                                         u32 gsi)
+ {
+       int ioapic;
+       int pin;
+       struct mpc_intsrc mp_irq;
+       /*
+        * Convert 'gsi' to 'ioapic.pin'.
+        */
+       ioapic = mp_find_ioapic(gsi);
+       if (ioapic < 0)
+               return;
+       pin = mp_find_ioapic_pin(ioapic, gsi);
+       /*
+        * TBD: This check is for faulty timer entries, where the override
+        *      erroneously sets the trigger to level, resulting in a HUGE
+        *      increase of timer interrupts!
+        */
+       if ((bus_irq == 0) && (trigger == 3))
+               trigger = 1;
+       mp_irq.type = MP_INTSRC;
+       mp_irq.irqtype = mp_INT;
+       mp_irq.irqflag = (trigger << 2) | polarity;
+       mp_irq.srcbus = MP_ISA_BUS;
+       mp_irq.srcbusirq = bus_irq;     /* IRQ */
+       mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
+       mp_irq.dstirq = pin;    /* INTIN# */
+       mp_save_irq(&mp_irq);
+       /*
+        * Reset default identity mapping if gsi is also an legacy IRQ,
+        * otherwise there will be more than one entry with the same GSI
+        * and acpi_isa_irq_to_gsi() may give wrong result.
+        */
+       if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
+               isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
+       isa_irq_to_gsi[bus_irq] = gsi;
+ }
+ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
+                       int polarity)
+ {
+ #ifdef CONFIG_X86_MPPARSE
+       struct mpc_intsrc mp_irq;
+       struct pci_dev *pdev;
+       unsigned char number;
+       unsigned int devfn;
+       int ioapic;
+       u8 pin;
+       if (!acpi_ioapic)
+               return 0;
+       if (!dev || !dev_is_pci(dev))
+               return 0;
+       pdev = to_pci_dev(dev);
+       number = pdev->bus->number;
+       devfn = pdev->devfn;
+       pin = pdev->pin;
+       /* print the entry should happen on mptable identically */
+       mp_irq.type = MP_INTSRC;
+       mp_irq.irqtype = mp_INT;
+       mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+                               (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+       mp_irq.srcbus = number;
+       mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+       ioapic = mp_find_ioapic(gsi);
+       mp_irq.dstapic = mpc_ioapic_id(ioapic);
+       mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
+       mp_save_irq(&mp_irq);
+ #endif
+       return 0;
+ }
+ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+                          int polarity)
+ {
+       int irq, node;
+       if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+               return gsi;
+       /* Don't set up the ACPI SCI because it's already set up */
+       if (acpi_gbl_FADT.sci_interrupt == gsi)
+               return gsi;
+       trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
+       polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
+       node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+       if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
+               pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+               return -1;
+       }
+       irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
+       if (irq < 0)
+               return irq;
+       if (enable_update_mptable)
+               mp_config_acpi_gsi(dev, gsi, trigger, polarity);
+       return irq;
+ }
+ static void mp_unregister_gsi(u32 gsi)
+ {
+       int irq;
+       if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+               return;
+       if (acpi_gbl_FADT.sci_interrupt == gsi)
+               return;
+       irq = mp_map_gsi_to_irq(gsi, 0);
+       if (irq > 0)
+               mp_unmap_irq(irq);
+ }
+ static struct irq_domain_ops acpi_irqdomain_ops = {
+       .map = mp_irqdomain_map,
+       .unmap = mp_irqdomain_unmap,
+ };
  
  static int __init
  acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
  {
        struct acpi_madt_io_apic *ioapic = NULL;
+       struct ioapic_domain_cfg cfg = {
+               .type = IOAPIC_DOMAIN_DYNAMIC,
+               .ops = &acpi_irqdomain_ops,
+       };
  
        ioapic = (struct acpi_madt_io_apic *)header;
  
  
        acpi_table_print_madt_entry(header);
  
-       mp_register_ioapic(ioapic->id,
-                          ioapic->address, ioapic->global_irq_base);
+       /* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
+       if (ioapic->global_irq_base < nr_legacy_irqs())
+               cfg.type = IOAPIC_DOMAIN_LEGACY;
+       mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
+                          &cfg);
  
        return 0;
  }
@@@ -378,11 -485,6 +481,6 @@@ static void __init acpi_sci_ioapic_setu
        if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
                polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
  
-       /*
-        * mp_config_acpi_legacy_irqs() already setup IRQs < 16
-        * If GSI is < 16, this will update its flags,
-        * else it will create a new mp_irqs[] entry.
-        */
        mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
  
        /*
@@@ -504,25 -606,28 +602,28 @@@ void __init acpi_pic_sci_set_trigger(un
        outb(new >> 8, 0x4d1);
  }
  
- int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
  {
-       *irq = gsi_to_irq(gsi);
+       int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
  
- #ifdef CONFIG_X86_IO_APIC
-       if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
-               setup_IO_APIC_irq_extra(gsi);
- #endif
+       if (irq >= 0) {
+               *irqp = irq;
+               return 0;
+       }
  
-       return 0;
+       return -1;
  }
  EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
  
  int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
  {
-       if (isa_irq >= 16)
-               return -1;
-       *gsi = irq_to_gsi(isa_irq);
-       return 0;
+       if (isa_irq < nr_legacy_irqs() &&
+           isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
+               *gsi = isa_irq_to_gsi[isa_irq];
+               return 0;
+       }
+       return -1;
  }
  
  static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
  static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
                                    int trigger, int polarity)
  {
+       int irq = gsi;
  #ifdef CONFIG_X86_IO_APIC
-       gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+       irq = mp_register_gsi(dev, gsi, trigger, polarity);
  #endif
  
-       return gsi;
+       return irq;
+ }
+ static void acpi_unregister_gsi_ioapic(u32 gsi)
+ {
+ #ifdef CONFIG_X86_IO_APIC
+       mp_unregister_gsi(gsi);
+ #endif
  }
  
  int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
                           int trigger, int polarity) = acpi_register_gsi_pic;
+ void (*__acpi_unregister_gsi)(u32 gsi) = NULL;
  
  #ifdef CONFIG_ACPI_SLEEP
  int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
@@@ -564,32 -679,22 +675,22 @@@ int (*acpi_suspend_lowlevel)(void)
   */
  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;
+       return __acpi_register_gsi(dev, gsi, trigger, polarity);
  }
  EXPORT_SYMBOL_GPL(acpi_register_gsi);
  
  void acpi_unregister_gsi(u32 gsi)
  {
+       if (__acpi_unregister_gsi)
+               __acpi_unregister_gsi(gsi);
  }
  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
  
- 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)
+ static void __init acpi_set_irq_model_ioapic(void)
  {
        acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
        __acpi_register_gsi = acpi_register_gsi_ioapic;
+       __acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
        acpi_ioapic = 1;
  }
  
@@@ -825,9 -930,8 +926,8 @@@ static int __init early_acpi_parse_madt
         * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
         */
  
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
-                                 acpi_parse_lapic_addr_ovr, 0);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+                                     acpi_parse_lapic_addr_ovr, 0);
        if (count < 0) {
                printk(KERN_ERR PREFIX
                       "Error parsing LAPIC address override entry\n");
@@@ -852,9 -956,8 +952,8 @@@ static int __init acpi_parse_madt_lapic
         * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
         */
  
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
-                                 acpi_parse_lapic_addr_ovr, 0);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+                                     acpi_parse_lapic_addr_ovr, 0);
        if (count < 0) {
                printk(KERN_ERR PREFIX
                       "Error parsing LAPIC address override entry\n");
                return count;
        }
  
-       x2count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
-                                 acpi_parse_x2apic_nmi, 0);
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+       x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+                                       acpi_parse_x2apic_nmi, 0);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+                                     acpi_parse_lapic_nmi, 0);
        if (count < 0 || x2count < 0) {
                printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
                /* TBD: Cleanup to allow fallback to MPS */
  #endif                                /* CONFIG_X86_LOCAL_APIC */
  
  #ifdef        CONFIG_X86_IO_APIC
- #define MP_ISA_BUS            0
- void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
- {
-       int ioapic;
-       int pin;
-       struct mpc_intsrc mp_irq;
-       /*
-        * Convert 'gsi' to 'ioapic.pin'.
-        */
-       ioapic = mp_find_ioapic(gsi);
-       if (ioapic < 0)
-               return;
-       pin = mp_find_ioapic_pin(ioapic, gsi);
-       /*
-        * TBD: This check is for faulty timer entries, where the override
-        *      erroneously sets the trigger to level, resulting in a HUGE
-        *      increase of timer interrupts!
-        */
-       if ((bus_irq == 0) && (trigger == 3))
-               trigger = 1;
-       mp_irq.type = MP_INTSRC;
-       mp_irq.irqtype = mp_INT;
-       mp_irq.irqflag = (trigger << 2) | polarity;
-       mp_irq.srcbus = MP_ISA_BUS;
-       mp_irq.srcbusirq = bus_irq;     /* IRQ */
-       mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
-       mp_irq.dstirq = pin;    /* INTIN# */
-       mp_save_irq(&mp_irq);
-       isa_irq_to_gsi[bus_irq] = gsi;
- }
- void __init mp_config_acpi_legacy_irqs(void)
+ static void __init mp_config_acpi_legacy_irqs(void)
  {
        int i;
        struct mpc_intsrc mp_irq;
         * Use the default configuration for the IRQs 0-15.  Unless
         * overridden by (MADT) interrupt source override entries.
         */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < nr_legacy_irqs(); i++) {
                int ioapic, pin;
                unsigned int dstapic;
                int idx;
        }
  }
  
- static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
-                       int polarity)
- {
- #ifdef CONFIG_X86_MPPARSE
-       struct mpc_intsrc mp_irq;
-       struct pci_dev *pdev;
-       unsigned char number;
-       unsigned int devfn;
-       int ioapic;
-       u8 pin;
-       if (!acpi_ioapic)
-               return 0;
-       if (!dev || !dev_is_pci(dev))
-               return 0;
-       pdev = to_pci_dev(dev);
-       number = pdev->bus->number;
-       devfn = pdev->devfn;
-       pin = pdev->pin;
-       /* print the entry should happen on mptable identically */
-       mp_irq.type = MP_INTSRC;
-       mp_irq.irqtype = mp_INT;
-       mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
-                               (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
-       mp_irq.srcbus = number;
-       mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
-       ioapic = mp_find_ioapic(gsi);
-       mp_irq.dstapic = mpc_ioapic_id(ioapic);
-       mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
-       mp_save_irq(&mp_irq);
- #endif
-       return 0;
- }
- int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
- {
-       int ioapic;
-       int ioapic_pin;
-       struct io_apic_irq_attr irq_attr;
-       int ret;
-       if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
-               return gsi;
-       /* Don't set up the ACPI SCI because it's already set up */
-       if (acpi_gbl_FADT.sci_interrupt == gsi)
-               return gsi;
-       ioapic = mp_find_ioapic(gsi);
-       if (ioapic < 0) {
-               printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
-               return gsi;
-       }
-       ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-       if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
-               printk(KERN_ERR "Invalid reference to IOAPIC pin "
-                      "%d-%d\n", mpc_ioapic_id(ioapic),
-                      ioapic_pin);
-               return gsi;
-       }
-       if (enable_update_mptable)
-               mp_config_acpi_gsi(dev, gsi, trigger, polarity);
-       set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
-                            trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
-                            polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
-       ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
-       if (ret < 0)
-               gsi = INT_MIN;
-       return gsi;
- }
  /*
   * Parse IOAPIC related entries in MADT
   * returns 0 on success, < 0 on error
@@@ -1107,9 -1094,8 +1090,8 @@@ static int __init acpi_parse_madt_ioapi
                return -ENODEV;
        }
  
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
-                                 MAX_IO_APICS);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+                                     MAX_IO_APICS);
        if (!count) {
                printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
                return -ENODEV;
                return count;
        }
  
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
-                                 nr_irqs);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+                                     acpi_parse_int_src_ovr, nr_irqs);
        if (count < 0) {
                printk(KERN_ERR PREFIX
                       "Error parsing interrupt source overrides entry\n");
        /* Fill in identity legacy mappings where no override */
        mp_config_acpi_legacy_irqs();
  
-       count =
-           acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
-                                 nr_irqs);
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+                                     acpi_parse_nmi_src, nr_irqs);
        if (count < 0) {
                printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
                /* TBD: Cleanup to allow fallback to MPS */