From 8a1e97ee2e025f116765c92409a3cf8f6cb07ad6 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 29 Mar 2007 23:42:42 +0100 Subject: [MIPS] SMTC: Fix recursion in instant IPI replay code. local_irq_restore -> raw_local_irq_restore -> irq_restore_epilog -> smtc_ipi_replay -> smtc_ipi_dq -> spin_unlock_irqrestore -> _spin_unlock_irqrestore -> local_irq_restore The recursion does abort when there is no more IPI queued for a CPU, so this isn't usually fatal which is why we got away with this for so long until this was discovered by code inspection. Signed-off-by: Ralf Baechle --- include/asm-mips/irqflags.h | 55 +++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) (limited to 'include/asm-mips/irqflags.h') diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h index af3b07dfad4..e459fa05db8 100644 --- a/include/asm-mips/irqflags.h +++ b/include/asm-mips/irqflags.h @@ -13,29 +13,9 @@ #ifndef __ASSEMBLY__ +#include #include -/* - * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs, - * at the cost of branch and call overhead on each local_irq_restore() - */ - -#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY - -extern void smtc_ipi_replay(void); - -#define irq_restore_epilog(flags) \ -do { \ - if (!(flags & 0x0400)) \ - smtc_ipi_replay(); \ -} while (0) - -#else - -#define irq_restore_epilog(ignore) do { } while (0) - -#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ - __asm__ ( " .macro raw_local_irq_enable \n" " .set push \n" @@ -205,17 +185,28 @@ __asm__ ( " .set pop \n" " .endm \n"); -#define raw_local_irq_restore(flags) \ -do { \ - unsigned long __tmp1; \ - \ - __asm__ __volatile__( \ - "raw_local_irq_restore\t%0" \ - : "=r" (__tmp1) \ - : "0" (flags) \ - : "memory"); \ - irq_restore_epilog(flags); \ -} while(0) +extern void smtc_ipi_replay(void); + +static inline void raw_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + +#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY + /* + * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred + * IPIs, at the cost of branch and call overhead on each + * local_irq_restore() + */ + if (unlikely(!(flags & 0x0400))) + smtc_ipi_replay(); +#endif + + __asm__ __volatile__( + "raw_local_irq_restore\t%0" + : "=r" (__tmp1) + : "0" (flags) + : "memory"); +} static inline int raw_irqs_disabled_flags(unsigned long flags) { -- cgit v1.2.3