vserver 1.9.5.x5
[linux-2.6.git] / arch / sh / kernel / irq.c
index a37e2d1..9a7d936 100644 (file)
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
+#include <linux/bitops.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/bitops.h>
 #include <asm/pgalloc.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -137,14 +137,16 @@ unlock:
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
        int status = 1; /* Force the "do bottom halves" bit */
-       int retval = 0;
+       int ret, retval = 0;
 
        if (!(action->flags & SA_INTERRUPT))
                local_irq_enable();
 
        do {
-               status |= action->flags;
-               retval |= action->handler(irq, action->dev_id, regs);
+               ret = action->handler(irq, action->dev_id, regs);
+               if (ret == IRQ_HANDLED)
+                       status |= action->flags;
+               retval |= ret;
                action = action->next;
        } while (action);
 
@@ -436,7 +438,7 @@ int request_irq(unsigned int irq,
 
        action->handler = handler;
        action->flags = irqflags;
-       action->mask = 0;
+       cpus_clear(action->mask);
        action->name = devname;
        action->next = NULL;
        action->dev_id = dev_id;
@@ -575,6 +577,49 @@ unsigned long probe_irq_on(void)
 
 EXPORT_SYMBOL(probe_irq_on);
 
+/* Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+
+/*
+ *     probe_irq_mask - scan a bitmap of interrupt lines
+ *     @val:   mask of interrupts to consider
+ *
+ *     Scan the ISA bus interrupt lines and return a bitmap of
+ *     active interrupts. The interrupt probe logic state is then
+ *     returned to its previous value.
+ *
+ *     Note: we need to scan all the irq's even though we will
+ *     only return ISA irq numbers - just so that we reset them
+ *     all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long val)
+{
+       int i;
+       unsigned int mask;
+
+       mask = 0;
+       for (i = 0; i < NR_IRQS; i++) {
+               irq_desc_t *desc = irq_desc + i;
+               unsigned int status;
+
+               spin_lock_irq(&desc->lock);
+               status = desc->status;
+
+               if (status & IRQ_AUTODETECT) {
+                       if (i < 16 && !(status & IRQ_WAITING))
+                               mask |= 1 << i;
+
+                       desc->status = status & ~IRQ_AUTODETECT;
+                       desc->handler->shutdown(i);
+               }
+               spin_unlock_irq(&desc->lock);
+       }
+       up(&probe_sem);
+
+       return mask & val;
+}
+
 int probe_irq_off(unsigned long val)
 {
        int i, irq_found, nr_irqs;