]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/irq/manage.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6-omap-h63xx.git] / kernel / irq / manage.c
index 9eb1d518ee1c8dc8da68f7903cd207482352e8fa..92be519eff26fe3fd467eb6ca0e3e063a36f50ce 100644 (file)
@@ -7,7 +7,6 @@
  * This file contains driver APIs to the irq subsystem.
  */
 
-#include <linux/config.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/random.h>
@@ -115,7 +114,7 @@ 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);
+               printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
                WARN_ON(1);
                break;
        case 1: {
@@ -138,16 +137,40 @@ EXPORT_SYMBOL(enable_irq);
  *     @irq:   interrupt to control
  *     @on:    enable/disable power management wakeup
  *
- *     Enable/disable power management wakeup mode
+ *     Enable/disable power management wakeup mode, which is
+ *     disabled by default.  Enables and disables must match,
+ *     just as they match for non-wakeup mode support.
+ *
+ *     Wakeup mode lets this IRQ wake the system from sleep
+ *     states like "suspend to RAM".
  */
 int set_irq_wake(unsigned int irq, unsigned int on)
 {
        struct irq_desc *desc = irq_desc + irq;
        unsigned long flags;
        int ret = -ENXIO;
+       int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
 
+       /* wakeup-capable irqs can be shared between drivers that
+        * don't need to have the same sleep mode behaviors.
+        */
        spin_lock_irqsave(&desc->lock, flags);
-       if (desc->chip->set_wake)
+       if (on) {
+               if (desc->wake_depth++ == 0)
+                       desc->status |= IRQ_WAKEUP;
+               else
+                       set_wake = NULL;
+       } else {
+               if (desc->wake_depth == 0) {
+                       printk(KERN_WARNING "Unbalanced IRQ %d "
+                                       "wake disable\n", irq);
+                       WARN_ON(1);
+               } else if (--desc->wake_depth == 0)
+                       desc->status &= ~IRQ_WAKEUP;
+               else
+                       set_wake = NULL;
+       }
+       if (set_wake)
                ret = desc->chip->set_wake(irq, on);
        spin_unlock_irqrestore(&desc->lock, flags);
        return ret;
@@ -168,7 +191,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
 
        action = irq_desc[irq].action;
        if (action)
-               if (irqflags & action->flags & SA_SHIRQ)
+               if (irqflags & action->flags & IRQF_SHARED)
                        action = NULL;
 
        return !action;
@@ -206,7 +229,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
         * so we have to be careful not to interfere with a
         * running system.
         */
-       if (new->flags & SA_SAMPLE_RANDOM) {
+       if (new->flags & IRQF_SAMPLE_RANDOM) {
                /*
                 * This function might sleep, we want to call it first,
                 * outside of the atomic block.
@@ -228,16 +251,17 @@ int setup_irq(unsigned int irq, struct irqaction *new)
                /*
                 * Can't share interrupts unless both agree to and are
                 * the same type (level, edge, polarity). So both flag
-                * fields must have SA_SHIRQ set and the bits which
+                * fields must have IRQF_SHARED set and the bits which
                 * set the trigger type must match.
                 */
-               if (!((old->flags & new->flags) & SA_SHIRQ) ||
-                   ((old->flags ^ new->flags) & SA_TRIGGER_MASK))
+               if (!((old->flags & new->flags) & IRQF_SHARED) ||
+                   ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK))
                        goto mismatch;
 
-#if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
+#if defined(CONFIG_IRQ_PER_CPU)
                /* All handlers must agree on per-cpuness */
-               if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU))
+               if ((old->flags & IRQF_PERCPU) !=
+                   (new->flags & IRQF_PERCPU))
                        goto mismatch;
 #endif
 
@@ -250,26 +274,27 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        }
 
        *p = new;
-#if defined(CONFIG_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ)
-       if (new->flags & SA_PERCPU_IRQ)
+#if defined(CONFIG_IRQ_PER_CPU)
+       if (new->flags & IRQF_PERCPU)
                desc->status |= IRQ_PER_CPU;
 #endif
        if (!shared) {
                irq_chip_set_defaults(desc->chip);
 
                /* Setup the type (level, edge polarity) if configured: */
-               if (new->flags & SA_TRIGGER_MASK) {
+               if (new->flags & IRQF_TRIGGER_MASK) {
                        if (desc->chip && desc->chip->set_type)
                                desc->chip->set_type(irq,
-                                               new->flags & SA_TRIGGER_MASK);
+                                               new->flags & IRQF_TRIGGER_MASK);
                        else
                                /*
-                                * SA_TRIGGER_* but the PIC does not support
+                                * IRQF_TRIGGER_* but the PIC does not support
                                 * multiple flow-types?
                                 */
-                               printk(KERN_WARNING "setup_irq(%d) SA_TRIGGER"
-                                      "set. No set_type function available\n",
-                                      irq);
+                               printk(KERN_WARNING "No IRQF_TRIGGER set_type "
+                                      "function for IRQ %d (%s)\n", irq,
+                                      desc->chip ? desc->chip->name :
+                                      "unknown");
                } else
                        compat_irq_chip_set_default_handler(desc);
 
@@ -298,8 +323,8 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 
 mismatch:
        spin_unlock_irqrestore(&desc->lock, flags);
-       if (!(new->flags & SA_PROBEIRQ)) {
-               printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__);
+       if (!(new->flags & IRQF_PROBE_SHARED)) {
+               printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
                dump_stack();
        }
        return -EBUSY;
@@ -366,7 +391,7 @@ void free_irq(unsigned int irq, void *dev_id)
                        kfree(action);
                        return;
                }
-               printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
+               printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
                spin_unlock_irqrestore(&desc->lock, flags);
                return;
        }
@@ -397,9 +422,9 @@ EXPORT_SYMBOL(free_irq);
  *
  *     Flags:
  *
- *     SA_SHIRQ                Interrupt is shared
- *     SA_INTERRUPT            Disable local interrupts while processing
- *     SA_SAMPLE_RANDOM        The interrupt can be used for entropy
+ *     IRQF_SHARED             Interrupt is shared
+ *     IRQF_DISABLED   Disable local interrupts while processing
+ *     IRQF_SAMPLE_RANDOM      The interrupt can be used for entropy
  *
  */
 int request_irq(unsigned int irq,
@@ -409,13 +434,19 @@ int request_irq(unsigned int irq,
        struct irqaction *action;
        int retval;
 
+#ifdef CONFIG_LOCKDEP
+       /*
+        * Lockdep wants atomic interrupt handlers:
+        */
+       irqflags |= SA_INTERRUPT;
+#endif
        /*
         * Sanity-check: shared interrupts must pass in a real dev-ID,
         * otherwise we'll have trouble later trying to figure out
         * which interrupt is which (messes up the interrupt freeing
         * logic etc).
         */
-       if ((irqflags & SA_SHIRQ) && !dev_id)
+       if ((irqflags & IRQF_SHARED) && !dev_id)
                return -EINVAL;
        if (irq >= NR_IRQS)
                return -EINVAL;