public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH][RFC] per isr in_progress markers
@ 2002-09-07 22:34 Zwane Mwaikambo
  2002-09-08  7:55 ` Ingo Molnar
  0 siblings, 1 reply; 34+ messages in thread
From: Zwane Mwaikambo @ 2002-09-07 22:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Robert Love, Linux Kernel

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



^ permalink raw reply	[flat|nested] 34+ messages in thread
* Re: [PATCH][RFC] per isr in_progress markers
@ 2002-09-09  9:49 zwane
  2002-09-09 14:34 ` Robert Love
  0 siblings, 1 reply; 34+ messages in thread
From: zwane @ 2002-09-09  9:49 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Robert Love, Linux Kernel

[-- Attachment #1: Type: text/plain, Size: 10267 bytes --]

Hi,
   I sent you a bad patch yesterday.

       Zwane

Index: linux-2.5.33/arch/i386/kernel/io_apic.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/arch/i386/kernel/io_apic.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io_apic.c
--- linux-2.5.33/arch/i386/kernel/io_apic.c	31 Aug 2002 22:31:11 -0000	1.1.1.1
+++ linux-2.5.33/arch/i386/kernel/io_apic.c	8 Sep 2002 17:45:32 -0000
@@ -1292,15 +1292,14 @@
 #define shutdown_edge_ioapic_irq	disable_edge_ioapic_irq
 
 /*
- * Once we have recorded IRQ_PENDING already, we can mask the
+ * Once we have recorded irq pending already, we can mask the
  * interrupt for real. This prevents IRQ storms from unhandled
  * devices.
  */
 static void ack_edge_ioapic_irq(unsigned int irq)
 {
 	balance_irq(irq);
-	if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED))
-					== (IRQ_PENDING | IRQ_DISABLED))
+	if (irq_desc[irq].pending && (irq_desc[irq].status & IRQ_DISABLED))
 		mask_IO_APIC_irq(irq);
 	ack_APIC_irq();
 }
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	8 Sep 2002 22:46:56 -0000
@@ -66,7 +66,7 @@
  * Controller mappings for all interrupt sources:
  */
 irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
-	{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
+	{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED, 0}};
 
 static void register_irq_proc (unsigned int irq);
 
@@ -186,11 +186,29 @@
 #if CONFIG_SMP
 inline void synchronize_irq(unsigned int irq)
 {
+	/* We can still synchronize with IRQ_INPROGRESS even
+	 * with asynchronous handlers since it encapsulates
+	 * the handlers
+	 */
 	while (irq_desc[irq].status & IRQ_INPROGRESS)
 		cpu_relax();
 }
 #endif
 
+/* This should be called from ISRs to enable
+ * their interrupt line once they've acked
+ * the device interrupt they are handling.
+ */
+ 
+void isr_unmask_irq(unsigned int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	
+	/* check for an IOAPIC wired interrupt */
+	if ((desc->action->flags & SA_UNMASKIRQ) && !memcmp(desc->handler, "IO", 2))
+		desc->handler->ack(irq);
+}
+
 /*
  * This should really return information about whether
  * we should do bottom half handling etc. Right now we
@@ -200,21 +218,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;
 }
 
 /*
@@ -289,9 +313,10 @@
 	case 1: {
 		unsigned int status = desc->status & ~IRQ_DISABLED;
 		desc->status = status;
-		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+		
+		if (!(status & IRQ_REPLAY) && desc->pending) {
 			desc->status = status | IRQ_REPLAY;
-			hw_resend_irq(desc->handler,irq);
+			hw_resend_irq(desc->handler, irq);
 		}
 		desc->handler->enable(irq);
 		/* fall-through */
@@ -338,16 +363,19 @@
 	   WAITING is used by probe to mark irqs that are being tested
 	   */
 	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-	status |= IRQ_PENDING; /* we _want_ to handle it */
+	desc->pending++;	/* we _want_ to handle it */
 
 	/*
 	 * 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 */
+		desc->pending--; /* we commit to handling */
 		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
 	desc->status = status;
@@ -376,9 +404,9 @@
 		handle_IRQ_event(irq, &regs, action);
 		spin_lock(&desc->lock);
 		
-		if (likely(!(desc->status & IRQ_PENDING)))
+		if (likely(!desc->pending))
 			break;
