Merge branch 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 23:06:50 +0000 (16:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 26 Mar 2009 23:06:50 +0000 (16:06 -0700)
* 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (32 commits)
  x86: disable __do_IRQ support
  sparseirq, powerpc/cell: fix unused variable warning in interrupt.c
  genirq: deprecate obsolete typedefs and defines
  genirq: deprecate __do_IRQ
  genirq: add doc to struct irqaction
  genirq: use kzalloc instead of explicit zero initialization
  genirq: make irqreturn_t an enum
  genirq: remove redundant if condition
  genirq: remove unused hw_irq_controller typedef
  irq: export remove_irq() and setup_irq() symbols
  irq: match remove_irq() args with setup_irq()
  irq: add remove_irq() for freeing of setup_irq() irqs
  genirq: assert that irq handlers are indeed running in hardirq context
  irq: name 'p' variables a bit better
  irq: further clean up the free_irq() code flow
  irq: refactor and clean up the free_irq() code flow
  irq: clean up manage.c
  irq: use GFP_KERNEL for action allocation in request_irq()
  kernel/irq: fix sparse warning: make symbol static
  irq: optimize init_kstat_irqs/init_copy_kstat_irqs
  ...

37 files changed:
Documentation/DocBook/genericirq.tmpl
Documentation/feature-removal-schedule.txt
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/arm/kernel/irq.c
arch/arm/mach-ns9xxx/irq.c
arch/avr32/kernel/irq.c
arch/blackfin/kernel/irqchip.c
arch/cris/kernel/irq.c
arch/frv/kernel/irq.c
arch/h8300/kernel/irq.c
arch/ia64/kernel/irq.c
arch/m32r/kernel/irq.c
arch/mips/kernel/irq.c
arch/mn10300/kernel/irq.c
arch/parisc/kernel/irq.c
arch/powerpc/kernel/irq.c
arch/powerpc/platforms/cell/interrupt.c
arch/sh/kernel/irq.c
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/time_64.c
arch/um/kernel/irq.c
arch/x86/Kconfig
arch/xtensa/kernel/irq.c
drivers/char/random.c
drivers/pci/intr_remapping.c
include/linux/interrupt.h
include/linux/irq.h
include/linux/irqnr.h
include/linux/irqreturn.h
include/linux/kernel_stat.h
kernel/irq/chip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/numa_migrate.c
kernel/irq/spurious.c

index 3a882d9a90a9134317799a2b0357b53e3dcdb8fd..c671a01680965f5008ddc87b67c1049b3e519cbd 100644 (file)
@@ -440,6 +440,7 @@ desc->chip->end();
      used in the generic IRQ layer.
      </para>
 !Iinclude/linux/irq.h
+!Iinclude/linux/interrupt.h
   </chapter>
 
   <chapter id="pubfunctions">
index 802c6fd20c635b26aa87d997a56a4d44ad095aa7..e47c0ff8ba7aaf59d8d6fa8776ab331b9c5c25b6 100644 (file)
@@ -346,3 +346,20 @@ Why:       See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
        Removal is subject to fixing any remaining bugs in ACPI which may
        cause the thermal throttling not to happen at the right time.
 Who:   Dave Jones <davej@redhat.com>, Matthew Garrett <mjg@redhat.com>
+
+-----------------------------
+
+What:  __do_IRQ all in one fits nothing interrupt handler
+When:  2.6.32
+Why:   __do_IRQ was kept for easy migration to the type flow handlers.
+       More than two years of migration time is enough.
+Who:   Thomas Gleixner <tglx@linutronix.de>
+
+-----------------------------
+
+What:  obsolete generic irq defines and typedefs
+When:  2.6.30
+Why:   The defines and typedefs (hw_interrupt_type, no_irq_type, irq_desc_t)
+       have been kept around for migration reasons. After more than two years
+       it's time to remove them finally
+Who:   Thomas Gleixner <tglx@linutronix.de>
index 703731accda6d515e6879afe276e68818eaddd4b..d3812eb84015bcf5f9d573d1db382fb2d04e3fbf 100644 (file)
@@ -90,7 +90,7 @@ show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(irq));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[irq]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
 #endif
                seq_printf(p, " %14s", irq_desc[irq].chip->typename);
                seq_printf(p, "  %c%s",
index e16aeb6e79ef8cd62955f27d7fd623cacfd79cca..67c19f8a9944804ad9ef3cd2ca56de73fc9c97fc 100644 (file)
@@ -64,7 +64,7 @@ do_entInt(unsigned long type, unsigned long vector,
                smp_percpu_timer_interrupt(regs);
                cpu = smp_processor_id();
                if (cpu != boot_cpuid) {
-                       kstat_cpu(cpu).irqs[RTC_IRQ]++;
+                       kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ));
                } else {
                        handle_irq(RTC_IRQ);
                }
