You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-linux-kernel/patches.fixes/make-note_interrupt-fast.diff

194 lines
6.6 KiB

From: Bernhard Walle <bwalle@suse.de>
Subject: Fix performance regression on large IA64 systems
References: bnc #469589
Patch-mainline: no (and never will)
This patch tries to address a performance regression discovered by SGI.
Patch b60c1f6ffd88850079ae419aa933ab0eddbd5535 removes the call
to note_interrupt() in __do_IRQ(). Patch d85a60d85ea5b7c597508c1510c88e657773d378
adds it again. Because it's needed for irqpoll.
That patch now introduces a new parameter 'only_fixup' for note_interrupt().
This parameter determines two cases:
TRUE => The function should be only executed when irqfixup is set.
Either 'irqpoll' or 'irqfixup' directly set that.
FALSE => Just the behaviour as note_interrupt() always had.
Now the patch converts all calls of note_interrupt() to only_fixup=FALSE,
except the call that has been removed by b60c1f6ffd88850079ae419aa933ab0eddbd5535.
So that call is always done, but the body is only executed when either
'irqpoll' or 'irqfixup' are specified.
This patch is not meant for mainline inclusion in the first run!
Signed-off-by: Bernhard Walle <bwalle@suse.de>
---
arch/arm/mach-ns9xxx/irq.c | 2 +-
arch/powerpc/platforms/cell/interrupt.c | 2 +-
drivers/mfd/ezx-pcap.c | 3 ++-
drivers/mfd/twl4030-irq.c | 2 +-
include/linux/irq.h | 2 +-
kernel/irq/chip.c | 12 ++++++------
kernel/irq/handle.c | 4 ++--
kernel/irq/spurious.c | 10 +++++++++-
8 files changed, 23 insertions(+), 14 deletions(-)
--- a/arch/arm/mach-ns9xxx/irq.c
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -85,7 +85,7 @@ static void handle_prio_irq(unsigned int
/* XXX: There is no direct way to access noirqdebug, so check
* unconditionally for spurious irqs...
* Maybe this function should go to kernel/irq/chip.c? */
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -268,7 +268,7 @@ static void handle_iic_irq(unsigned int
raw_spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -203,7 +203,8 @@ static void pcap_isr_work(struct work_st
break;
if (desc->status & IRQ_DISABLED)
- note_interrupt(irq, desc, IRQ_NONE);
+ note_interrupt(irq, desc, IRQ_NONE,
+ false);
else
desc->handle_irq(irq, desc);
}
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -330,7 +330,7 @@ static int twl4030_irq_thread(void *data
*/
if (d->status & IRQ_DISABLED)
note_interrupt(module_irq, d,
- IRQ_NONE);
+ IRQ_NONE, false);
else
d->handle_irq(module_irq, d);
}
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -324,7 +324,7 @@ static inline void generic_handle_irq(un
/* Handling of unhandled and spurious interrupts: */
extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
- irqreturn_t action_ret);
+ irqreturn_t action_ret, bool only_fixup);
/* Resending of interrupts :*/
void check_irq_resend(struct irq_desc *desc, unsigned int irq);
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -390,7 +390,7 @@ void handle_nested_irq(unsigned int irq)
action_ret = action->thread_fn(action->irq, action->dev_id);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock_irq(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
@@ -434,7 +434,7 @@ handle_simple_irq(unsigned int irq, stru
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
@@ -479,7 +479,7 @@ handle_level_irq(unsigned int irq, struc
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
@@ -535,7 +535,7 @@ handle_fasteoi_irq(unsigned int irq, str
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
@@ -613,7 +613,7 @@ handle_edge_irq(unsigned int irq, struct
raw_spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
@@ -642,7 +642,7 @@ handle_percpu_irq(unsigned int irq, stru
action_ret = handle_IRQ_event(irq, desc->action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
if (desc->chip->eoi)
desc->chip->eoi(irq);
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -465,7 +465,7 @@ unsigned int __do_IRQ(unsigned int irq)
if (likely(!(desc->status & IRQ_DISABLED))) {
action_ret = handle_IRQ_event(irq, desc->action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, true);
}
desc->chip->end(irq);
return 1;
@@ -519,7 +519,7 @@ unsigned int __do_IRQ(unsigned int irq)
action_ret = handle_IRQ_event(irq, action);
if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
+ note_interrupt(irq, desc, action_ret, false);
raw_spin_lock(&desc->lock);
if (likely(!(desc->status & IRQ_PENDING)))
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -213,9 +213,17 @@ try_misrouted_irq(unsigned int irq, stru
return action && (action->flags & IRQF_IRQPOLL);
}
+/*
+ * The parameter "only_fixup" means that the function should be only executed
+ * if this parameter is set either to false or to true simultaneously with
+ * irqfixup enabled.
+ */
void note_interrupt(unsigned int irq, struct irq_desc *desc,
- irqreturn_t action_ret)
+ irqreturn_t action_ret, bool only_fixup)
{
+ if (only_fixup && irqfixup == 0)
+ return;
+
if (unlikely(action_ret != IRQ_HANDLED)) {
/*
* If we are seeing only the odd spurious IRQ caused by