-		desc->status &= ~IRQ_PENDING;
+		desc->pending--;
 	}
 out:
 	desc->status &= ~IRQ_INPROGRESS;
@@ -424,6 +452,7 @@
  *
  *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
  *
+ *	SA_UNMASKIRQ		Unmask irq line whilst processing
  */
  
 int request_irq(unsigned int irq, 
@@ -463,6 +492,7 @@
 	action->mask = 0;
 	action->name = devname;
 	action->next = NULL;
+	action->status = 0;
 	action->dev_id = dev_id;
 
 	retval = setup_irq(irq, action);
@@ -563,14 +593,14 @@
 		desc = irq_desc + i;
 
 		spin_lock_irq(&desc->lock);
-		if (!irq_desc[i].action) 
-			irq_desc[i].handler->startup(i);
+		if (!desc->action) 
+			desc->handler->startup(i);
 		spin_unlock_irq(&desc->lock);
 	}
 
 	/* Wait for longstanding interrupts to trigger. */
 	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ barrier();
+		/* about 20ms delay */ cpu_relax();
 
 	/*
 	 * enable any unassigned irqs
@@ -584,7 +614,7 @@
 		if (!desc->action) {
 			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
 			if (desc->handler->startup(i))
-				desc->status |= IRQ_PENDING;
+				desc->pending++;
 		}
 		spin_unlock_irq(&desc->lock);
 	}
@@ -593,7 +623,7 @@
 	 * Wait for spurious interrupts to trigger
 	 */
 	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */ barrier();
+		/* about 100ms delay */ cpu_relax();
 
 	/*
 	 * Now filter out any obviously spurious interrupts
@@ -756,6 +786,14 @@
 			return -EBUSY;
 		}
 
+		if (!(old->flags & new->flags & SA_UNMASKIRQ)) {
+			printk(KERN_DEBUG
+				"Unable to unmask irqs with isrs old:%s new:%s\n",
+				old->name, new->name);
+			old->flags &= ~SA_UNMASKIRQ;
+			new->flags &= ~SA_UNMASKIRQ;
+		}
+		
 		/* add new interrupt at end of irq queue */
 		do {
 			p = &old->next;
Index: linux-2.5.33/include/asm-i386/hw_irq.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/include/asm-i386/hw_irq.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 hw_irq.h
--- linux-2.5.33/include/asm-i386/hw_irq.h	31 Aug 2002 22:31:04 -0000	1.1.1.1
+++ linux-2.5.33/include/asm-i386/hw_irq.h	8 Sep 2002 20:29:58 -0000
@@ -43,6 +43,7 @@
 
 extern void mask_irq(unsigned int irq);
 extern void unmask_irq(unsigned int irq);
+extern void isr_unmask_irq(unsigned int irq);
 extern void disable_8259A_irq(unsigned int irq);
 extern void enable_8259A_irq(unsigned int irq);
 extern int i8259A_irq_pending(unsigned int irq);
Index: linux-2.5.33/include/asm-i386/signal.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/include/asm-i386/signal.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 signal.h
--- linux-2.5.33/include/asm-i386/signal.h	31 Aug 2002 22:31:04 -0000	1.1.1.1
+++ linux-2.5.33/include/asm-i386/signal.h	8 Sep 2002 17:47:11 -0000
@@ -120,6 +120,7 @@
 #define SA_PROBE		SA_ONESHOT
 #define SA_SAMPLE_RANDOM	SA_RESTART
 #define SA_SHIRQ		0x04000000
+#define SA_UNMASKIRQ		SA_NOMASK
 #endif
 
 #define SIG_BLOCK          0	/* for blocking signals */
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	8 Sep 2002 17:45:31 -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/include/linux/irq.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.33/include/linux/irq.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 irq.h
--- linux-2.5.33/include/linux/irq.h	31 Aug 2002 22:30:53 -0000	1.1.1.1
+++ linux-2.5.33/include/linux/irq.h	8 Sep 2002 17:45:32 -0000
@@ -24,13 +24,12 @@
  */
 #define IRQ_INPROGRESS	1	/* IRQ handler active - do not enter! */
 #define IRQ_DISABLED	2	/* IRQ disabled - do not enter! */
-#define IRQ_PENDING	4	/* IRQ pending - replay on enable */
-#define IRQ_REPLAY	8	/* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT	16	/* IRQ is being autodetected */
-#define IRQ_WAITING	32	/* IRQ not yet seen - for autodetection */
-#define IRQ_LEVEL	64	/* IRQ level triggered */
-#define IRQ_MASKED	128	/* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU	256	/* IRQ is per CPU */
+#define IRQ_REPLAY	4	/* IRQ has been replayed but not acked yet */
+#define IRQ_AUTODETECT	8	/* IRQ is being autodetected */
+#define IRQ_WAITING	16	/* IRQ not yet seen - for autodetection */
+#define IRQ_LEVEL	32	/* IRQ level triggered */
+#define IRQ_MASKED	64	/* IRQ masked - shouldn't be seen again */
+#define IRQ_PER_CPU	128	/* IRQ is per CPU */
 
 /*
  * Interrupt controller descriptor. This is all we need
@@ -62,6 +61,7 @@
 	struct irqaction *action;	/* IRQ action list */
 	unsigned int depth;		/* nested irq disables */
 	spinlock_t lock;
+	unsigned int pending;
 } ____cacheline_aligned irq_desc_t;
 
 extern irq_desc_t irq_desc [NR_IRQS];

^ permalink raw reply	[flat|nested] 34+ messages in thread
* Re: [PATCH][RFC] per isr in_progress markers
@ 2002-09-09 10:13 zwane
  0 siblings, 0 replies; 34+ messages in thread
From: zwane @ 2002-09-09 10:13 UTC (permalink / raw)
  To: bert hubert; +Cc: Linux Kernel

[-- Attachment #1: Type: text/plain, Size: 622 bytes --]

bert hubert <ahu@ds9a.nl> wrote ..
> On Sun, Sep 08, 2002 at 03:01:02PM -0700, Linus Torvalds wrote:
> 
> >    setups (as opposed to most laptops, which often seem to put every PCI
> >    device on the same irq)
> 
> I've always thought that this was a linux problem - any reason *why* laptops
> do this?

Hi Bert,
   I'd presume the reason for that would be because the irq/pin mappings end up in a manner that all the devices end up having the same irq assigned to the pin they're using. This would be a BIOS/fw problem, although it can be alleviated with PCI IRQ router support for that particular chipset.

     Zwane

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2002-09-10 20:49 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-09-07 22:34 [PATCH][RFC] per isr in_progress markers Zwane Mwaikambo
2002-09-08  7:55 ` Ingo Molnar
2002-09-08  8:15   ` Ingo Molnar
2002-09-08 10:38     ` Zwane Mwaikambo
2002-09-08 13:31     ` Zwane Mwaikambo
2002-09-08 16:59       ` Zwane Mwaikambo
2002-09-08 22:01         ` Linus Torvalds
2002-09-08 23:03           ` Jeff Garzik
2002-09-09  6:49           ` bert hubert
2002-09-09 16:24             ` Linus Torvalds
2002-09-09 10:06           ` Ingo Molnar
2002-09-09 15:06             ` Linus Torvalds
2002-09-09 18:44               ` Ingo Molnar
2002-09-09 18:53                 ` Linus Torvalds
2002-09-09 19:37                   ` Zwane Mwaikambo
2002-09-09 19:23                     ` Ingo Molnar
2002-09-09 20:05                       ` Zwane Mwaikambo
2002-09-09 20:08                       ` Andrew Morton
2002-09-10 15:05                       ` David Woodhouse
2002-09-10 15:32                         ` Alan Cox
2002-09-10 22:37                       ` Gérard Roudier
2002-09-09 19:38                     ` Maciej W. Rozycki
2002-09-10 11:55                     ` Stephan von Krawczynski
2002-09-10 18:07                     ` Gunther Mayer
2002-09-10 18:38                       ` Zwane Mwaikambo
2002-09-10  7:46                   ` Rogier Wolff
2002-09-08 10:57   ` Zwane Mwaikambo
2002-09-09 20:40     ` Alan Cox
2002-09-09 20:48       ` Andre Hedrick
2002-09-10 17:47         ` Zwane Mwaikambo
  -- strict thread matches above, loose matches on Subject: below --
2002-09-09  9:49 zwane
2002-09-09 14:34 ` Robert Love
2002-09-09 18:23   ` Zwane Mwaikambo
2002-09-09 10:13 zwane

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox