Commit 8cd809c5 authored by Takashi Iwai's avatar Takashi Iwai Committed by Linus Torvalds

[PATCH] Fix the unnecessary entropy call in the irq handler

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: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b08e7589
......@@ -83,6 +83,7 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
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, struct pt_regs *regs,
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)
......
......@@ -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 irqaction *action, struct pt_regs *regs)
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);
......
......@@ -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 irqaction *action, struct pt_regs *regs)
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);
......
......@@ -125,7 +125,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
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 pt_regs * regs)
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);
......
......@@ -220,14 +220,16 @@ asmlinkage 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)
......
......@@ -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)
......
......@@ -180,7 +180,7 @@ int get_irq_list(char *buf)
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_regs * regs)
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)
......
......@@ -144,14 +144,16 @@ inline void synchronize_irq(unsigned int irq)
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)
......
......@@ -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)
......
......@@ -363,14 +363,16 @@ int show_interrupts(struct seq_file *p, void *v)
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)
......
......@@ -137,14 +137,16 @@ int show_interrupts(struct seq_file *p, void *v)
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);
......
......@@ -148,6 +148,7 @@ asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs)
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, struct pt_regs * regs, struct irqaction *
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)
......
......@@ -147,13 +147,15 @@ 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)
......
......@@ -141,13 +141,15 @@ int show_interrupts(struct seq_file *p, void *v)
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)
......
......@@ -213,13 +213,15 @@ inline void synchronize_irq(unsigned int irq)
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment