aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-05-17 01:19:34 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-05-18 11:23:47 -0400
commit3c646f2c6aa9e918d7fc77867df7f430059f9ccc (patch)
tree83cb34334d12c1ca9fcea185f36e75ed26cc6a61
parent63781394c540dd9e666a6b21d70b64dd52bce76e (diff)
genirq: Don't suspend nested_thread irqs over system suspend
Nested IRQs can only fire when the parent irq fires. So when the parent is suspended, there is no need to suspend the child irq. Suspending nested irqs can cause a problem is they are suspended or resumed in the wrong order. If an interrupt fires while the parent is active but the child is suspended, then the interrupt will not be acknowledged properly and so an interrupt storm can result. This is particularly likely if the parent is resumed before the child, and the interrupt was raised during suspend. Ensuring correct ordering would be possible, but it is simpler to just never suspend nested interrupts. Signed-off-by: NeilBrown <neil@brown.name> Cc: GTA04 owners <gta04-owner@goldelico.com> Cc: Kalle Jokiniemi <kalle.jokiniemi@jollamobile.com> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Link: http://lkml.kernel.org/r/20150517151934.2393e8f8@notabene.brown Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/irq/pm.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index 5204a6d1b985..d22786a6dbde 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -123,6 +123,8 @@ void suspend_device_irqs(void)
123 unsigned long flags; 123 unsigned long flags;
124 bool sync; 124 bool sync;
125 125
126 if (irq_settings_is_nested_thread(desc))
127 continue;
126 raw_spin_lock_irqsave(&desc->lock, flags); 128 raw_spin_lock_irqsave(&desc->lock, flags);
127 sync = suspend_device_irq(desc, irq); 129 sync = suspend_device_irq(desc, irq);
128 raw_spin_unlock_irqrestore(&desc->lock, flags); 130 raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -163,6 +165,8 @@ static void resume_irqs(bool want_early)
163 165
164 if (!is_early && want_early) 166 if (!is_early && want_early)
165 continue; 167 continue;
168 if (irq_settings_is_nested_thread(desc))
169 continue;
166 170
167 raw_spin_lock_irqsave(&desc->lock, flags); 171 raw_spin_lock_irqsave(&desc->lock, flags);
168 resume_irq(desc, irq); 172 resume_irq(desc, irq);