]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Mar 2010 16:15:37 +0000 (08:15 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Mar 2010 16:15:37 +0000 (08:15 -0800)
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (25 commits)
  x86: Fix out of order of gsi
  x86: apic: Fix mismerge, add arch_probe_nr_irqs() again
  x86, irq: Keep chip_data in create_irq_nr and destroy_irq
  xen: Remove unnecessary arch specific xen irq functions.
  smp: Use nr_cpus= to set nr_cpu_ids early
  x86, irq: Remove arch_probe_nr_irqs
  sparseirq: Use radix_tree instead of ptrs array
  sparseirq: Change irq_desc_ptrs to static
  init: Move radix_tree_init() early
  irq: Remove unnecessary bootmem code
  x86: Add iMac9,1 to pci_reboot_dmi_table
  x86: Convert i8259_lock to raw_spinlock
  x86: Convert nmi_lock to raw_spinlock
  x86: Convert ioapic_lock and vector_lock to raw_spinlock
  x86: Avoid race condition in pci_enable_msix()
  x86: Fix SCI on IOAPIC != 0
  x86, ia32_aout: do not kill argument mapping
  x86, irq: Move __setup_vector_irq() before the first irq enable in cpu online path
  x86, irq: Update the vector domain for legacy irqs handled by io-apic
  x86, irq: Don't block IRQ0_VECTOR..IRQ15_VECTOR's on all cpu's
  ...

1  2 
Documentation/kernel-parameters.txt
arch/ia64/kernel/acpi.c
arch/x86/ia32/ia32_aout.c
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/nmi.c
arch/x86/kernel/smpboot.c
include/linux/irq.h
init/main.c

index fbcddc5abe25b7b3ed55f3b8a43680d2c38ddfc3,51bceb0fb2778564b0dd5383fa13cbbfdad1ad6c..d80930d58daeb4a479e3ab6592b156faaf5d3e69
@@@ -54,7 -54,6 +54,7 @@@ parameter is applicable
        IMA     Integrity measurement architecture is enabled.
        IOSCHED More than one I/O scheduler is enabled.
        IP_PNP  IP DHCP, BOOTP, or RARP is enabled.
 +      IPV6    IPv6 support is enabled.
        ISAPNP  ISA PnP code is enabled.
        ISDN    Appropriate ISDN support is enabled.
        JOY     Appropriate joystick support is enabled.
@@@ -200,10 -199,6 +200,10 @@@ and is between 256 and 4096 characters
                        acpi_display_output=video
                        See above.
  
 +      acpi_early_pdc_eval     [HW,ACPI] Evaluate processor _PDC methods
 +                              early. Needed on some platforms to properly
 +                              initialize the EC.
 +
        acpi_irq_balance [HW,ACPI]
                        ACPI will balance active IRQs
                        default in APIC mode
        aic79xx=        [HW,SCSI]
                        See Documentation/scsi/aic79xx.txt.
  
 +      alignment=      [KNL,ARM]
 +                      Allow the default userspace alignment fault handler
 +                      behaviour to be specified.  Bit 0 enables warnings,
 +                      bit 1 enables fixups, and bit 2 sends a segfault.
 +
        amd_iommu=      [HW,X86-84]
                        Pass parameters to the AMD IOMMU driver in the system.
                        Possible values are:
                        Change the amount of debugging information output
                        when initialising the APIC and IO-APIC components.
  
 +      autoconf=       [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
        show_lapic=     [APIC,X86] Advanced Programmable Interrupt Controller
                        Limit apic dumping. The parameter defines the maximal
                        number of local apics being dumped. Also it is possible
                        See drivers/char/README.epca and
                        Documentation/serial/digiepca.txt.
  
 +      disable=        [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
 +      disable_ipv6=   [IPV6]
 +                      See Documentation/networking/ipv6.txt.
 +
        disable_mtrr_cleanup [X86]
                        The kernel tries to adjust MTRR layout from continuous
                        to discrete, to make X server driver able to add WB
        nomfgpt         [X86-32] Disable Multi-Function General Purpose
                        Timer usage (for AMD Geode machines).
  
 +      nopat           [X86] Disable PAT (page attribute table extension of
 +                      pagetables) support.
 +
        norandmaps      Don't use address space randomization.  Equivalent to
                        echo 0 > /proc/sys/kernel/randomize_va_space
  
                        purges which is reported from either PAL_VM_SUMMARY or
                        SAL PALO.
  
+       nr_cpus=        [SMP] Maximum number of processors that an SMP kernel
+                       could support.  nr_cpus=n : n >= 1 limits the kernel to
+                       supporting 'n' processors. Later in runtime you can not
+                       use hotplug cpu feature to put more cpu back to online.
+                       just like you compile the kernel NR_CPUS=n
        nr_uarts=       [SERIAL] maximum number of UARTs to be registered.
  
        numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
                                IRQ routing is enabled.
                noacpi          [X86] Do not use ACPI for IRQ routing
                                or for PCI scanning.
 -              use_crs         [X86] Use _CRS for PCI resource
 -                              allocation.
 +              use_crs         [X86] Use PCI host bridge window information
 +                              from ACPI.  On BIOSes from 2008 or later, this
 +                              is enabled by default.  If you need to use this,
 +                              please report a bug.
 +              nocrs           [X86] Ignore PCI host bridge windows from ACPI.
 +                              If you need to use this, please report a bug.
                routeirq        Do IRQ routing for all PCI devices.
                                This is normally done in pci_enable_device(),
                                so this option is a temporary workaround
                force   Enable ASPM even on devices that claim not to support it.
                        WARNING: Forcing ASPM on may cause system lockups.
  
 +      pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
 +              off     Do not use native PCIe PME signaling.
 +              force   Use native PCIe PME signaling even if the BIOS refuses
 +                      to allow the kernel to control the relevant PCIe config
 +                      registers.
 +              nomsi   Do not use MSI for native PCIe PME signaling (this makes
 +                      all PCIe root ports use INTx for everything).
 +
        pcmv=           [HW,PCMCIA] BadgePAD 4
  
        pd.             [PARIDE]
                                        medium is write-protected).
                        Example: quirks=0419:aaf5:rl,0421:0433:rc
  
 +      userpte=
 +                      [X86] Flags controlling user PTE allocations.
 +
 +                              nohigh = do not allocate PTE pages in
 +                                      HIGHMEM regardless of setting
 +                                      of CONFIG_HIGHPTE.
 +
        vdso=           [X86,SH]
                        vdso=2: enable compat VDSO (default with COMPAT_VDSO)
                        vdso=1: enable VDSO (default)
diff --combined arch/ia64/kernel/acpi.c
index c16fb03037d4a2c69703465d135b44e5e173a6e5,605a08b29721eca160672484a76aa5a90b8adee3..a7ca07f3754e50483f73dda4d545383c293e4c82
  
  #define PREFIX                        "ACPI: "
  
 -void (*pm_idle) (void);
 -EXPORT_SYMBOL(pm_idle);
 -void (*pm_power_off) (void);
 -EXPORT_SYMBOL(pm_power_off);
 -
  u32 acpi_rsdt_forced;
  unsigned int acpi_cpei_override;
  unsigned int acpi_cpei_phys_cpuid;
@@@ -78,10 -83,12 +78,10 @@@ static unsigned long __init acpi_find_r
                       "v1.0/r0.71 tables no longer supported\n");
        return rsdp_phys;
  }
 -#endif
  
  const char __init *
  acpi_get_sysname(void)
  {
 -#ifdef CONFIG_IA64_GENERIC
        unsigned long rsdp_phys;
        struct acpi_table_rsdp *rsdp;
        struct acpi_table_xsdt *xsdt;
  #endif
  
        return "dig";
 -#else
 -# if defined (CONFIG_IA64_HP_SIM)
 -      return "hpsim";
 -# elif defined (CONFIG_IA64_HP_ZX1)
 -      return "hpzx1";
 -# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
 -      return "hpzx1_swiotlb";
 -# elif defined (CONFIG_IA64_SGI_SN2)
 -      return "sn2";
 -# elif defined (CONFIG_IA64_SGI_UV)
 -      return "uv";
 -# elif defined (CONFIG_IA64_DIG)
 -      return "dig";
 -# elif defined (CONFIG_IA64_XEN_GUEST)
 -      return "xen";
 -# elif defined(CONFIG_IA64_DIG_VTD)
 -      return "dig_vtd";
 -# else
 -#     error Unknown platform.  Fix acpi.c.
 -# endif
 -#endif
  }
 -
 -#ifdef CONFIG_ACPI
 +#endif /* CONFIG_IA64_GENERIC */
  
  #define ACPI_MAX_PLATFORM_INTERRUPTS  256
  
