]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/irq/manage.c
[PATCH] genirq: core
[linux-2.6-omap-h63xx.git] / kernel / irq / manage.c
index ca9b5d36abe8ee7a0d020ca09f689e17cd893c69..b61784ee78b2adde4c673893c6aeef2914090faf 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * linux/kernel/irq/manage.c
  *
- * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
+ * Copyright (C) 2005-2006 Thomas Gleixner
  *
  * This file contains driver APIs to the irq subsystem.
  */
@@ -114,17 +115,15 @@ void enable_irq(unsigned int irq)
        spin_lock_irqsave(&desc->lock, flags);
        switch (desc->depth) {
        case 0:
+               printk(KERN_WARNING "Unablanced enable_irq(%d)\n", irq);
                WARN_ON(1);
                break;
        case 1: {
                unsigned int status = desc->status & ~IRQ_DISABLED;
 
-               desc->status = status;
-               if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-                       desc->status = status | IRQ_REPLAY;
-                       hw_resend_irq(desc->chip,irq);
-               }
-               desc->chip->enable(irq);
+               /* Prevent probing on this irq: */
+               desc->status = status | IRQ_NOPROBE;
+               check_irq_resend(desc, irq);
                /* fall-through */
        }
        default:
@@ -143,7 +142,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
        struct irqaction *action;
 
-       if (irq >= NR_IRQS)
+       if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
                return 0;
 
        action = irq_desc[irq].action;
@@ -154,6 +153,17 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
        return !action;
 }
 
+void compat_irq_chip_set_default_handler(struct irq_desc *desc)
+{
+       /*
+        * If the architecture still has not overriden
+        * the flow handler then zap the default. This
+        * should catch incorrect flow-type setting.
+        */
+       if (desc->handle_irq == &handle_bad_irq)
+               desc->handle_irq = NULL;
+}
+
 /*
  * Internal function to register an irqaction - typically used to
  * allocate special interrupts that are part of the architecture.
@@ -198,7 +208,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
                if (!(old->flags & new->flags & SA_SHIRQ))
                        goto mismatch;
 
-#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+#if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
                /* All handlers must agree on per-cpuness */
                if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU))
                        goto mismatch;
@@ -213,18 +223,25 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        }
 
        *p = new;
-#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+#if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
        if (new->flags & SA_PERCPU_IRQ)
                desc->status |= IRQ_PER_CPU;
 #endif
        if (!shared) {
-               desc->depth = 0;
-               desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT |
-                                 IRQ_WAITING | IRQ_INPROGRESS);
-               if (desc->chip->startup)
-                       desc->chip->startup(irq);
-               else
-                       desc->chip->enable(irq);
+               irq_chip_set_defaults(desc->chip);
+               compat_irq_chip_set_default_handler(desc);
+
+               desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
+                                 IRQ_INPROGRESS);
+
+               if (!(desc->status & IRQ_NOAUTOEN)) {
+                       desc->depth = 0;
+                       desc->status &= ~IRQ_DISABLED;
+                       if (desc->chip->startup)
+                               desc->chip->startup(irq);
+                       else
+                               desc->chip->enable(irq);
+               }
        }
        spin_unlock_irqrestore(&desc->lock, flags);
 
@@ -358,6 +375,8 @@ int request_irq(unsigned int irq,
                return -EINVAL;
        if (irq >= NR_IRQS)
                return -EINVAL;
+       if (irq_desc[irq].status & IRQ_NOREQUEST)
+               return -EINVAL;
        if (!handler)
                return -EINVAL;