From: Takashi Iwai <tiwai@suse.de>

Currently add_interrupt_randomness() is called at each interrupt when one
of the handlers has SA_SAMPLE_RANDOM flag, regardless whether the interrupt
is processed by that handler or not.  This results in the higher latency
and perfomance loss.

The patch fixes this behavior to avoid the unnecessary call by checking the
return value from each handler.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/alpha/kernel/irq.c  |    6 ++++--
 25-akpm/arch/arm/kernel/irq.c    |    8 +++++---
 25-akpm/arch/arm26/kernel/irq.c  |    6 ++++--
 25-akpm/arch/cris/kernel/irq.c   |    8 +++++---
 25-akpm/arch/i386/kernel/irq.c   |    8 +++++---
 25-akpm/arch/ia64/kernel/irq.c   |    8 +++++---
 25-akpm/arch/mips/baget/irq.c    |    7 ++++---
 25-akpm/arch/mips/kernel/irq.c   |    8 +++++---
 25-akpm/arch/ppc/kernel/irq.c    |    6 ++++--
 25-akpm/arch/ppc64/kernel/irq.c  |    8 +++++---
 25-akpm/arch/sh/kernel/irq.c     |    8 +++++---
 25-akpm/arch/sh64/kernel/irq.c   |    6 ++++--
 25-akpm/arch/um/kernel/irq.c     |    6 ++++--
 25-akpm/arch/v850/kernel/irq.c   |    6 ++++--
 25-akpm/arch/x86_64/kernel/irq.c |    6 ++++--
 15 files changed, 67 insertions(+), 38 deletions(-)

diff -puN arch/alpha/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/alpha/kernel/irq.c
--- 25/arch/alpha/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/alpha/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -83,6 +83,7 @@ handle_IRQ_event(unsigned int irq, struc
 		 struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret;
 
 	do {
 		if (!(action->flags & SA_INTERRUPT))
@@ -90,8 +91,9 @@ handle_IRQ_event(unsigned int irq, struc
 		else
 			local_irq_disable();
 
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/arm26/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/arm26/kernel/irq.c
--- 25/arch/arm26/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/arm26/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -187,6 +187,7 @@ static void
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
+	int ret;
 
 	spin_unlock(&irq_controller_lock);
 	if (!(action->flags & SA_INTERRUPT))
@@ -194,8 +195,9 @@ __do_irq(unsigned int irq, struct irqact
 
 	status = 0;
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 
diff -puN arch/arm/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/arm/kernel/irq.c
--- 25/arch/arm/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/arm/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -261,7 +261,7 @@ static int
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
-	int retval = 0;
+	int ret, retval = 0;
 
 	spin_unlock(&irq_controller_lock);
 
@@ -270,8 +270,10 @@ __do_irq(unsigned int irq, struct irqact
 
 	status = 0;
 	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);
 
diff -puN arch/cris/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/cris/kernel/irq.c
--- 25/arch/cris/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/cris/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -125,7 +125,7 @@ asmlinkage void do_IRQ(int irq, struct p
 {
 	struct irqaction *action;
 	int do_random, cpu;
-        int retval = 0;
+        int ret, retval = 0;
 
         cpu = smp_processor_id();
         irq_enter();
@@ -137,8 +137,10 @@ asmlinkage void do_IRQ(int irq, struct p
                         local_irq_enable();
                 do_random = 0;
                 do {
-                        do_random |= action->flags;
-                        retval |= action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
+                        retval |= ret;
                         action = action->next;
                 } while (action);
 
diff -puN arch/i386/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/i386/kernel/irq.c
--- 25/arch/i386/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/i386/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -220,14 +220,16 @@ asmlinkage int handle_IRQ_event(unsigned
 		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);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/ia64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/ia64/kernel/irq.c
--- 25/arch/ia64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/ia64/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -255,14 +255,16 @@ 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);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/mips/baget/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/mips/baget/irq.c
--- 25/arch/mips/baget/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/mips/baget/irq.c	Thu Aug 26 16:25:17 2004
@@ -180,7 +180,7 @@ skip:
 static void do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct irqaction *action;
-	int do_random, cpu;
+	int ret, do_random, cpu;
 
 	cpu = smp_processor_id();
 	irq_enter();
@@ -194,8 +194,9 @@ static void do_IRQ(int irq, struct pt_re
 		action = *(irq + irq_action);
 		do_random = 0;
         	do {
-			do_random |= action->flags;
-			action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
 			action = action->next;
         	} while (action);
 		if (do_random & SA_SAMPLE_RANDOM)
diff -puN arch/mips/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/mips/kernel/irq.c
--- 25/arch/mips/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/mips/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -144,14 +144,16 @@ inline void synchronize_irq(unsigned int
 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);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/ppc64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/ppc64/kernel/irq.c
--- 25/arch/ppc64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/ppc64/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -363,14 +363,16 @@ skip:
 int handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
-	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);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/ppc/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/ppc/kernel/irq.c
--- 25/arch/ppc/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/ppc/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -414,13 +414,15 @@ static inline void
 handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/sh64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/sh64/kernel/irq.c
--- 25/arch/sh64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/sh64/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -148,6 +148,7 @@ asmlinkage void do_NMI(unsigned long vec
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status;
+	int ret;
 
 	status = 1;	/* Force the "do bottom halves" bit */
 
@@ -155,8 +156,9 @@ int handle_IRQ_event(unsigned int irq, s
                 local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/sh/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/sh/kernel/irq.c
--- 25/arch/sh/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/sh/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -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);
 
diff -puN arch/um/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/um/kernel/irq.c
--- 25/arch/um/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/um/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -147,13 +147,15 @@ int handle_IRQ_event(unsigned int irq, s
 		     struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/v850/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/v850/kernel/irq.c
--- 25/arch/v850/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/v850/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -141,13 +141,15 @@ skip:
 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;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff -puN arch/x86_64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler arch/x86_64/kernel/irq.c
--- 25/arch/x86_64/kernel/irq.c~fix-the-unnecessary-entropy-call-in-the-irq-handler	Thu Aug 26 16:25:17 2004
+++ 25-akpm/arch/x86_64/kernel/irq.c	Thu Aug 26 16:25:17 2004
@@ -213,13 +213,15 @@ inline void synchronize_irq(unsigned int
 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;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
_