Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[cascardo/linux.git] / kernel / irq / chip.c
index 11c9969..0133f4f 100644 (file)
@@ -39,6 +39,7 @@ void dynamic_irq_init(unsigned int irq)
        desc->chip = &no_irq_chip;
        desc->handle_irq = handle_bad_irq;
        desc->depth = 1;
+       desc->msi_desc = NULL;
        desc->handler_data = NULL;
        desc->chip_data = NULL;
        desc->action = NULL;
@@ -74,6 +75,9 @@ void dynamic_irq_cleanup(unsigned int irq)
                WARN_ON(1);
                return;
        }
+       desc->msi_desc = NULL;
+       desc->handler_data = NULL;
+       desc->chip_data = NULL;
        desc->handle_irq = handle_bad_irq;
        desc->chip = &no_irq_chip;
        spin_unlock_irqrestore(&desc->lock, flags);
@@ -161,6 +165,30 @@ int set_irq_data(unsigned int irq, void *data)
 }
 EXPORT_SYMBOL(set_irq_data);
 
+/**
+ *     set_irq_data - set irq type data for an irq
+ *     @irq:   Interrupt number
+ *     @entry: Pointer to MSI descriptor data
+ *
+ *     Set the hardware irq controller data for an irq
+ */
+int set_irq_msi(unsigned int irq, struct msi_desc *entry)
+{
+       struct irq_desc *desc;
+       unsigned long flags;
+
+       if (irq >= NR_IRQS) {
+               printk(KERN_ERR
+                      "Trying to install msi data for IRQ%d\n", irq);
+               return -EINVAL;
+       }
+       desc = irq_desc + irq;
+       spin_lock_irqsave(&desc->lock, flags);
+       desc->msi_desc = entry;
+       spin_unlock_irqrestore(&desc->lock, flags);
+       return 0;
+}
+
 /**
  *     set_irq_chip_data - set irq chip data for an irq
  *     @irq:   Interrupt number
@@ -202,10 +230,6 @@ static void default_enable(unsigned int irq)
  */
 static void default_disable(unsigned int irq)
 {
-       struct irq_desc *desc = irq_desc + irq;
-
-       if (!(desc->status & IRQ_DELAYED_DISABLE))
-               desc->chip->mask(irq);
 }
 
 /*
@@ -233,6 +257,8 @@ void irq_chip_set_defaults(struct irq_chip *chip)
                chip->shutdown = chip->disable;
        if (!chip->name)
                chip->name = chip->typename;
+       if (!chip->end)
+               chip->end = dummy_irq_chip.end;
 }
 
 static inline void mask_ack_irq(struct irq_desc *desc, int irq)
@@ -268,13 +294,18 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 
        if (unlikely(desc->status & IRQ_INPROGRESS))
                goto out_unlock;
-       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
        kstat_cpu(cpu).irqs[irq]++;
 
        action = desc->action;
-       if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+       if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+               if (desc->chip->mask)
+                       desc->chip->mask(irq);
+               desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+               desc->status |= IRQ_PENDING;
                goto out_unlock;
+       }
 
+       desc->status &= ~(IRQ_REPLAY | IRQ_WAITING | IRQ_PENDING);
        desc->status |= IRQ_INPROGRESS;
        spin_unlock(&desc->lock);
 
@@ -366,11 +397,13 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 
        /*
         * If its disabled or no action available
-        * keep it masked and get out of here
+        * then mask it and get out of here:
         */
        action = desc->action;
        if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
                desc->status |= IRQ_PENDING;
+               if (desc->chip->mask)
+                       desc->chip->mask(irq);
                goto out;
        }
 
@@ -499,7 +532,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 #endif /* CONFIG_SMP */
 
 void
-__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained)
+__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+                 const char *name)
 {
        struct irq_desc *desc;
        unsigned long flags;
@@ -514,10 +548,9 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained)
 
        if (!handle)
                handle = handle_bad_irq;
-
-       if (desc->chip == &no_irq_chip) {
+       else if (desc->chip == &no_irq_chip) {
                printk(KERN_WARNING "Trying to install %sinterrupt handler "
-                      "for IRQ%d\n", is_chained ? "chained " : " ", irq);
+                      "for IRQ%d\n", is_chained ? "chained " : "", irq);
                /*
                 * Some ARM implementations install a handler for really dumb
                 * interrupt hardware without setting an irq_chip. This worked
@@ -532,14 +565,13 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained)
 
        /* Uninstall? */
        if (handle == handle_bad_irq) {
-               if (desc->chip != &no_irq_chip) {
-                       desc->chip->mask(irq);
-                       desc->chip->ack(irq);
-               }
+               if (desc->chip != &no_irq_chip)
+                       mask_ack_irq(desc, irq);
                desc->status |= IRQ_DISABLED;
                desc->depth = 1;
        }
        desc->handle_irq = handle;
+       desc->name = name;
 
        if (handle != handle_bad_irq && is_chained) {
                desc->status &= ~IRQ_DISABLED;
@@ -555,30 +587,13 @@ set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
                         irq_flow_handler_t handle)
 {
        set_irq_chip(irq, chip);
-       __set_irq_handler(irq, handle, 0);
+       __set_irq_handler(irq, handle, 0, NULL);
 }
 
-/*
- * Get a descriptive string for the highlevel handler, for
- * /proc/interrupts output:
- */
-const char *
-handle_irq_name(irq_flow_handler_t handle)
+void
+set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+                             irq_flow_handler_t handle, const char *name)
 {
-       if (handle == handle_level_irq)
-               return "level  ";
-       if (handle == handle_fasteoi_irq)
-               return "fasteoi";
-       if (handle == handle_edge_irq)
-               return "edge   ";
-       if (handle == handle_simple_irq)
-               return "simple ";
-#ifdef CONFIG_SMP
-       if (handle == handle_percpu_irq)
-               return "percpu ";
-#endif
-       if (handle == handle_bad_irq)
-               return "bad    ";
-
-       return NULL;
+       set_irq_chip(irq, chip);
+       __set_irq_handler(irq, handle, 0, name);
 }