summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2012-06-27 13:13:52 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 09:03:21 -0700
commitee1602ff18545ddf7f19638fb350e4eec2030c0d (patch)
tree5fb6a4f86e7ef199685a19a996178b5c9d8e7252
parent8057f6c444173496806618f2fe173c2f02fb3995 (diff)
downloadlinux-3.10-ee1602ff18545ddf7f19638fb350e4eec2030c0d.tar.gz
linux-3.10-ee1602ff18545ddf7f19638fb350e4eec2030c0d.tar.bz2
linux-3.10-ee1602ff18545ddf7f19638fb350e4eec2030c0d.zip
powerpc: check_and_cede_processor() never cedes
commit 0b17ba7258db83cd02da560884e053b85de371f2 upstream. Commit f948501b36c6 ("Make hard_irq_disable() actually hard-disable interrupts") caused check_and_cede_processor to stop working. ->irq_happened will never be zero right after a hard_irq_disable so the compiler removes the call to cede_processor completely. The bug was introduced back in the lazy interrupt handling rework of 3.4 but was hidden until recently because hard_irq_disable did nothing. This issue will eventually appear in 3.4 stable since the hard_irq_disable fix is marked stable, so mark this one for stable too. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/include/asm/hw_irq.h5
-rw-r--r--arch/powerpc/platforms/pseries/processor_idle.c2
2 files changed, 6 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 102abd6dbc0..6627a3e1b13 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -102,6 +102,11 @@ static inline void hard_irq_disable(void)
/* include/linux/interrupt.h needs hard_irq_disable to be a macro */
#define hard_irq_disable hard_irq_disable
+static inline bool lazy_irq_pending(void)
+{
+ return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS);
+}
+
/*
* This is called by asynchronous interrupts to conditionally
* re-enable hard interrupts when soft-disabled after having
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
index 41a34bc4a9a..e61483e8e96 100644
--- a/arch/powerpc/platforms/pseries/processor_idle.c
+++ b/arch/powerpc/platforms/pseries/processor_idle.c
@@ -106,7 +106,7 @@ static void check_and_cede_processor(void)
* we first hard disable then check.
*/
hard_irq_disable();
- if (get_paca()->irq_happened == 0)
+ if (!lazy_irq_pending())
cede_processor();
}