index 363db186cb93334791588db5b2158e6f295c5c54..7296f041628663f2c88258b90f2e411d99d3a4aa 100644 (file)
@@ -76,7 +76,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
                seq_printf(p, "%3d: ", i);
                for_each_present_cpu(cpu)
-                       seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
                seq_printf(p, "  %s", action->name);
                for (action = action->next; action; action = action->next)
index 22e0eb6e9ec405416dd88d18ba0787794c2619fc..feb0e54a91de6de4c27c5210d2a1b5bc9ff39da8 100644 (file)
@@ -63,7 +63,6 @@ static struct irq_chip ns9xxx_chip = {
 #else
 static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int cpu = smp_processor_id();
        struct irqaction *action;
        irqreturn_t action_ret;
 
@@ -72,7 +71,7 @@ static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
        BUG_ON(desc->status & IRQ_INPROGRESS);
 
        desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-       kstat_cpu(cpu).irqs[irq]++;
+       kstat_incr_irqs_this_cpu(irq, desc);
 
        action = desc->action;
        if (unlikely(!action || (desc->status & IRQ_DISABLED)))
index a8e767d836aac621c0c449406e32d06b0d13d2db..9f572229d3183752e0c602ef9106b94617fd99ea 100644 (file)
@@ -58,7 +58,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
                seq_printf(p, "%3d: ", i);
                for_each_online_cpu(cpu)
-                       seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
                seq_printf(p, "  %s", action->name);
                for (action = action->next; action; action = action->next)
index 7fd12656484666ee4c29784a1d2d1e0e4e5fee04..bd052a67032e467bfef3a4aa30eb6dd1b4bc02e7 100644 (file)
@@ -83,7 +83,7 @@ int show_interrupts(struct seq_file *p, void *v)
                        goto skip;
                seq_printf(p, "%3d: ", i);
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
                seq_printf(p, " %8s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
                for (action = action->next; action; action = action->next)
index 2dfac8c79090a248291375e8ed3f392878530ca8..7f642fcffbfc912cdda5ceb81f03d657bac4d1f6 100644 (file)
@@ -66,7 +66,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->typename);
                seq_printf(p, "  %s", action->name);
index 73abae767fdc8a089c468372ba7ae499a21f65f2..af3e824b91b3027afb72a0fa9f455150d3599421 100644 (file)
@@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (action) {
                        seq_printf(p, "%3d: ", i);
                        for_each_present_cpu(cpu)
-                               seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+                               seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                        seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
                        seq_printf(p, "  %s", action->name);
                        for (action = action->next;
index ef4f0047067d309663f116cd537a5f04d635786a..74f8dd7b34d2f4be2d44f1922bda2760e200597c 100644 (file)
@@ -183,7 +183,7 @@ asmlinkage void do_IRQ(int irq)
 #if defined(CONFIG_PROC_FS)
 int show_interrupts(struct seq_file *p, void *v)
 {
-       int i = *(loff_t *) v, j;
+       int i = *(loff_t *) v;
        struct irqaction * action;
        unsigned long flags;
 
@@ -196,7 +196,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (!action)
                        goto unlock;
                seq_printf(p, "%3d: ",i);
-               seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+               seq_printf(p, "%10u ", kstat_irqs(i));
                seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "-%-8s", irq_desc[i].name);
                seq_printf(p, "  %s", action->name);
index a58f64ca9f0e9931476ffd4f8460f95ec4200fad..4f596613bffd86ad842d781b1143928782465a09 100644 (file)
@@ -80,7 +80,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j) {
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
                }
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->name);
index 2aeae4670098245f7072ca69b4e732955e4d25d5..8dfd31e87c4c884d2937d7259bd04f637cef0b11 100644 (file)
@@ -49,7 +49,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->typename);
                seq_printf(p, "  %s", action->name);
