]>
Commit | Line | Data |
---|---|---|
8f69975d BS |
1 | From: Bernhard Walle <bwalle@suse.de> |
2 | Subject: [PATCH] Fix performance regression on large IA64 systems | |
3 | References: bnc #469589 | |
4 | ||
5 | This patch tries to address a performance regression discovered by SGI. | |
6 | ||
7 | Patch b60c1f6ffd88850079ae419aa933ab0eddbd5535 removes the call | |
8 | to note_interrupt() in __do_IRQ(). Patch d85a60d85ea5b7c597508c1510c88e657773d378 | |
9 | adds it again. Because it's needed for irqpoll. | |
10 | ||
11 | That patch now introduces a new parameter 'only_fixup' for note_interrupt(). | |
12 | This parameter determines two cases: | |
13 | ||
14 | TRUE => The function should be only executed when irqfixup is set. | |
15 | Either 'irqpoll' or 'irqfixup' directly set that. | |
16 | ||
17 | FALSE => Just the behaviour as note_interrupt() always had. | |
18 | ||
19 | Now the patch converts all calls of note_interrupt() to only_fixup=FALSE, | |
20 | except the call that has been removed by b60c1f6ffd88850079ae419aa933ab0eddbd5535. | |
21 | So that call is always done, but the body is only executed when either | |
22 | 'irqpoll' or 'irqfixup' are specified. | |
23 | ||
24 | This patch is not meant for mainline inclusion in the first run! | |
25 | ||
26 | ||
27 | Signed-off-by: Bernhard Walle <bwalle@suse.de> | |
28 | ||
29 | --- | |
30 | arch/arm/mach-ns9xxx/irq.c | 2 +- | |
31 | arch/powerpc/platforms/cell/interrupt.c | 2 +- | |
32 | include/linux/irq.h | 2 +- | |
33 | kernel/irq/chip.c | 10 +++++----- | |
34 | kernel/irq/handle.c | 4 ++-- | |
35 | kernel/irq/spurious.c | 13 ++++++++++++- | |
36 | 6 files changed, 22 insertions(+), 11 deletions(-) | |
37 | ||
38 | --- a/arch/arm/mach-ns9xxx/irq.c | |
39 | +++ b/arch/arm/mach-ns9xxx/irq.c | |
40 | @@ -86,7 +86,7 @@ static void handle_prio_irq(unsigned int | |
41 | /* XXX: There is no direct way to access noirqdebug, so check | |
42 | * unconditionally for spurious irqs... | |
43 | * Maybe this function should go to kernel/irq/chip.c? */ | |
44 | - note_interrupt(irq, desc, action_ret); | |
45 | + note_interrupt(irq, desc, action_ret, 0); | |
46 | ||
47 | spin_lock(&desc->lock); | |
48 | desc->status &= ~IRQ_INPROGRESS; | |
49 | --- a/arch/powerpc/platforms/cell/interrupt.c | |
50 | +++ b/arch/powerpc/platforms/cell/interrupt.c | |
51 | @@ -270,7 +270,7 @@ static void handle_iic_irq(unsigned int | |
52 | spin_unlock(&desc->lock); | |
53 | action_ret = handle_IRQ_event(irq, action); | |
54 | if (!noirqdebug) | |
55 | - note_interrupt(irq, desc, action_ret); | |
56 | + note_interrupt(irq, desc, action_ret, 0); | |
57 | spin_lock(&desc->lock); | |
58 | ||
59 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | |
60 | --- a/include/linux/irq.h | |
61 | +++ b/include/linux/irq.h | |
62 | @@ -296,7 +296,7 @@ static inline void generic_handle_irq(un | |
63 | ||
64 | /* Handling of unhandled and spurious interrupts: */ | |
65 | extern void note_interrupt(unsigned int irq, struct irq_desc *desc, | |
66 | - int action_ret); | |
67 | + int action_ret, int only_fixup); | |
68 | ||
69 | /* Resending of interrupts :*/ | |
70 | void check_irq_resend(struct irq_desc *desc, unsigned int irq); | |
71 | --- a/kernel/irq/chip.c | |
72 | +++ b/kernel/irq/chip.c | |
73 | @@ -324,7 +324,7 @@ handle_simple_irq(unsigned int irq, stru | |
74 | ||
75 | action_ret = handle_IRQ_event(irq, action); | |
76 | if (!noirqdebug) | |
77 | - note_interrupt(irq, desc, action_ret); | |
78 | + note_interrupt(irq, desc, action_ret, 0); | |
79 | ||
80 | spin_lock(&desc->lock); | |
81 | desc->status &= ~IRQ_INPROGRESS; | |
82 | @@ -370,7 +370,7 @@ handle_level_irq(unsigned int irq, struc | |
83 | ||
84 | action_ret = handle_IRQ_event(irq, action); | |
85 | if (!noirqdebug) | |
86 | - note_interrupt(irq, desc, action_ret); | |
87 | + note_interrupt(irq, desc, action_ret, 0); | |
88 | ||
89 | spin_lock(&desc->lock); | |
90 | desc->status &= ~IRQ_INPROGRESS; | |
91 | @@ -423,7 +423,7 @@ handle_fasteoi_irq(unsigned int irq, str | |
92 | ||
93 | action_ret = handle_IRQ_event(irq, action); | |
94 | if (!noirqdebug) | |
95 | - note_interrupt(irq, desc, action_ret); | |
96 | + note_interrupt(irq, desc, action_ret, 0); | |
97 | ||
98 | spin_lock(&desc->lock); | |
99 | desc->status &= ~IRQ_INPROGRESS; | |
100 | @@ -503,7 +503,7 @@ handle_edge_irq(unsigned int irq, struct | |
101 | spin_unlock(&desc->lock); | |
102 | action_ret = handle_IRQ_event(irq, action); | |
103 | if (!noirqdebug) | |
104 | - note_interrupt(irq, desc, action_ret); | |
105 | + note_interrupt(irq, desc, action_ret, 0); | |
106 | spin_lock(&desc->lock); | |
107 | ||
108 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | |
109 | @@ -532,7 +532,7 @@ handle_percpu_irq(unsigned int irq, stru | |
110 | ||
111 | action_ret = handle_IRQ_event(irq, desc->action); | |
112 | if (!noirqdebug) | |
113 | - note_interrupt(irq, desc, action_ret); | |
114 | + note_interrupt(irq, desc, action_ret, 0); | |
115 | ||
116 | if (desc->chip->eoi) | |
117 | desc->chip->eoi(irq); | |
118 | --- a/kernel/irq/handle.c | |
119 | +++ b/kernel/irq/handle.c | |
120 | @@ -187,7 +187,7 @@ unsigned int __do_IRQ(unsigned int irq) | |
121 | if (likely(!(desc->status & IRQ_DISABLED))) { | |
122 | action_ret = handle_IRQ_event(irq, desc->action); | |
123 | if (!noirqdebug) | |
124 | - note_interrupt(irq, desc, action_ret); | |
125 | + note_interrupt(irq, desc, action_ret, 1); | |
126 | } | |
127 | desc->chip->end(irq); | |
128 | return 1; | |
129 | @@ -241,7 +241,7 @@ unsigned int __do_IRQ(unsigned int irq) | |
130 | ||
131 | action_ret = handle_IRQ_event(irq, action); | |
132 | if (!noirqdebug) | |
133 | - note_interrupt(irq, desc, action_ret); | |
134 | + note_interrupt(irq, desc, action_ret, 0); | |
135 | ||
136 | spin_lock(&desc->lock); | |
137 | if (likely(!(desc->status & IRQ_PENDING))) | |
138 | --- a/kernel/irq/spurious.c | |
139 | +++ b/kernel/irq/spurious.c | |
140 | @@ -171,8 +171,19 @@ static inline int try_misrouted_irq(unsi | |
141 | } | |
142 | ||
143 | void note_interrupt(unsigned int irq, struct irq_desc *desc, | |
144 | - irqreturn_t action_ret) | |
145 | + irqreturn_t action_ret, int only_fixup) | |
146 | { | |
147 | + /* | |
148 | + * The parameter "only_fixup" means that the function should be only | |
149 | + * executed if this parameter is set to 1 and the function should | |
150 | + * not be executed if the parameter is 0. | |
151 | + * | |
152 | + * We need that because irqfixup is static to the function but | |
153 | + * this function is called from kernel/irq/handle.c. | |
154 | + */ | |
155 | + if (only_fixup && irqfixup == 0) | |
156 | + return; | |
157 | + | |
158 | if (unlikely(action_ret != IRQ_HANDLED)) { | |
159 | /* | |
160 | * If we are seeing only the odd spurious IRQ caused by |