@@@ -852,8 -881,8 +852,8 @@@ __init void prefill_possible_map(void
  
        possible = available_cpus + additional_cpus;
  
-       if (possible > NR_CPUS)
-               possible = NR_CPUS;
+       if (possible > nr_cpu_ids)
+               possible = nr_cpu_ids;
  
        printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
                possible, max((possible - available_cpus), 0));
@@@ -1031,3 -1060,5 +1031,3 @@@ void acpi_restore_state_mem(void) {
   * do_suspend_lowlevel()
   */
  void do_suspend_lowlevel(void) {}
 -
 -#endif                                /* CONFIG_ACPI */
index 9046e4af66ce7a36d2ed5e83522046d04a3a6081,14531abdd0ced75cc2f5a60e9ff29fe0308a91b8..280c019cfad8c8475741178daed7406214a8308c
@@@ -297,7 -297,7 +297,7 @@@ static int load_aout_binary(struct linu
         * size limits imposed on them by creating programs with large
         * arrays in the data or bss.
         */
 -      rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
 +      rlim = rlimit(RLIMIT_DATA);
        if (rlim >= RLIM_INFINITY)
                rlim = ~0;
        if (ex.a_data + ex.a_bss > rlim)
        current->mm->free_area_cache = TASK_UNMAPPED_BASE;
        current->mm->cached_hole_size = 0;
  
-       current->mm->mmap = NULL;
        install_exec_creds(bprm);
        current->flags &= ~PF_FORKNOEXEC;
  
index f95703098f8dc9e4b6c0f4e4cd482217783c2d5e,5c96b75c6ea8433baebd1c3b92dee16cf34c71df..738fcb60e7086ccca4096fa82bc818b2d0d7b35a
@@@ -49,7 -49,6 +49,7 @@@ EXPORT_SYMBOL(acpi_disabled)
  
  #ifdef        CONFIG_X86_64
  # include <asm/proto.h>
 +# include <asm/numa_64.h>
  #endif                                /* X86 */
  
  #define BAD_MADT_ENTRY(entry, end) (                                      \
@@@ -447,6 -446,12 +447,12 @@@ void __init acpi_pic_sci_set_trigger(un
  int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
  {
        *irq = gsi;
+ #ifdef CONFIG_X86_IO_APIC
+       if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+               setup_IO_APIC_irq_extra(gsi);
+ #endif
        return 0;
  }
  
@@@ -474,7 -479,8 +480,8 @@@ int acpi_register_gsi(struct device *de
                plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
        }
  #endif
-       acpi_gsi_to_irq(plat_gsi, &irq);
+       irq = plat_gsi;
        return irq;
  }
  
   */
  #ifdef CONFIG_ACPI_HOTPLUG_CPU
  
 +static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 +{
 +#ifdef CONFIG_ACPI_NUMA
 +      int nid;
 +
 +      nid = acpi_get_node(handle);
 +      if (nid == -1 || !node_online(nid))
 +              return;
 +#ifdef CONFIG_X86_64
 +      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
 +}
 +
  static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
  {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        }
  
        cpu = cpumask_first(new_map);
 +      acpi_map_cpu2node(handle, cpu, physid);
  
        *pcpu = cpu;
        retval = 0;
@@@ -1363,6 -1349,14 +1370,6 @@@ static struct dmi_system_id __initdata 
                     DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
                     },
         },
 -      {
 -       .callback = force_acpi_ht,
 -       .ident = "ASUS P2B-DS",
 -       .matches = {
 -                   DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
 -                   DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
 -                   },
 -       },
        {
         .callback = force_acpi_ht,
         .ident = "ASUS CUR-DLS",
index 6bdd2c7ead755827ab67f62e0af854c95b27f485,97e1e3ec2edf2ac4ac361e60d1d4c01f47775374..14862f11cc4ad68a1b8ef7761ec3f2c37f82b532
@@@ -73,8 -73,8 +73,8 @@@
   */
  int sis_apic_bug = -1;
  
- static DEFINE_SPINLOCK(ioapic_lock);
- static DEFINE_SPINLOCK(vector_lock);
+ static DEFINE_RAW_SPINLOCK(ioapic_lock);
+ static DEFINE_RAW_SPINLOCK(vector_lock);
  
  /*
   * # of IRQ routing registers
@@@ -94,8 -94,6 +94,6 @@@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURC
  /* # of MP IRQ source entries */
  int mp_irq_entries;
  
- /* Number of legacy interrupts */
- static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
  /* GSI interrupts */
  static int nr_irqs_gsi = NR_IRQS_LEGACY;
  
@@@ -140,27 -138,10 +138,10 @@@ static struct irq_pin_list *get_one_fre
  
  /* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
  #ifdef CONFIG_SPARSE_IRQ
- static struct irq_cfg irq_cfgx[] = {
+ static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
  #else
- static struct irq_cfg irq_cfgx[NR_IRQS] = {
+ static struct irq_cfg irq_cfgx[NR_IRQS];
  #endif
-       [0]  = { .vector = IRQ0_VECTOR,  },
-       [1]  = { .vector = IRQ1_VECTOR,  },
-       [2]  = { .vector = IRQ2_VECTOR,  },
-       [3]  = { .vector = IRQ3_VECTOR,  },
-       [4]  = { .vector = IRQ4_VECTOR,  },
-       [5]  = { .vector = IRQ5_VECTOR,  },
-       [6]  = { .vector = IRQ6_VECTOR,  },
-       [7]  = { .vector = IRQ7_VECTOR,  },
-       [8]  = { .vector = IRQ8_VECTOR,  },
-       [9]  = { .vector = IRQ9_VECTOR,  },
-       [10] = { .vector = IRQ10_VECTOR, },
-       [11] = { .vector = IRQ11_VECTOR, },
-       [12] = { .vector = IRQ12_VECTOR, },
-       [13] = { .vector = IRQ13_VECTOR, },
-       [14] = { .vector = IRQ14_VECTOR, },
-       [15] = { .vector = IRQ15_VECTOR, },
- };
  
  void __init io_apic_disable_legacy(void)
  {
@@@ -185,8 -166,14 +166,14 @@@ int __init arch_early_irq_init(void
                desc->chip_data = &cfg[i];
                zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
                zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
-               if (i < nr_legacy_irqs)
-                       cpumask_setall(cfg[i].domain);
+               /*
+                * For legacy IRQ's, start with assigning irq0 to irq15 to
+                * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
+                */
+               if (i < nr_legacy_irqs) {
+                       cfg[i].vector = IRQ0_VECTOR + i;
+                       cpumask_set_cpu(0, cfg[i].domain);
+               }
        }
  
        return 0;
@@@ -406,7 -393,7 +393,7 @@@ static bool io_apic_level_ack_pending(s
        struct irq_pin_list *entry;
        unsigned long flags;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        for_each_irq_pin(entry, cfg->irq_2_pin) {
                unsigned int reg;
                int pin;
                reg = io_apic_read(entry->apic, 0x10 + pin*2);
                /* Is the remote IRR bit set? */
                if (reg & IO_APIC_REDIR_REMOTE_IRR) {
-                       spin_unlock_irqrestore(&ioapic_lock, flags);
+                       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
                        return true;
                }
        }
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        return false;
  }
@@@ -433,10 -420,10 +420,10 @@@ static struct IO_APIC_route_entry ioapi
  {
        union entry_union eu;
        unsigned long flags;
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
        eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
        return eu.entry;
  }
  
@@@ -459,9 -446,9 +446,9 @@@ __ioapic_write_entry(int apic, int pin
  void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
  {
        unsigned long flags;
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        __ioapic_write_entry(apic, pin, e);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  }
  
  /*
@@@ -474,10 -461,10 +461,10 @@@ static void ioapic_mask_entry(int apic
        unsigned long flags;
        union entry_union eu = { .entry.mask = 1 };
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        io_apic_write(apic, 0x10 + 2*pin, eu.w1);
        io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  }
  
  /*
@@@ -604,9 -591,9 +591,9 @@@ static void mask_IO_APIC_irq_desc(struc
  
        BUG_ON(!cfg);
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        __mask_IO_APIC_irq(cfg);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  }
  
  static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
        struct irq_cfg *cfg = desc->chip_data;
        unsigned long flags;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        __unmask_IO_APIC_irq(cfg);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  }
  
  static void mask_IO_APIC_irq(unsigned int irq)
@@@ -1140,12 -1127,12 +1127,12 @@@ void lock_vector_lock(void
        /* Used to the online set of cpus does not change
         * during assign_irq_vector.
         */
-       spin_lock(&vector_lock);
+       raw_spin_lock(&vector_lock);
  }
  
  void unlock_vector_lock(void)
  {
-       spin_unlock(&vector_lock);
+       raw_spin_unlock(&vector_lock);
  }
  
  static int
@@@ -1162,7 -1149,8 +1149,8 @@@ __assign_irq_vector(int irq, struct irq
         * Also, we've got to be careful not to trash gate
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
-       static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+       static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
+       static int current_offset = VECTOR_OFFSET_START % 8;
        unsigned int old_vector;
        int cpu, err;
        cpumask_var_t tmp_mask;
@@@ -1198,7 -1186,7 +1186,7 @@@ next
                if (vector >= first_system_vector) {
                        /* If out of vectors on large boxen, must share them. */
                        offset = (offset + 1) % 8;
-                       vector = FIRST_DEVICE_VECTOR + offset;
+                       vector = FIRST_EXTERNAL_VECTOR + offset;
                }
                if (unlikely(current_vector == vector))
                        continue;
@@@ -1232,9 -1220,9 +1220,9 @@@ int assign_irq_vector(int irq, struct i
        int err;
        unsigned long flags;
  
-       spin_lock_irqsave(&vector_lock, flags);
+       raw_spin_lock_irqsave(&vector_lock, flags);
        err = __assign_irq_vector(irq, cfg, mask);
-       spin_unlock_irqrestore(&vector_lock, flags);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
        return err;
  }
  
@@@ -1268,11 -1256,16 +1256,16 @@@ static void __clear_irq_vector(int irq
  void __setup_vector_irq(int cpu)
  {
        /* Initialize vector_irq on a new cpu */
-       /* This function must be called with vector_lock held */
        int irq, vector;
        struct irq_cfg *cfg;
        struct irq_desc *desc;
  
+       /*
+        * vector_lock will make sure that we don't run into irq vector
+        * assignments that might be happening on another cpu in parallel,
+        * while we setup our initial vector to irq mappings.
+        */
+       raw_spin_lock(&vector_lock);
        /* Mark the inuse vectors */
        for_each_irq_desc(irq, desc) {
                cfg = desc->chip_data;
                if (!cpumask_test_cpu(cpu, cfg->domain))
                        per_cpu(vector_irq, cpu)[vector] = -1;
        }
+       raw_spin_unlock(&vector_lock);
  }
  
  static struct irq_chip ioapic_chip;
@@@ -1440,6 -1434,14 +1434,14 @@@ static void setup_IO_APIC_irq(int apic_
  
        cfg = desc->chip_data;
  
+       /*
+        * For legacy irqs, cfg->domain starts with cpu 0 for legacy
+        * controllers like 8259. Now that IO-APIC can handle this irq, update
+        * the cfg->domain.
+        */
+       if (irq < nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
+               apic->vector_allocation_domain(0, cfg->domain);
        if (assign_irq_vector(irq, cfg, apic->target_cpus()))
                return;
  
@@@ -1473,7 -1475,7 +1475,7 @@@ static struct 
  
  static void __init setup_IO_APIC_irqs(void)
  {
-       int apic_id = 0, pin, idx, irq;
+       int apic_id, pin, idx, irq;
        int notcon = 0;
        struct irq_desc *desc;
        struct irq_cfg *cfg;
  
        apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
  
- #ifdef CONFIG_ACPI
-       if (!acpi_disabled && acpi_ioapic) {
-               apic_id = mp_find_ioapic(0);
-               if (apic_id < 0)
-                       apic_id = 0;
-       }
- #endif
+       for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
        for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
                idx = find_irq_entry(apic_id, pin, mp_INT);
                if (idx == -1) {
  
                irq = pin_2_irq(idx, apic_id, pin);
  
+               if ((apic_id > 0) && (irq > 16))
+                       continue;
                /*
                 * Skip the timer IRQ if there's a quirk handler
                 * installed and if it returns 1:
                        " (apicid-pin) not connected\n");
  }
  
+ /*
+  * for the gsit that is not in first ioapic
+  * but could not use acpi_register_gsi()
+  * like some special sci in IBM x3330
+  */
+ void setup_IO_APIC_irq_extra(u32 gsi)
+ {
+       int apic_id = 0, pin, idx, irq;
+       int node = cpu_to_node(boot_cpu_id);
+       struct irq_desc *desc;
+       struct irq_cfg *cfg;
+       /*
+        * Convert 'gsi' to 'ioapic.pin'.
+        */
+       apic_id = mp_find_ioapic(gsi);
+       if (apic_id < 0)
+               return;
+       pin = mp_find_ioapic_pin(apic_id, gsi);
+       idx = find_irq_entry(apic_id, pin, mp_INT);
+       if (idx == -1)
+               return;
+       irq = pin_2_irq(idx, apic_id, pin);
+ #ifdef CONFIG_SPARSE_IRQ
+       desc = irq_to_desc(irq);
+       if (desc)
+               return;
+ #endif
+       desc = irq_to_desc_alloc_node(irq, node);
+       if (!desc) {
+               printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+               return;
+       }
+       cfg = desc->chip_data;
+       add_pin_to_irq_node(cfg, node, apic_id, pin);
+       if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
+               pr_debug("Pin %d-%d already programmed\n",
+                        mp_ioapics[apic_id].apicid, pin);
+               return;
+       }
+       set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+       setup_IO_APIC_irq(apic_id, pin, irq, desc,
+                       irq_trigger(idx), irq_polarity(idx));
+ }
  /*
   * Set up the timer pin, possibly with the 8259A-master behind.
   */
@@@ -1601,14 -1649,14 +1649,14 @@@ __apicdebuginit(void) print_IO_APIC(voi
  
        for (apic = 0; apic < nr_ioapics; apic++) {
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_00.raw = io_apic_read(apic, 0);
        reg_01.raw = io_apic_read(apic, 1);
        if (reg_01.bits.version >= 0x10)
                reg_02.raw = io_apic_read(apic, 2);
        if (reg_01.bits.version >= 0x20)
                reg_03.raw = io_apic_read(apic, 3);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        printk("\n");
        printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid);
        printk(KERN_DEBUG ".... IRQ redirection table:\n");
  
        printk(KERN_DEBUG " NR Dst Mask Trig IRR Pol"
 -                        " Stat Dmod Deli Vect:   \n");
 +                        " Stat Dmod Deli Vect:\n");
  
        for (i = 0; i <= reg_01.bits.entries; i++) {
                struct IO_APIC_route_entry entry;
@@@ -1830,7 -1878,7 +1878,7 @@@ __apicdebuginit(void) print_PIC(void
  
        printk(KERN_DEBUG "\nprinting PIC contents\n");
  
-       spin_lock_irqsave(&i8259A_lock, flags);
+       raw_spin_lock_irqsave(&i8259A_lock, flags);
  
        v = inb(0xa1) << 8 | inb(0x21);
        printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
        outb(0x0a,0xa0);
        outb(0x0a,0x20);
  
-       spin_unlock_irqrestore(&i8259A_lock, flags);
+       raw_spin_unlock_irqrestore(&i8259A_lock, flags);
  
        printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
  
@@@ -1903,9 -1951,9 +1951,9 @@@ void __init enable_IO_APIC(void
         * The number of IO-APIC IRQ registers (== #pins):
         */
        for (apic = 0; apic < nr_ioapics; apic++) {
-               spin_lock_irqsave(&ioapic_lock, flags);
+               raw_spin_lock_irqsave(&ioapic_lock, flags);
                reg_01.raw = io_apic_read(apic, 1);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               raw_spin_unlock_irqrestore(&ioapic_lock, flags);
                nr_ioapic_registers[apic] = reg_01.bits.entries+1;
        }
  
@@@ -2045,9 -2093,9 +2093,9 @@@ void __init setup_ioapic_ids_from_mpc(v
        for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
  
                /* Read the register 0 value */
-               spin_lock_irqsave(&ioapic_lock, flags);
+               raw_spin_lock_irqsave(&ioapic_lock, flags);
                reg_00.raw = io_apic_read(apic_id, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
                old_id = mp_ioapics[apic_id].apicid;
  
                        mp_ioapics[apic_id].apicid);
  
                reg_00.bits.ID = mp_ioapics[apic_id].apicid;
-               spin_lock_irqsave(&ioapic_lock, flags);
+               raw_spin_lock_irqsave(&ioapic_lock, flags);
                io_apic_write(apic_id, 0, reg_00.raw);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
                /*
                 * Sanity check
                 */
-               spin_lock_irqsave(&ioapic_lock, flags);
+               raw_spin_lock_irqsave(&ioapic_lock, flags);
                reg_00.raw = io_apic_read(apic_id, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               raw_spin_unlock_irqrestore(&ioapic_lock, flags);
                if (reg_00.bits.ID != mp_ioapics[apic_id].apicid)
                        printk("could not set ID!\n");
                else
@@@ -2198,7 -2246,7 +2246,7 @@@ static unsigned int startup_ioapic_irq(
        unsigned long flags;
        struct irq_cfg *cfg;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        if (irq < nr_legacy_irqs) {
                disable_8259A_irq(irq);
                if (i8259A_irq_pending(irq))
        }
        cfg = irq_cfg(irq);
        __unmask_IO_APIC_irq(cfg);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        return was_pending;
  }
@@@ -2217,9 -2265,9 +2265,9 @@@ static int ioapic_retrigger_irq(unsigne
        struct irq_cfg *cfg = irq_cfg(irq);
        unsigned long flags;
  
-       spin_lock_irqsave(&vector_lock, flags);
+       raw_spin_lock_irqsave(&vector_lock, flags);
        apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
-       spin_unlock_irqrestore(&vector_lock, flags);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
  
        return 1;
  }
@@@ -2312,14 -2360,14 +2360,14 @@@ set_ioapic_affinity_irq_desc(struct irq
        irq = desc->irq;
        cfg = desc->chip_data;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        ret = set_desc_affinity(desc, mask, &dest);
        if (!ret) {
                /* Only the high 8 bits are valid. */
                dest = SET_APIC_LOGICAL_ID(dest);
                __target_IO_APIC_irq(irq, dest, cfg);
        }
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        return ret;
  }
@@@ -2554,9 -2602,9 +2602,9 @@@ static void eoi_ioapic_irq(struct irq_d
        irq = desc->irq;
        cfg = desc->chip_data;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        __eoi_ioapic_irq(irq, cfg);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  }
  
  static void ack_apic_level(unsigned int irq)
@@@ -3138,13 -3186,13 +3186,13 @@@ static int ioapic_resume(struct sys_dev
        data = container_of(dev, struct sysfs_ioapic_data, dev);
        entry = data->entry;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_00.raw = io_apic_read(dev->id, 0);
        if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
                reg_00.bits.ID = mp_ioapics[dev->id].apicid;
                io_apic_write(dev->id, 0, reg_00.raw);
        }
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
        for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
                ioapic_write_entry(dev->id, i, entry[i]);
  
@@@ -3207,7 -3255,7 +3255,7 @@@ unsigned int create_irq_nr(unsigned in
        if (irq_want < nr_irqs_gsi)
                irq_want = nr_irqs_gsi;
  
-       spin_lock_irqsave(&vector_lock, flags);
+       raw_spin_lock_irqsave(&vector_lock, flags);
        for (new = irq_want; new < nr_irqs; new++) {
                desc_new = irq_to_desc_alloc_node(new, node);
                if (!desc_new) {
                        irq = new;
                break;
        }
-       spin_unlock_irqrestore(&vector_lock, flags);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+       if (irq > 0)
+               dynamic_irq_init_keep_chip_data(irq);
  
-       if (irq > 0) {
-               dynamic_irq_init(irq);
-               /* restore it, in case dynamic_irq_init clear it */
-               if (desc_new)
-                       desc_new->chip_data = cfg_new;
-       }
        return irq;
  }
  
@@@ -3255,20 -3300,13 +3300,13 @@@ int create_irq(void
  void destroy_irq(unsigned int irq)
  {
        unsigned long flags;
-       struct irq_cfg *cfg;
-       struct irq_desc *desc;
  
-       /* store it, in case dynamic_irq_cleanup clear it */
-       desc = irq_to_desc(irq);
-       cfg = desc->chip_data;
-       dynamic_irq_cleanup(irq);
-       /* connect back irq_cfg */
-       desc->chip_data = cfg;
+       dynamic_irq_cleanup_keep_chip_data(irq);
  
        free_irte(irq);
-       spin_lock_irqsave(&vector_lock, flags);
-       __clear_irq_vector(irq, cfg);
-       spin_unlock_irqrestore(&vector_lock, flags);
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       __clear_irq_vector(irq, get_irq_chip_data(irq));
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
  }
  
  /*
@@@ -3805,9 -3843,9 +3843,9 @@@ int __init io_apic_get_redir_entries (i
        union IO_APIC_reg_01    reg_01;
        unsigned long flags;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_01.raw = io_apic_read(ioapic, 1);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        return reg_01.bits.entries;
  }
@@@ -3969,9 -4007,9 +4007,9 @@@ int __init io_apic_get_unique_id(int io
        if (physids_empty(apic_id_map))
                apic->ioapic_phys_id_map(&phys_cpu_present_map, &apic_id_map);
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_00.raw = io_apic_read(ioapic, 0);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        if (apic_id >= get_physical_broadcast()) {
                printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
        if (reg_00.bits.ID != apic_id) {
                reg_00.bits.ID = apic_id;
  
-               spin_lock_irqsave(&ioapic_lock, flags);
+               raw_spin_lock_irqsave(&ioapic_lock, flags);
                io_apic_write(ioapic, 0, reg_00.raw);
                reg_00.raw = io_apic_read(ioapic, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
                /* Sanity check */
                if (reg_00.bits.ID != apic_id) {
@@@ -4029,9 -4067,9 +4067,9 @@@ int __init io_apic_get_version(int ioap
        union IO_APIC_reg_01    reg_01;
        unsigned long flags;
  
-       spin_lock_irqsave(&ioapic_lock, flags);
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
        reg_01.raw = io_apic_read(ioapic, 1);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
  
        return reg_01.bits.version;
  }
@@@ -4063,27 -4101,23 +4101,23 @@@ int acpi_get_override_irq(int bus_irq, 
  #ifdef CONFIG_SMP
  void __init setup_ioapic_dest(void)
  {
-       int pin, ioapic = 0, irq, irq_entry;
+       int pin, ioapic, irq, irq_entry;
        struct irq_desc *desc;
        const struct cpumask *mask;
  
        if (skip_ioapic_setup == 1)
                return;
  
- #ifdef CONFIG_ACPI
-       if (!acpi_disabled && acpi_ioapic) {
-               ioapic = mp_find_ioapic(0);
-               if (ioapic < 0)
-                       ioapic = 0;
-       }
- #endif
+       for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
        for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
                irq_entry = find_irq_entry(ioapic, pin, mp_INT);
                if (irq_entry == -1)
                        continue;
                irq = pin_2_irq(irq_entry, ioapic, pin);
  
+               if ((ioapic > 0) && (irq > 16))
+                       continue;
                desc = irq_to_desc(irq);
  
                /*
index 4ada42c3dabb97aec6dd0dd27b5405258d31397a,24e7742d633abb3018cb627fa60bb638a734385e..bd7c96b5e8d8fd2f26f85c3e5e03cd5977682c68
@@@ -416,13 -416,13 +416,13 @@@ nmi_watchdog_tick(struct pt_regs *regs
  
        /* We can be called before check_nmi_watchdog, hence NULL check. */
        if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
-               static DEFINE_SPINLOCK(lock);   /* Serialise the printks */
+               static DEFINE_RAW_SPINLOCK(lock); /* Serialise the printks */
  
-               spin_lock(&lock);
+               raw_spin_lock(&lock);
                printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
                show_regs(regs);
                dump_stack();
-               spin_unlock(&lock);
+               raw_spin_unlock(&lock);
                cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
  
                rc = 1;
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
 -              __this_cpu_inc(per_cpu_var(alert_counter));
 -              if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz)
 +              __this_cpu_inc(alert_counter);
 +              if (__this_cpu_read(alert_counter) == 5 * nmi_hz)
                        /*
                         * die_nmi will return ONLY if NOTIFY_STOP happens..
                         */
                                regs, panic_on_timeout);
        } else {
                __get_cpu_var(last_irq_sum) = sum;
 -              __this_cpu_write(per_cpu_var(alert_counter), 0);
 +              __this_cpu_write(alert_counter, 0);
        }
  
        /* see if the nmi watchdog went off */
index 9b4401115ea1813b002b84a4f7f2bb8a8d1a644f,da99eef1f0dcdfc2a4c9c6a2800e0b0bb801e18c..a435c76d714ebd81eef9d0fa9c293087ed92a7bc
@@@ -241,6 -241,11 +241,11 @@@ static void __cpuinit smp_callin(void
        map_cpu_to_logical_apicid();
  
        notify_cpu_starting(cpuid);
+       /*
+        * Need to setup vector mappings before we enable interrupts.
+        */
+       __setup_vector_irq(smp_processor_id());
        /*
         * Get our bogomips.
         *
@@@ -315,12 -320,10 +320,11 @@@ notrace static void __cpuinit start_sec
         */
        ipi_call_lock();
        lock_vector_lock();
-       __setup_vector_irq(smp_processor_id());
        set_cpu_online(smp_processor_id(), true);
        unlock_vector_lock();
        ipi_call_unlock();
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 +      x86_platform.nmi_init();
  
        /* enable local interrupts */
        local_irq_enable();
@@@ -1212,11 -1215,12 +1216,12 @@@ __init void prefill_possible_map(void
  
        total_cpus = max_t(int, possible, num_processors + disabled_cpus);
  
-       if (possible > CONFIG_NR_CPUS) {
+       /* nr_cpu_ids could be reduced via nr_cpus= */
+       if (possible > nr_cpu_ids) {
                printk(KERN_WARNING
                        "%d Processors exceeds NR_CPUS limit of %d\n",
-                       possible, CONFIG_NR_CPUS);
-               possible = CONFIG_NR_CPUS;
+                       possible, nr_cpu_ids);
+               possible = nr_cpu_ids;
        }
  
        printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
diff --combined include/linux/irq.h
index d13492df57a1bb9c55dd51085b6518aae5557208,4d9b26e044bcb7ee02a3f2e4b4aed70e9c88d7c0..707ab122e2e68cf7e3e1d7af284cbfd419c2d6c2
@@@ -90,7 -90,7 +90,7 @@@ struct msi_desc
   * @startup:          start up the interrupt (defaults to ->enable if NULL)
   * @shutdown:         shut down the interrupt (defaults to ->disable if NULL)
   * @enable:           enable the interrupt (defaults to chip->unmask if NULL)
 - * @disable:          disable the interrupt (defaults to chip->mask if NULL)
 + * @disable:          disable the interrupt
   * @ack:              start of a new interrupt
   * @mask:             mask an interrupt source
   * @mask_ack:         ack and mask an interrupt source
@@@ -400,7 -400,9 +400,9 @@@ static inline int irq_has_action(unsign
  
  /* Dynamic irq helper functions */
  extern void dynamic_irq_init(unsigned int irq);
+ void dynamic_irq_init_keep_chip_data(unsigned int irq);
  extern void dynamic_irq_cleanup(unsigned int irq);
+ void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
  
  /* Set/get chip/data for an IRQ: */
  extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
diff --combined init/main.c
index c75dcd6eef091061e78b306ce3944958b5b9b30d,05b5283e98fab4b5666134c1612c44bfaf36a51b..18098153c33170c782309f6275cb7f936cdcf6b0
@@@ -149,6 -149,20 +149,20 @@@ static int __init nosmp(char *str
  
  early_param("nosmp", nosmp);
  
+ /* this is hard limit */
+ static int __init nrcpus(char *str)
+ {
+       int nr_cpus;
+       get_option(&str, &nr_cpus);
+       if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
+               nr_cpu_ids = nr_cpus;
+       return 0;
+ }
+ early_param("nr_cpus", nrcpus);
  static int __init maxcpus(char *str)
  {
        get_option(&str, &setup_max_cpus);
@@@ -416,9 -430,7 +430,9 @@@ static noinline void __init_refok rest_
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
 +      rcu_read_lock();
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
 +      rcu_read_unlock();
        unlock_kernel();
  
        /*
@@@ -586,6 -598,7 +600,7 @@@ asmlinkage void __init start_kernel(voi
                local_irq_disable();
        }
        rcu_init();
+       radix_tree_init();
        /* init some links before init_ISA_irqs() */
        early_irq_init();
        init_IRQ();
        proc_caches_init();
        buffer_init();
        key_init();
-       radix_tree_init();
        security_init();
        vfs_caches_init(totalram_pages);
        signals_init();