index 4b4007b3083a8f881cef80371e68a2a688c55f32..7b845ba9dff4cf565394393dbb1e24f497e5aed4 100644 (file)
@@ -108,7 +108,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "  %s", action->name);
index 56c64ccc9c21cd2ee530baab8f0b7fcfbea5ce7c..50fdb5c16e0c34368e4faad479d041b4b4362eb9 100644 (file)
@@ -221,7 +221,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (action) {
                        seq_printf(p, "%3d: ", i);
                        for_each_present_cpu(cpu)
-                               seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+                               seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                        seq_printf(p, " %14s.%u", irq_desc[i].chip->name,
                                   (GxICR(i) & GxICR_LEVEL) >>
                                   GxICR_LEVEL_SHIFT);
index 29e70e16ede8feaa9672f270c13bdf04aadd174a..adfd617b4c18c66dfdfca0202b6a960157f4bf73 100644 (file)
@@ -185,7 +185,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #else
                seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
index 23b8b5e36f98b9afb5cf970e20b4a77ab5785627..17efb7118db1140296bf8fa447b1b1133867c398 100644 (file)
@@ -190,7 +190,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #else
                seq_printf(p, "%10u ", kstat_irqs(i));
 #endif /* CONFIG_SMP */
index 28c04dab263350110055b2883a916355c39deba6..882e47080e74f493523399a0b1e7703c09b7b999 100644 (file)
@@ -237,8 +237,6 @@ extern int noirqdebug;
 
 static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
 {
-       const unsigned int cpu = smp_processor_id();
-
        spin_lock(&desc->lock);
 
        desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
@@ -254,7 +252,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
                goto out_eoi;
        }
 
-       kstat_cpu(cpu).irqs[irq]++;
+       kstat_incr_irqs_this_cpu(irq, desc);
 
        /* Mark the IRQ currently in progress.*/
        desc->status |= IRQ_INPROGRESS;
index 90d63aefd2755907d66932d42e4ac30629d277b5..3f1372eb0091f69ab93fb0912a3162c143d164f5 100644 (file)
@@ -51,7 +51,7 @@ int show_interrupts(struct seq_file *p, void *v)
                        goto unlock;
                seq_printf(p, "%3d: ",i);
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
                seq_printf(p, " %14s", irq_desc[i].chip->name);
                seq_printf(p, "-%-8s", irq_desc[i].name);
                seq_printf(p, "  %s", action->name);
index 1c378d8e90c588ce722a9d6abfb935f5cb6e62d9..8ba064f08a6fbdd31bed882e1137ff924bd6a350 100644 (file)
@@ -185,7 +185,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %9s", irq_desc[i].chip->typename);
                seq_printf(p, "  %s", action->name);
index 2db3c2229b95ca39870fef29c01677ff39dc7c2d..642562d83ec44603dddfbc6276fcb7a2e52a211d 100644 (file)
 #include <linux/clocksource.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/irq.h>
 
 #include <asm/oplib.h>
 #include <asm/timer.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/starfire.h>
index 3d7aad09b171cfeca9fdc0a132ccf86f3d6a71f9..336b61569072be6958ccb74c22e6c87abbb7c9b2 100644 (file)
@@ -42,7 +42,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->typename);
                seq_printf(p, "  %s", action->name);
index bc2fbadff9f90fe681d9c30ae621d1ec94e348cf..3a330a437c6f9d55b44a0545b306242b6f55edba 100644 (file)
@@ -165,6 +165,9 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
+
 config GENERIC_IRQ_PROBE
        bool
        default y
index 5fbcde59a92d919507505e0605a7faf08f02a2d1..f3b66fba5b8f71f0f45700601b9117dd865ae9b9 100644 (file)
@@ -99,7 +99,7 @@ int show_interrupts(struct seq_file *p, void *v)
                seq_printf(p, "%10u ", kstat_irqs(i));
 #else
                for_each_online_cpu(j)
-                       seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+                       seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
                seq_printf(p, " %14s", irq_desc[i].chip->typename);
                seq_printf(p, "  %s", action->name);
index 7c13581ca9cd6ac1ea4a2d54e80397831cebd75f..7c43ae782b26e385e1b0c96efacd7e82846b794b 100644 (file)
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+# include <linux/irq.h>
+#endif
+
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
@@ -558,7 +562,7 @@ struct timer_rand_state {
        unsigned dont_count_entropy:1;
 };
 
-#ifndef CONFIG_SPARSE_IRQ
+#ifndef CONFIG_GENERIC_HARDIRQS
 
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
 
index 45effc5726c0f63a55862c85eaa6d9cb4a38c706..b721c2fbe8f5005c871874cd39c90c5f03ab4d40 100644 (file)
@@ -20,7 +20,7 @@ struct irq_2_iommu {
        u8  irte_mask;
 };
 
