aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:26 -0400
commite7b946e98a456077dd6897f726f3d6197bd7e3b9 (patch)
treebb76eb06edcef981540774d638a1bd7eaef690ee
parenta24ceab4f44f21749aa0b6bd38bee37c775e036f (diff)
[PATCH] genirq: irq: add moved_masked_irq
Currently move_native_irq disables and renables the irq we are migrating to ensure we don't take that irq when we are actually doing the migration operation. Disabling the irq needs to happen but sometimes doing the work is move_native_irq is too late. On x86 with ioapics the irq move sequences needs to be: edge_triggered: mask irq. move irq. unmask irq. ack irq. level_triggered: mask irq. ack irq. move irq. unmask irq. We can easily perform the edge triggered sequence, with the current defintion of move_native_irq. However the level triggered case does not map well. For that I have added move_masked_irq, to allow me to disable the irqs around both the ack and the move. Q: Why have we not seen this problem earlier? A: The only symptom I have been able to reproduce is that if we change the vector before acknowleding an irq the wrong irq is acknowledged. Since we currently are not reprogramming the irq vector during migration no problems show up. We have to mask the irq before we acknowledge the irq or else we could hit a window where an irq is asserted just before we acknowledge it. Edge triggered irqs do not have this problem because acknowledgements do not propogate in the same way. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rajesh Shah <rajesh.shah@intel.com> Cc: Andi Kleen <ak@muc.de> Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/irq.h6
-rw-r--r--kernel/irq/migration.c28
2 files changed, 27 insertions, 7 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3eab46f590a9..a31a7d8acdb2 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -205,6 +205,7 @@ static inline void set_native_irq_info(int irq, cpumask_t mask)
205 205
206void set_pending_irq(unsigned int irq, cpumask_t mask); 206void set_pending_irq(unsigned int irq, cpumask_t mask);
207void move_native_irq(int irq); 207void move_native_irq(int irq);
208void move_masked_irq(int irq);
208 209
209#ifdef CONFIG_PCI_MSI 210#ifdef CONFIG_PCI_MSI
210/* 211/*
@@ -246,6 +247,10 @@ static inline void move_native_irq(int irq)
246{ 247{
247} 248}
248 249
250static inline void move_masked_irq(int irq)
251{
252}
253
249static inline void set_pending_irq(unsigned int irq, cpumask_t mask) 254static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
250{ 255{
251} 256}
@@ -261,6 +266,7 @@ static inline void set_irq_info(int irq, cpumask_t mask)
261 266
262#define move_irq(x) 267#define move_irq(x)
263#define move_native_irq(x) 268#define move_native_irq(x)
269#define move_masked_irq(x)
264 270
265#endif /* CONFIG_SMP */ 271#endif /* CONFIG_SMP */
266 272
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 9b234df810d0..4baa3bbcd25a 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -12,7 +12,7 @@ void set_pending_irq(unsigned int irq, cpumask_t mask)
12 spin_unlock_irqrestore(&desc->lock, flags); 12 spin_unlock_irqrestore(&desc->lock, flags);
13} 13}
14 14
15void move_native_irq(int irq) 15void move_masked_irq(int irq)
16{ 16{
17 struct irq_desc *desc = irq_desc + irq; 17 struct irq_desc *desc = irq_desc + irq;
18 cpumask_t tmp; 18 cpumask_t tmp;
@@ -48,15 +48,29 @@ void move_native_irq(int irq)
48 * when an active trigger is comming in. This could 48 * when an active trigger is comming in. This could
49 * cause some ioapics to mal-function. 49 * cause some ioapics to mal-function.
50 * Being paranoid i guess! 50 * Being paranoid i guess!
51 *
52 * For correct operation this depends on the caller
53 * masking the irqs.
51 */ 54 */
52 if (likely(!cpus_empty(tmp))) { 55 if (likely(!cpus_empty(tmp))) {
53 if (likely(!(desc->status & IRQ_DISABLED)))
54 desc->chip->disable(irq);
55
56 desc->chip->set_affinity(irq,tmp); 56 desc->chip->set_affinity(irq,tmp);
57
58 if (likely(!(desc->status & IRQ_DISABLED)))
59 desc->chip->enable(irq);
60 } 57 }
61 cpus_clear(irq_desc[irq].pending_mask); 58 cpus_clear(irq_desc[irq].pending_mask);
62} 59}
60
61void move_native_irq(int irq)
62{
63 struct irq_desc *desc = irq_desc + irq;
64
65 if (likely(!(desc->status & IRQ_MOVE_PENDING)))
66 return;
67
68 if (likely(!(desc->status & IRQ_DISABLED)))
69 desc->chip->disable(irq);
70
71 move_masked_irq(irq);
72
73 if (likely(!(desc->status & IRQ_DISABLED)))
74 desc->chip->enable(irq);
75}
76