1. 21 Jan, 2011 40 commits
    • Thomas Gleixner's avatar
      score: Use generic irq Kconfig · 2fc361bf
      Thomas Gleixner authored
      No functional change
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Acked-by: default avatarChen Liqin <liqin.chen@sunplusct.com>
      2fc361bf
    • Thomas Gleixner's avatar
      powerpc: Use generic irq Kconfig · 2604362b
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
      2604362b
    • Thomas Gleixner's avatar
      parisc: Use generic irq Kconfig · 72e73af1
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Kyle McMartin <kyle@mcmartin.ca>
      Acked-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
      72e73af1
    • Thomas Gleixner's avatar
      mn10300: Use generic irq Kconfig · b169c908
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Acked-by: default avatarDavid Howells <dhowells@redhat.com>
      b169c908
    • Thomas Gleixner's avatar
      microblaze: Use generic irq Kconfig · b6e31629
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Acked-by: default avatarMichal Simek <monstr@monstr.eu>
      b6e31629
    • Thomas Gleixner's avatar
      m68knommu: Use generic irq Kconfig · d8b19323
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Greg Ungerer <gerg@uclinux.org>
      d8b19323
    • Thomas Gleixner's avatar
      ia64: Use generic irq Kconfig · c5e66129
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Acked-by: default avatarTony Luck <tony.luck@intel.com>
      c5e66129
    • Thomas Gleixner's avatar
      frv: Use generic irq Kconfig · f39b02d6
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Acked-by: default avatarDavid Howells <dhowells@redhat.com>
      f39b02d6
    • Thomas Gleixner's avatar
      blackfin: Use generic irq Kconfig · 7b028863
      Thomas Gleixner authored
      No functional change.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Mike Frysinger <vapier@gentoo.org>
      7b028863
    • Thomas Gleixner's avatar
      alpha: Use generic irq Kconfig · e27ec649
      Thomas Gleixner authored
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Richard Henderson <rth@twiddle.net>
      e27ec649
    • Thomas Gleixner's avatar
      genirq: Remove __do_IRQ · 1c77ff22
      Thomas Gleixner authored
      All architectures are finally converted. Remove the cruft.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Richard Henderson <rth@twiddle.net>
      Cc: Mike Frysinger <vapier@gentoo.org>
      Cc: David Howells <dhowells@redhat.com>
      Cc: Tony Luck <tony.luck@intel.com>
      Cc: Greg Ungerer <gerg@uclinux.org>
      Cc: Michal Simek <monstr@monstr.eu>
      Acked-by: default avatarDavid Howells <dhowells@redhat.com>
      Cc: Kyle McMartin <kyle@mcmartin.ca>
      Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Cc: Chen Liqin <liqin.chen@sunplusct.com>
      Cc: "David S. Miller" <davem@davemloft.net>
      Cc: Chris Metcalf <cmetcalf@tilera.com>
      Cc: Jeff Dike <jdike@addtoit.com>
      1c77ff22
    • Thomas Gleixner's avatar
      m32r: Convert to generic irq Kconfig · 0e155b2c
      Thomas Gleixner authored
      Use the generic irq Kconfig. Select GENERIC_HARDIRQS_NO_DEPRECATED as
      we have converted all irq_chip functions.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      0e155b2c
    • Thomas Gleixner's avatar
      m32r: Convert usrv platform irq handling · 7a0abc7e
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      7a0abc7e
    • Thomas Gleixner's avatar
      m32r: Convert opsput_lcdpld irq chip · 9b141fa6
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      9b141fa6
    • Thomas Gleixner's avatar
      m32r: Convert opsput lanpld irq chip · 1899a493
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      1899a493
    • Thomas Gleixner's avatar
      m32r: Convert opsput pld irq chip · 22cbc938
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      22cbc938
    • Thomas Gleixner's avatar
      m32r: Convert opsput irq chip · 883c0ccd
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      883c0ccd
    • Thomas Gleixner's avatar
      m32r: Convert oaks32r irq chips · ce1104ce
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      ce1104ce
    • Thomas Gleixner's avatar
      m32r: Convert mappi3 irq chip · b82727ec
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      b82727ec
    • Thomas Gleixner's avatar
      m32r: Convert mappi2 irq chip · efa63c64
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      efa63c64
    • Thomas Gleixner's avatar
      m32r: Convert mappi irq chips · 1f12681a
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      1f12681a
    • Thomas Gleixner's avatar
      m32r: Convert m32700ut lcdpld irq chip · 37808e47
      Thomas Gleixner authored
      Convert the irq chip to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      37808e47
    • Thomas Gleixner's avatar
      m32r: Convert m32700ut lanpld irq chip · 72bd198f
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      72bd198f
    • Thomas Gleixner's avatar
      m32r: Convert m32700ut pld irq chip · 63b549b6
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      63b549b6
    • Thomas Gleixner's avatar
      m32r: Convert m32104ut irq chip · 364a9ba0
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      364a9ba0
    • Thomas Gleixner's avatar
      m32r: Convert m32104ut irq handling · 8afb53b9
      Thomas Gleixner authored
      Convert the irq chips to the new functions and use proper flow
      handlers. handle_level_irq is appropriate.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      8afb53b9
    • Thomas Gleixner's avatar
      m32r: Cleanup direct irq_desc access · 863018a7
      Thomas Gleixner authored
      The irq descriptors are already initialized by the generic
      code. Remove the redundant init code and set the irq chip with the
      proper accessor function.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Hirokazu Takata <takata@linux-m32r.org>
      Cc: Paul Mundt <lethal@linux-sh.org>
      863018a7
    • Thomas Gleixner's avatar
      cris: Use generic irq Kconfig · 30139785
      Thomas Gleixner authored
      Use the generic irq Kconfig. Select GENERIC_HARDIRQS_NO_DEPRECATED as
      we have converted all irq_chip functions. Fix the fallout in
      show_interrupts().
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Mikael Starvik <starvik@axis.com>
      30139785
    • Thomas Gleixner's avatar
      cris: Convert V32 interrupt handling · 9af7503d
      Thomas Gleixner authored
      Convert the irq chip functions and install handle_simple_irq for each
      interrupt to get rid of __do_IRQ()
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Mikael Starvik <starvik@axis.com>
      9af7503d
    • Thomas Gleixner's avatar
      cris: Convert V10 interrupt handling · f7a004ba
      Thomas Gleixner authored
      Convert the irq_chip functions and install handle_simple_irq for each
      interrupt. This converts V10 to the flow handling and lets us remove
      __do_IRQ().
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Mikael Starvik <starvik@axis.com>
      f7a004ba
    • Thomas Gleixner's avatar
      cris: Use irq handling wrapper · c84077ac
      Thomas Gleixner authored
      Use the wrapper around __do_IRQ() so we can convert V10 and V32
      seperately.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Mikael Starvik <starvik@axis.com>
      c84077ac
    • Thomas Gleixner's avatar
      h8300: Use generic irq Kconfig · 51f3f159
      Thomas Gleixner authored
      Switch to the generic irq Kconfig. h8300 has all irq chips converted
      to the new functions, so select the GENERIC_HARDIRQS_NO_DEPRECATED
      switch as well. Fixup the resulting fallout in show_interrupts().
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
      Cc: Paul Mundt <lethal@linux-sh.org>
      51f3f159
    • Thomas Gleixner's avatar
      h8300: Convert interrupt handling to flow handler · f9f91ef5
      Thomas Gleixner authored
      __do_IRQ is deprecated so h8300 needs to be converted to proper flow
      handling. The irq chip is simple and does not required any
      mask/ack/eoi functions, so we can use handle_simple_irq.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
      Cc: Paul Mundt <lethal@linux-sh.org>
      f9f91ef5
    • Thomas Gleixner's avatar
      h8300: Convert to new irq_chip functions · 12174aac
      Thomas Gleixner authored
      No functional change, just straight forward conversion.
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
      Cc: Paul Mundt <lethal@linux-sh.org>
      12174aac
    • Linus Torvalds's avatar
      Merge branch 'core-fixes-for-linus' of... · 2b1caf6e
      Linus Torvalds authored
      Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
      
      * 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
        smp: Allow on_each_cpu() to be called while early_boot_irqs_disabled status to init/main.c
        lockdep: Move early boot local IRQ enable/disable status to init/main.c
      2b1caf6e
    • Rafael J. Wysocki's avatar
      ACPI / PM: Call suspend_nvs_free() earlier during resume · d551d81d
      Rafael J. Wysocki authored
      It turns out that some device drivers map pages from the ACPI NVS region
      during resume using ioremap(), which conflicts with ioremap_cache() used
      for mapping those pages by the NVS save/restore code in nvs.c.
      
      Make the NVS pages mapped by the code in nvs.c be unmapped before device
      drivers' resume routines run.
      Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      d551d81d
    • Rafael J. Wysocki's avatar
      ACPI: Introduce acpi_os_ioremap() · 2d6d9fd3
      Rafael J. Wysocki authored
      Commit ca9b600b ("ACPI / PM: Make suspend_nvs_save() use
      acpi_os_map_memory()") attempted to prevent the code in osl.c and nvs.c
      from using different ioremap() variants by making the latter use
      acpi_os_map_memory() for mapping the NVS pages.  However, that also
      requires acpi_os_unmap_memory() to be used for unmapping them, which
      causes synchronize_rcu() to be executed many times in a row
      unnecessarily and introduces substantial delays during resume on some
      systems.
      
      Instead of using acpi_os_map_memory() for mapping the NVS pages in nvs.c
      introduce acpi_os_ioremap() calling ioremap_cache() and make the code in
      both osl.c and nvs.c use it.
      Reported-by: default avatarJeff Chua <jeff.chua.linux@gmail.com>
      Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      2d6d9fd3
    • Linus Torvalds's avatar
      Merge branch 'akpm' · 8d99641f
      Linus Torvalds authored
      * akpm:
        kernel/smp.c: consolidate writes in smp_call_function_interrupt()
        kernel/smp.c: fix smp_call_function_many() SMP race
        memcg: correctly order reading PCG_USED and pc->mem_cgroup
        backlight: fix 88pm860x_bl macro collision
        drivers/leds/ledtrig-gpio.c: make output match input, tighten input checking
        MAINTAINERS: update Atmel AT91 entry
        mm: fix truncate_setsize() comment
        memcg: fix rmdir, force_empty with THP
        memcg: fix LRU accounting with THP
        memcg: fix USED bit handling at uncharge in THP
        memcg: modify accounting function for supporting THP better
        fs/direct-io.c: don't try to allocate more than BIO_MAX_PAGES in a bio
        mm: compaction: prevent division-by-zero during user-requested compaction
        mm/vmscan.c: remove duplicate include of compaction.h
        memblock: fix memblock_is_region_memory()
        thp: keep highpte mapped until it is no longer needed
        kconfig: rename CONFIG_EMBEDDED to CONFIG_EXPERT
      8d99641f
    • Milton Miller's avatar
      kernel/smp.c: consolidate writes in smp_call_function_interrupt() · 225c8e01
      Milton Miller authored
      We have to test the cpu mask in the interrupt handler before checking the
      refs, otherwise we can start to follow an entry before its deleted and
      find it partially initailzed for the next trip.  Presently we also clear
      the cpumask bit before executing the called function, which implies
      getting write access to the line.  After the function is called we then
      decrement refs, and if they go to zero we then unlock the structure.
      
      However, this implies getting write access to the call function data
      before and after another the function is called.  If we can assert that no
      smp_call_function execution function is allowed to enable interrupts, then
      we can move both writes to after the function is called, hopfully allowing
      both writes with one cache line bounce.
      
      On a 256 thread system with a kernel compiled for 1024 threads, the time
      to execute testcase in the "smp_call_function_many race" changelog was
      reduced by about 30-40ms out of about 545 ms.
      
      I decided to keep this as WARN because its now a buggy function, even
      though the stack trace is of no value -- a simple printk would give us the
      information needed.
      
      Raw data:
      
      Without patch:
        ipi_test startup took 1219366ns complete 539819014ns total 541038380ns
        ipi_test startup took 1695754ns complete 543439872ns total 545135626ns
        ipi_test startup took 7513568ns complete 539606362ns total 547119930ns
        ipi_test startup took 13304064ns complete 533898562ns total 547202626ns
        ipi_test startup took 8668192ns complete 544264074ns total 552932266ns
        ipi_test startup took 4977626ns complete 548862684ns total 553840310ns
        ipi_test startup took 2144486ns complete 541292318ns total 543436804ns
        ipi_test startup took 21245824ns complete 530280180ns total 551526004ns
      
      With patch:
        ipi_test startup took 5961748ns complete 500859628ns total 506821376ns
        ipi_test startup took 8975996ns complete 495098924ns total 504074920ns
        ipi_test startup took 19797750ns complete 492204740ns total 512002490ns
        ipi_test startup took 14824796ns complete 487495878ns total 502320674ns
        ipi_test startup took 11514882ns complete 494439372ns total 505954254ns
        ipi_test startup took 8288084ns complete 502570774ns total 510858858ns
        ipi_test startup took 6789954ns complete 493388112ns total 500178066ns
      
      	#include <linux/module.h>
      	#include <linux/init.h>
      	#include <linux/sched.h> /* sched clock */
      
      	#define ITERATIONS 100
      
      	static void do_nothing_ipi(void *dummy)
      	{
      	}
      
      	static void do_ipis(struct work_struct *dummy)
      	{
      		int i;
      
      		for (i = 0; i < ITERATIONS; i++)
      			smp_call_function(do_nothing_ipi, NULL, 1);
      
      		printk(KERN_DEBUG "cpu %d finished\n", smp_processor_id());
      	}
      
      	static struct work_struct work[NR_CPUS];
      
      	static int __init testcase_init(void)
      	{
      		int cpu;
      		u64 start, started, done;
      
      		start = local_clock();
      		for_each_online_cpu(cpu) {
      			INIT_WORK(&work[cpu], do_ipis);
      			schedule_work_on(cpu, &work[cpu]);
      		}
      		started = local_clock();
      		for_each_online_cpu(cpu)
      			flush_work(&work[cpu]);
      		done = local_clock();
      		pr_info("ipi_test startup took %lldns complete %lldns total %lldns\n",
      			started-start, done-started, done-start);
      
      		return 0;
      	}
      
      	static void __exit testcase_exit(void)
      	{
      	}
      
      	module_init(testcase_init)
      	module_exit(testcase_exit)
      	MODULE_LICENSE("GPL");
      	MODULE_AUTHOR("Anton Blanchard");
      Signed-off-by: default avatarMilton Miller <miltonm@bga.com>
      Cc: Anton Blanchard <anton@samba.org>
      Cc: Ingo Molnar <mingo@elte.hu>
      Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      225c8e01
    • Anton Blanchard's avatar
      kernel/smp.c: fix smp_call_function_many() SMP race · 6dc19899
      Anton Blanchard authored
      I noticed a failure where we hit the following WARN_ON in
      generic_smp_call_function_interrupt:
      
                      if (!cpumask_test_and_clear_cpu(cpu, data->cpumask))
                              continue;
      
                      data->csd.func(data->csd.info);
      
                      refs = atomic_dec_return(&data->refs);
                      WARN_ON(refs < 0);      <-------------------------
      
      We atomically tested and cleared our bit in the cpumask, and yet the
      number of cpus left (ie refs) was 0.  How can this be?
      
      It turns out commit 54fdade1
      ("generic-ipi: make struct call_function_data lockless") is at fault.  It
      removes locking from smp_call_function_many and in doing so creates a
      rather complicated race.
      
      The problem comes about because:
      
       - The smp_call_function_many interrupt handler walks call_function.queue
         without any locking.
       - We reuse a percpu data structure in smp_call_function_many.
       - We do not wait for any RCU grace period before starting the next
         smp_call_function_many.
      
      Imagine a scenario where CPU A does two smp_call_functions back to back,
      and CPU B does an smp_call_function in between.  We concentrate on how CPU
      C handles the calls:
      
      CPU A            CPU B                  CPU C              CPU D
      
      smp_call_function
                                              smp_call_function_interrupt
                                                  walks
      					call_function.queue sees
      					data from CPU A on list
      
                       smp_call_function
      
                                              smp_call_function_interrupt
                                                  walks
      
                                              call_function.queue sees
                                                (stale) CPU A on list
      							   smp_call_function int
      							   clears last ref on A
      							   list_del_rcu, unlock
      smp_call_function reuses
      percpu *data A
                                               data->cpumask sees and
                                               clears bit in cpumask
                                               might be using old or new fn!
                                               decrements refs below 0
      
      set data->refs (too late!)
      
      The important thing to note is since the interrupt handler walks a
      potentially stale call_function.queue without any locking, then another
      cpu can view the percpu *data structure at any time, even when the owner
      is in the process of initialising it.
      
      The following test case hits the WARN_ON 100% of the time on my PowerPC
      box (having 128 threads does help :)
      
      #include <linux/module.h>
      #include <linux/init.h>
      
      #define ITERATIONS 100
      
      static void do_nothing_ipi(void *dummy)
      {
      }
      
      static void do_ipis(struct work_struct *dummy)
      {
      	int i;
      
      	for (i = 0; i < ITERATIONS; i++)
      		smp_call_function(do_nothing_ipi, NULL, 1);
      
      	printk(KERN_DEBUG "cpu %d finished\n", smp_processor_id());
      }
      
      static struct work_struct work[NR_CPUS];
      
      static int __init testcase_init(void)
      {
      	int cpu;
      
      	for_each_online_cpu(cpu) {
      		INIT_WORK(&work[cpu], do_ipis);
      		schedule_work_on(cpu, &work[cpu]);
      	}
      
      	return 0;
      }
      
      static void __exit testcase_exit(void)
      {
      }
      
      module_init(testcase_init)
      module_exit(testcase_exit)
      MODULE_LICENSE("GPL");
      MODULE_AUTHOR("Anton Blanchard");
      
      I tried to fix it by ordering the read and the write of ->cpumask and
      ->refs.  In doing so I missed a critical case but Paul McKenney was able
      to spot my bug thankfully :) To ensure we arent viewing previous
      iterations the interrupt handler needs to read ->refs then ->cpumask then
      ->refs _again_.
      
      Thanks to Milton Miller and Paul McKenney for helping to debug this issue.
      
      [miltonm@bga.com: add WARN_ON and BUG_ON, remove extra read of refs before initial read of mask that doesn't help (also noted by Peter Zijlstra), adjust comments, hopefully clarify scenario ]
      [miltonm@bga.com: remove excess tests]
      Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
      Signed-off-by: default avatarMilton Miller <miltonm@bga.com>
      Cc: Ingo Molnar <mingo@elte.hu>
      Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
      Cc: <stable@kernel.org> [2.6.32+]
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      6dc19899