-#ifdef CONFIG_SPARSE_IRQ
+#ifdef CONFIG_GENERIC_HARDIRQS
 static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
 {
        struct irq_2_iommu *iommu;
index 9127f6b51a39a0fac962030a1cedde2cdadd13b7..91658d0765982c04ee79e665411c82a17de10cb7 100644 (file)
 
 typedef irqreturn_t (*irq_handler_t)(int, void *);
 
+/**
+ * struct irqaction - per interrupt action descriptor
+ * @handler:   interrupt handler function
+ * @flags:     flags (see IRQF_* above)
+ * @mask:      no comment as it is useless and about to be removed
+ * @name:      name of the device
+ * @dev_id:    cookie to identify the device
+ * @next:      pointer to the next irqaction for shared interrupts
+ * @irq:       interrupt number
+ * @dir:       pointer to the proc/irq/NN/name entry
+ */
 struct irqaction {
        irq_handler_t handler;
        unsigned long flags;
@@ -462,6 +473,12 @@ static inline void init_irq_proc(void)
 }
 #endif
 
+#if defined(CONFIG_GENERIC_HARDIRQS) && defined(CONFIG_DEBUG_SHIRQ)
+extern void debug_poll_all_shared_irqs(void);
+#else
+static inline void debug_poll_all_shared_irqs(void) { }
+#endif
+
 int show_interrupts(struct seq_file *p, void *v);
 
 struct irq_desc;
index f899b502f18622dce2c509aac5c656ef8150216f..6db939a575bd4780fe39bb5a91ff7fa3bac08757 100644 (file)
@@ -160,12 +160,10 @@ struct irq_2_iommu;
  */
 struct irq_desc {
        unsigned int            irq;
-#ifdef CONFIG_SPARSE_IRQ
        struct timer_rand_state *timer_rand_state;
        unsigned int            *kstat_irqs;
-# ifdef CONFIG_INTR_REMAP
+#ifdef CONFIG_INTR_REMAP
        struct irq_2_iommu      *irq_2_iommu;
-# endif
 #endif
        irq_flow_handler_t      handle_irq;
        struct irq_chip         *chip;
@@ -202,12 +200,6 @@ extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc
 extern struct irq_desc irq_desc[NR_IRQS];
 #else /* CONFIG_SPARSE_IRQ */
 extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
-
-#define kstat_irqs_this_cpu(DESC) \
-       ((DESC)->kstat_irqs[smp_processor_id()])
-#define kstat_incr_irqs_this_cpu(irqno, DESC) \
-       ((DESC)->kstat_irqs[smp_processor_id()]++)
-
 #endif /* CONFIG_SPARSE_IRQ */
 
 extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
@@ -226,7 +218,6 @@ irq_remap_to_desc(unsigned int irq, struct irq_desc *desc)
  * Migration helpers for obsolete names, they will go away:
  */
 #define hw_interrupt_type      irq_chip
-typedef struct irq_chip                hw_irq_controller;
 #define no_irq_type            no_irq_chip
 typedef struct irq_desc                irq_desc_t;
 
@@ -236,6 +227,7 @@ typedef struct irq_desc             irq_desc_t;
 #include <asm/hw_irq.h>
 
 extern int setup_irq(unsigned int irq, struct irqaction *new);
+extern void remove_irq(unsigned int irq, struct irqaction *act);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
@@ -280,7 +272,7 @@ static inline int irq_balancing_disabled(unsigned int irq)
 }
 
 /* Handle irq action chains: */
-extern int handle_IRQ_event(unsigned int irq, struct irqaction *action);
+extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
 /*
  * Built-in IRQ handlers for various IRQ types,
@@ -325,7 +317,7 @@ static inline void generic_handle_irq(unsigned int irq)
 
 /* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
-                          int action_ret);
+                          irqreturn_t action_ret);
 
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
index 86af92e9e84c0e3115845bcd3abbc125d28b5088..52ebbb4b161d46372ad3c53be48b2e14cf61811a 100644 (file)
@@ -28,13 +28,17 @@ extern struct irq_desc *irq_to_desc(unsigned int irq);
 # define for_each_irq_desc(irq, desc)                                  \
        for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs;           \
             irq++, desc = irq_to_desc(irq))                            \
-               if (desc)
+               if (!desc)                                              \
+                       ;                                               \
+               else
 
 
 # define for_each_irq_desc_reverse(irq, desc)                          \
        for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0;      \
             irq--, desc = irq_to_desc(irq))                            \
-               if (desc)
+               if (!desc)                                              \
+                       ;                                               \
+               else
 
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
index 881883c2009dfe0b2100697d9bc15ed2d344765f..c5584ca5b8c94e07ecc9340eb14255bd52606915 100644 (file)
@@ -1,25 +1,17 @@
-/* irqreturn.h */
 #ifndef _LINUX_IRQRETURN_H
 #define _LINUX_IRQRETURN_H
 
-/*
- * For 2.4.x compatibility, 2.4.x can use
- *
- *     typedef void irqreturn_t;
- *     #define IRQ_NONE
- *     #define IRQ_HANDLED
- *     #define IRQ_RETVAL(x)
- *
- * To mix old-style and new-style irq handler returns.
- *
- * IRQ_NONE means we didn't handle it.
- * IRQ_HANDLED means that we did have a valid interrupt and handled it.
- * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)
+/**
+ * enum irqreturn
+ * @IRQ_NONE           interrupt was not from this device
+ * @IRQ_HANDLED                interrupt was handled by this device
  */
-typedef int irqreturn_t;
+enum irqreturn {
+       IRQ_NONE,
+       IRQ_HANDLED,
+};
 
-#define IRQ_NONE       (0)
-#define IRQ_HANDLED    (1)
-#define IRQ_RETVAL(x)  ((x) != 0)
+typedef enum irqreturn irqreturn_t;
+#define IRQ_RETVAL(x)  ((x) != IRQ_NONE)
 
 #endif
index 570d2041311911352da76c830073f7c9aa314457..0c8b89f28a95eeccc1956c132777621bacf4d4c5 100644 (file)
@@ -28,7 +28,7 @@ struct cpu_usage_stat {
 
 struct kernel_stat {
        struct cpu_usage_stat   cpustat;
-#ifndef CONFIG_SPARSE_IRQ
+#ifndef CONFIG_GENERIC_HARDIRQS
        unsigned int irqs[NR_IRQS];
 #endif
 };
@@ -41,7 +41,7 @@ DECLARE_PER_CPU(struct kernel_stat, kstat);
 
 extern unsigned long long nr_context_switches(void);
 
-#ifndef CONFIG_SPARSE_IRQ
+#ifndef CONFIG_GENERIC_HARDIRQS
 #define kstat_irqs_this_cpu(irq) \
        (kstat_this_cpu.irqs[irq])
 
@@ -52,16 +52,19 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
 {
        kstat_this_cpu.irqs[irq]++;
 }
-#endif
-
 
-#ifndef CONFIG_SPARSE_IRQ
 static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
        return kstat_cpu(cpu).irqs[irq];
 }
 #else
+#include <linux/irq.h>
 extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu);
+#define kstat_irqs_this_cpu(DESC) \
+       ((DESC)->kstat_irqs[smp_processor_id()])
+#define kstat_incr_irqs_this_cpu(irqno, DESC) \
+       ((DESC)->kstat_irqs[smp_processor_id()]++)
+
 #endif
 
 /*
index 7de11bd64dfe33a2fa8c1091a308ed58b685d0c7..03d0bed2b8d925492a16e84951772330fccdcbd8 100644 (file)
@@ -78,6 +78,7 @@ void dynamic_irq_cleanup(unsigned int irq)
        desc->handle_irq = handle_bad_irq;
        desc->chip = &no_irq_chip;
        desc->name = NULL;
+       clear_kstat_irqs(desc);
        spin_unlock_irqrestore(&desc->lock, flags);
 }
 
@@ -290,7 +291,8 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq)
                desc->chip->mask_ack(irq);
        else {
                desc->chip->mask(irq);
-               desc->chip->ack(irq);
+               if (desc->chip->ack)
+                       desc->chip->ack(irq);
        }
 }
 
@@ -476,7 +478,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
        kstat_incr_irqs_this_cpu(irq, desc);
 
        /* Start handling the irq */
-       desc->chip->ack(irq);
+       if (desc->chip->ack)
+               desc->chip->ack(irq);
        desc = irq_remap_to_desc(irq, desc);
 
        /* Mark the IRQ currently in progress.*/
index 3aba8d12f328ec91e59f5c72217ceb0c0d2fd0a1..f6cdda68e5c6c04b4c0da4626db67d05a78af3b0 100644 (file)
@@ -83,19 +83,21 @@ static struct irq_desc irq_desc_init = {
 
 void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
 {
-       unsigned long bytes;
-       char *ptr;
        int node;
-
-       /* Compute how many bytes we need per irq and allocate them */
-       bytes = nr * sizeof(unsigned int);
+       void *ptr;
 
        node = cpu_to_node(cpu);
-       ptr = kzalloc_node(bytes, GFP_ATOMIC, node);
-       printk(KERN_DEBUG "  alloc kstat_irqs on cpu %d node %d\n", cpu, node);
+       ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node);
 
-       if (ptr)
-               desc->kstat_irqs = (unsigned int *)ptr;
+       /*
+        * don't overwite if can not get new one
+        * init_copy_kstat_irqs() could still use old one
+        */
+       if (ptr) {
+               printk(KERN_DEBUG "  alloc kstat_irqs on cpu %d node %d\n",
+                        cpu, node);
+               desc->kstat_irqs = ptr;
+       }
 }
 
 static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
@@ -227,6 +229,7 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
        }
 };
 
+static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
 int __init early_irq_init(void)
 {
        struct irq_desc *desc;
@@ -238,8 +241,10 @@ int __init early_irq_init(void)
        desc = irq_desc;
        count = ARRAY_SIZE(irq_desc);
 
-       for (i = 0; i < count; i++)
+       for (i = 0; i < count; i++) {
                desc[i].irq = i;
+               desc[i].kstat_irqs = kstat_irqs_all[i];
+       }
 
        return arch_early_irq_init();
 }
@@ -255,6 +260,11 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
 }
 #endif /* !CONFIG_SPARSE_IRQ */
 
+void clear_kstat_irqs(struct irq_desc *desc)
+{
+       memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
+}
+
 /*
  * What should we do if we get a hw irq event on an illegal vector?
  * Each architecture has to answer this themself.
@@ -328,6 +338,8 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
        irqreturn_t ret, retval = IRQ_NONE;
        unsigned int status = 0;
 
+       WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!");
+
        if (!(action->flags & IRQF_DISABLED))
                local_irq_enable_in_hardirq();
 
@@ -347,6 +359,11 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 }
 
 #ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
+
+#ifdef CONFIG_ENABLE_WARN_DEPRECATED
+# warning __do_IRQ is deprecated. Please convert to proper flow handlers
+#endif
+
 /**
  * __do_IRQ - original all in one highlevel IRQ handler
  * @irq:       the interrupt number
@@ -467,12 +484,10 @@ void early_init_irq_lock_class(void)
        }
 }
 
-#ifdef CONFIG_SPARSE_IRQ
 unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        return desc ? desc->kstat_irqs[cpu] : 0;
 }
-#endif
 EXPORT_SYMBOL(kstat_irqs_cpu);
 
index e6d0a43cc1255c2abb3778fcec5f5b1d4e5290ec..b60950bf5a16fb57286d95515bb0ceaa2022410a 100644 (file)
@@ -15,6 +15,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 
 extern struct lock_class_key irq_desc_lock_class;
 extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
+extern void clear_kstat_irqs(struct irq_desc *desc);
 extern spinlock_t sparse_irq_lock;
 extern struct irq_desc *irq_desc_ptrs[NR_IRQS];
 
index 291f03664552387658690f947b1d3a4d9562dcc6..ea119effe096b47628c2b8061c2e76e8fcfb5d43 100644 (file)
@@ -109,7 +109,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 /*
  * Generic version of the affinity autoselector.
  */
-int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc)
+static int setup_affinity(unsigned int irq, struct irq_desc *desc)
 {
        if (!irq_can_set_affinity(irq))
                return 0;
@@ -133,7 +133,7 @@ set_affinity:
        return 0;
 }
 #else
-static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d)
+static inline int setup_affinity(unsigned int irq, struct irq_desc *d)
 {
        return irq_select_affinity(irq);
 }
@@ -149,14 +149,14 @@ int irq_select_affinity_usr(unsigned int irq)
        int ret;
 
        spin_lock_irqsave(&desc->lock, flags);
-       ret = do_irq_select_affinity(irq, desc);
+       ret = setup_affinity(irq, desc);
        spin_unlock_irqrestore(&desc->lock, flags);
 
        return ret;
 }
 
 #else
-static inline int do_irq_select_affinity(int irq, struct irq_desc *desc)
+static inline int setup_affinity(unsigned int irq, struct irq_desc *desc)
 {
        return 0;
 }
@@ -389,9 +389,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
  * allocate special interrupts that are part of the architecture.
  */
 static int
-__setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
+__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 {
-       struct irqaction *old, **p;
+       struct irqaction *old, **old_ptr;
        const char *old_name = NULL;
        unsigned long flags;
        int shared = 0;
@@ -423,8 +423,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
         * The following block of code has to be executed atomically
         */
        spin_lock_irqsave(&desc->lock, flags);
-       p = &desc->action;
-       old = *p;
+       old_ptr = &desc->action;
+       old = *old_ptr;
        if (old) {
                /*
                 * Can't share interrupts unless both agree to and are
@@ -447,8 +447,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
 
                /* add new interrupt at end of irq queue */
                do {
-                       p = &old->next;
-                       old = *p;
+                       old_ptr = &old->next;
+                       old = *old_ptr;
                } while (old);
                shared = 1;
        }
@@ -488,7 +488,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
                        desc->status |= IRQ_NO_BALANCING;
 
                /* Set default affinity mask once everything is setup */
-               do_irq_select_affinity(irq, desc);
+               setup_affinity(irq, desc);
 
        } else if ((new->flags & IRQF_TRIGGER_MASK)
                        && (new->flags & IRQF_TRIGGER_MASK)
@@ -499,7 +499,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
                                (int)(new->flags & IRQF_TRIGGER_MASK));
        }
 
-       *p = new;
+       *old_ptr = new;
 
        /* Reset broken irq detection when installing new handler */
        desc->irq_count = 0;
@@ -549,90 +549,117 @@ int setup_irq(unsigned int irq, struct irqaction *act)
 
        return __setup_irq(irq, desc, act);
 }
+EXPORT_SYMBOL_GPL(setup_irq);
 
-/**
- *     free_irq - free an interrupt
- *     @irq: Interrupt line to free
- *     @dev_id: Device identity to free
- *
- *     Remove an interrupt handler. The handler is removed and if the
- *     interrupt line is no longer in use by any driver it is disabled.
- *     On a shared IRQ the caller must ensure the interrupt is disabled
- *     on the card it drives before calling this function. The function
- *     does not return until any executing interrupts for this IRQ
- *     have completed.
- *
- *     This function must not be called from interrupt context.
+ /*
+ * Internal function to unregister an irqaction - used to free
+ * regular and special interrupts that are part of the architecture.
  */
-void free_irq(unsigned int irq, void *dev_id)
+static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 {
        struct irq_desc *desc = irq_to_desc(irq);
-       struct irqaction **p;
+       struct irqaction *action, **action_ptr;
        unsigned long flags;
 
-       WARN_ON(in_interrupt());
+       WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
 
        if (!desc)
-               return;
+               return NULL;
 
        spin_lock_irqsave(&desc->lock, flags);
-       p = &desc->action;
+
+       /*
+        * There can be multiple actions per IRQ descriptor, find the right
+        * one based on the dev_id:
+        */
+       action_ptr = &desc->action;
        for (;;) {
-               struct irqaction *action = *p;
+               action = *action_ptr;
 
-               if (action) {
-                       struct irqaction **pp = p;
+               if (!action) {
+                       WARN(1, "Trying to free already-free IRQ %d\n", irq);
+                       spin_unlock_irqrestore(&desc->lock, flags);
 
-                       p = &action->next;
-                       if (action->dev_id != dev_id)
-                               continue;
+                       return NULL;
+               }
 
-                       /* Found it - now remove it from the list of entries */
-                       *pp = action->next;
+               if (action->dev_id == dev_id)
+                       break;
+               action_ptr = &action->next;
+       }
 
-                       /* Currently used only by UML, might disappear one day.*/
+       /* Found it - now remove it from the list of entries: */
+       *action_ptr = action->next;
+
+       /* Currently used only by UML, might disappear one day: */
 #ifdef CONFIG_IRQ_RELEASE_METHOD
-                       if (desc->chip->release)
-                               desc->chip->release(irq, dev_id);
+       if (desc->chip->release)
+               desc->chip->release(irq, dev_id);
 #endif
 
-                       if (!desc->action) {
-                               desc->status |= IRQ_DISABLED;
-                               if (desc->chip->shutdown)
-                                       desc->chip->shutdown(irq);
-                               else
-                                       desc->chip->disable(irq);
-                       }
-                       spin_unlock_irqrestore(&desc->lock, flags);
-                       unregister_handler_proc(irq, action);
+       /* If this was the last handler, shut down the IRQ line: */
+       if (!desc->action) {
+               desc->status |= IRQ_DISABLED;
+               if (desc->chip->shutdown)
+                       desc->chip->shutdown(irq);
+               else
+                       desc->chip->disable(irq);
+       }
+       spin_unlock_irqrestore(&desc->lock, flags);
+
+       unregister_handler_proc(irq, action);
+
+       /* Make sure it's not being used on another CPU: */
+       synchronize_irq(irq);
 
-                       /* Make sure it's not being used on another CPU */
-                       synchronize_irq(irq);
-#ifdef CONFIG_DEBUG_SHIRQ
-                       /*
-                        * It's a shared IRQ -- the driver ought to be
-                        * prepared for it to happen even now it's
-                        * being freed, so let's make sure....  We do
-                        * this after actually deregistering it, to
-                        * make sure that a 'real' IRQ doesn't run in
-                        * parallel with our fake
-                        */
-                       if (action->flags & IRQF_SHARED) {
-                               local_irq_save(flags);
-                               action->handler(irq, dev_id);
-                               local_irq_restore(flags);
-                       }
-#endif
-                       kfree(action);
-                       return;
-               }
-               printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
 #ifdef CONFIG_DEBUG_SHIRQ
-               dump_stack();
-#endif
-               spin_unlock_irqrestore(&desc->lock, flags);
-               return;
+       /*
+        * It's a shared IRQ -- the driver ought to be prepared for an IRQ
+        * event to happen even now it's being freed, so let's make sure that
+        * is so by doing an extra call to the handler ....
+        *
+        * ( We do this after actually deregistering it, to make sure that a
+        *   'real' IRQ doesn't run in * parallel with our fake. )
+        */
+       if (action->flags & IRQF_SHARED) {
+               local_irq_save(flags);
+               action->handler(irq, dev_id);
+               local_irq_restore(flags);
        }
+#endif
+       return action;
+}
+
+/**
+ *     remove_irq - free an interrupt
+ *     @irq: Interrupt line to free
+ *     @act: irqaction for the interrupt
+ *
+ * Used to remove interrupts statically setup by the early boot process.
+ */
+void remove_irq(unsigned int irq, struct irqaction *act)
+{
+       __free_irq(irq, act->dev_id);
+}
+EXPORT_SYMBOL_GPL(remove_irq);
+
+/**
+ *     free_irq - free an interrupt allocated with request_irq
+ *     @irq: Interrupt line to free
+ *     @dev_id: Device identity to free
+ *
+ *     Remove an interrupt handler. The handler is removed and if the
+ *     interrupt line is no longer in use by any driver it is disabled.
+ *     On a shared IRQ the caller must ensure the interrupt is disabled
+ *     on the card it drives before calling this function. The function
+ *     does not return until any executing interrupts for this IRQ
+ *     have completed.
+ *
+ *     This function must not be called from interrupt context.
+ */
+void free_irq(unsigned int irq, void *dev_id)
+{
+       kfree(__free_irq(irq, dev_id));
 }
 EXPORT_SYMBOL(free_irq);
 
