Hi Ingo, Robert,
What do you make of the following patch. It is supposed to ease
irq sharing by allowing multiple isrs to be executed, but still not
allowing a specific isr to be run asynchronously. I haven't been able to
test it on SMP proper, only SMP kernel on UP machine and using a shared
network card and sound card concurrently with an interrupt load of
~3000irqs/s
Few questions;
1) Should we set IRQ_PENDING on the way out again if it is found to be
ISR_INPROGRESS?
2) Is the spin_unlock(desc->lock).. handle_IRQ_event() ...
spin_lock(desc->lock) window large enough to allow another cpu in there
to handle another interrupt on that descriptor?
Thanks,
Zwane
Index: linux-2.5.33/include/linux/interrupt.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/include/linux/interrupt.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 interrupt.h
--- linux-2.5.33/include/linux/interrupt.h 31 Aug 2002 22:30:51 -0000 1.1.1.1
+++ linux-2.5.33/include/linux/interrupt.h 7 Sep 2002 17:21:40 -0000
@@ -13,6 +13,8 @@
#include <asm/system.h>
#include <asm/ptrace.h>
+#define ISR_INPROGRESS 1 /* ISR currently being executed */
+
struct irqaction {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
@@ -20,6 +22,7 @@
const char *name;
void *dev_id;
struct irqaction *next;
+ unsigned long status;
};
Index: linux-2.5.33/arch/i386/kernel/irq.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/arch/i386/kernel/irq.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 irq.c
--- linux-2.5.33/arch/i386/kernel/irq.c 31 Aug 2002 22:31:11 -0000 1.1.1.1
+++ linux-2.5.33/arch/i386/kernel/irq.c 7 Sep 2002 17:22:26 -0000
@@ -200,21 +200,27 @@
*/
int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
{
- int status = 1; /* Force the "do bottom halves" bit */
+ int ret = 1; /* Force the "do bottom halves" bit */
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
+ /* Ease irq sharing by allowing other handlers to be run instead
+ * of blocking all with IRQ_INPROGRESS */
+
do {
- status |= action->flags;
- action->handler(irq, action->dev_id, regs);
+ if (test_and_set_bit(ISR_INPROGRESS, &action->status) == 0) {
+ action->handler(irq, action->dev_id, regs);
+ clear_bit(ISR_INPROGRESS, &action->status);
+ }
+ ret |= action->flags;
action = action->next;
} while (action);
- if (status & SA_SAMPLE_RANDOM)
+ if (ret & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
- return status;
+ return ret;
}
/*
@@ -342,10 +348,13 @@
/*
* If the IRQ is disabled for whatever reason, we cannot
- * use the action we have.
+ * use the action we have. Note that we don't check for
+ * IRQ_INPROGRESS, we allow multiple ISRs from a shared
+ * interrupt to be run concurrently, but still not allowing
+ * the same handler to be run asynchronously.
*/
action = NULL;
- if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
+ if (likely(!(status & IRQ_DISABLED))) {
action = desc->action;
status &= ~IRQ_PENDING; /* we commit to handling */
status |= IRQ_INPROGRESS; /* we are handling it */
@@ -463,6 +472,7 @@
action->mask = 0;
action->name = devname;
action->next = NULL;
+ action->status = 0;
action->dev_id = dev_id;
retval = setup_irq(irq, action);
-- function.linuxpower.ca- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Sep 07 2002 - 22:00:33 EST