@@ -679,11 +706,12 @@ int request_irq(unsigned int irq, irq_handler_t handler,
         * the behavior is classified as "will not fix" so we need to
         * start nudging drivers away from using that idiom.
         */
-       if ((irqflags & (IRQF_SHARED|IRQF_DISABLED))
-                       == (IRQF_SHARED|IRQF_DISABLED))
-               pr_warning("IRQ %d/%s: IRQF_DISABLED is not "
-                               "guaranteed on shared IRQs\n",
-                               irq, devname);
+       if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) ==
+                                       (IRQF_SHARED|IRQF_DISABLED)) {
+               pr_warning(
+                 "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n",
+                       irq, devname);
+       }
 
 #ifdef CONFIG_LOCKDEP
        /*
@@ -709,15 +737,13 @@ int request_irq(unsigned int irq, irq_handler_t handler,
        if (!handler)
                return -EINVAL;
 
-       action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+       action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
        if (!action)
                return -ENOMEM;
 
        action->handler = handler;
        action->flags = irqflags;
-       cpus_clear(action->mask);
        action->name = devname;
-       action->next = NULL;
        action->dev_id = dev_id;
 
        retval = __setup_irq(irq, desc, action);
index acd88356ac76abfcbd186209f16d8e92d2ff31fb..aef18ab6b75bf1954f23ccff4a52a948d62b74d2 100644 (file)
@@ -17,16 +17,11 @@ static void init_copy_kstat_irqs(struct irq_desc *old_desc,
                                 struct irq_desc *desc,
                                 int cpu, int nr)
 {
-       unsigned long bytes;
-
        init_kstat_irqs(desc, cpu, nr);
 
-       if (desc->kstat_irqs != old_desc->kstat_irqs) {
-               /* Compute how many bytes we need per irq and allocate them */
-               bytes = nr * sizeof(unsigned int);
-
-               memcpy(desc->kstat_irqs, old_desc->kstat_irqs, bytes);
-       }
+       if (desc->kstat_irqs != old_desc->kstat_irqs)
+               memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
+                        nr * sizeof(*desc->kstat_irqs));
 }
 
 static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
index dd364c11e56e0f82e0e923fcc3b60d17524e991d..4d568294de3ebfc1326432a9d7a7e4a01cdb115b 100644 (file)
@@ -104,7 +104,7 @@ static int misrouted_irq(int irq)
        return ok;
 }
 
-static void poll_spurious_irqs(unsigned long dummy)
+static void poll_all_shared_irqs(void)
 {
        struct irq_desc *desc;
        int i;
@@ -123,11 +123,23 @@ static void poll_spurious_irqs(unsigned long dummy)
 
                try_one_irq(i, desc);
        }
+}
+
+static void poll_spurious_irqs(unsigned long dummy)
+{
+       poll_all_shared_irqs();
 
        mod_timer(&poll_spurious_irq_timer,
                  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
 }
 
+#ifdef CONFIG_DEBUG_SHIRQ
+void debug_poll_all_shared_irqs(void)
+{
+       poll_all_shared_irqs();
+}
+#endif
+
 /*
  * If 99,900 of the previous 100,000 interrupts have not been handled
  * then assume that the IRQ is stuck in some manner. Drop a diagnostic