This patch adds a menuconfig option that allows controlling
the lazy interrupt disabling feature implemented by this
commit:

commit d04c56f73c30a5e593202ecfcf25ed43d42363a2
Author: Paul Mackerras
Date:   Wed Oct 4 16:47:49 2006 +1000

    [POWERPC] Lazy interrupt disabling for 64-bit machines

The code in 'powerpc/include/asm/hw_irq.h' was rearranged and
cleaned-up a bit in order to reduce the number of needed #ifdef's.

Signed-off-by: Laurentiu Tudor <laurentiu.tu...@freescale.com>
---
Patch is against
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next

 arch/powerpc/Kconfig                 |   16 ++++++
 arch/powerpc/include/asm/hw_irq.h    |   86 ++++++++++++++--------------------
 arch/powerpc/include/asm/irqflags.h  |   22 +++++++++
 arch/powerpc/include/asm/paca.h      |    4 ++
 arch/powerpc/kernel/asm-offsets.c    |    3 +
 arch/powerpc/kernel/entry_64.S       |    4 ++
 arch/powerpc/kernel/exceptions-64e.S |   36 +++++++++++---
 arch/powerpc/kernel/head_64.S        |   10 ++++
 arch/powerpc/kernel/idle_book3e.S    |    7 +++
 arch/powerpc/kernel/irq.c            |    5 ++
 arch/powerpc/kernel/setup_64.c       |    2 +
 11 files changed, 138 insertions(+), 57 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ce5e045..2792278 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -609,6 +609,22 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
+config PPC_LAZY_EE
+       bool
+       prompt "Lazy interrupt disabling" if PPC_BOOK3E_64
+       default y if PPC_BOOK3S_64
+       help
+         Local interrupt disabling functions don't disable
+         interrupts right away and instead just clear an
+         internal 'interrupts are enabled' flag. If an
+         interrupt is triggered during this time, the
+         interrupt handling code checks the flag, and if
+         interrupts are supposed to be off, disables them
+         for real and returns, skipping interrupt handling.
+         When interrupts are enabled back, the interrupt
+         fires again and this time gets handled.
+
+         If unsure, say N.
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/hw_irq.h 
b/arch/powerpc/include/asm/hw_irq.h
index bb712c9..6f32593 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -13,7 +13,20 @@
 
 extern void timer_interrupt(struct pt_regs *);
 
+#ifdef CONFIG_BOOKE
+#define __hard_irq_enable()    asm volatile("wrteei 1" : : : "memory");
+#define __hard_irq_disable()   asm volatile("wrteei 0" : : : "memory");
+#else
 #ifdef CONFIG_PPC64
+#define __hard_irq_enable()    __mtmsrd(mfmsr() | MSR_EE, 1)
+#define __hard_irq_disable()   __mtmsrd(mfmsr() & ~MSR_EE, 1)
+#else
+#define __hard_irq_enable()    mtmsr(mfmsr() | MSR_EE)
+#define __hard_irq_disable()   mtmsr(mfmsr() & ~MSR_EE)
+#endif
+#endif /* CONFIG_BOOKE */
+
+#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_LAZY_EE)
 #include <asm/paca.h>
 
 static inline unsigned long arch_local_save_flags(void)
@@ -49,9 +62,11 @@ static inline void arch_local_irq_enable(void)
        arch_local_irq_restore(1);
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void hard_irq_disable(void)
 {
-       return arch_local_irq_disable();
+       __hard_irq_disable();
+       get_paca()->soft_enabled = 0;
+       get_paca()->hard_enabled = 0;
 }
 
 static inline bool arch_irqs_disabled_flags(unsigned long flags)
@@ -59,29 +74,7 @@ static inline bool arch_irqs_disabled_flags(unsigned long 
flags)
        return flags == 0;
 }
 
-static inline bool arch_irqs_disabled(void)
-{
-       return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-#ifdef CONFIG_PPC_BOOK3E
-#define __hard_irq_enable()    asm volatile("wrteei 1" : : : "memory");
-#define __hard_irq_disable()   asm volatile("wrteei 0" : : : "memory");
-#else
-#define __hard_irq_enable()    __mtmsrd(mfmsr() | MSR_EE, 1)
-#define __hard_irq_disable()   __mtmsrd(mfmsr() & ~MSR_EE, 1)
-#endif
-
-#define  hard_irq_disable()                    \
-       do {                                    \
-               __hard_irq_disable();           \
-               get_paca()->soft_enabled = 0;   \
-               get_paca()->hard_enabled = 0;   \
-       } while(0)
-
-#else /* CONFIG_PPC64 */
-
-#define SET_MSR_EE(x)  mtmsr(x)
+#else /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
 
 static inline unsigned long arch_local_save_flags(void)
 {
@@ -97,34 +90,24 @@ static inline void arch_local_irq_restore(unsigned long 
flags)
 #endif
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void arch_local_irq_enable(void)
 {
-       unsigned long flags = arch_local_save_flags();
-#ifdef CONFIG_BOOKE
-       asm volatile("wrteei 0" : : : "memory");
-#else
-       SET_MSR_EE(flags & ~MSR_EE);
-#endif
-       return flags;
+       __hard_irq_enable();
 }
 
-static inline void arch_local_irq_disable(void)
+static inline unsigned long arch_local_irq_disable(void)
 {
-#ifdef CONFIG_BOOKE
-       asm volatile("wrteei 0" : : : "memory");
-#else
-       arch_local_irq_save();
-#endif
+       unsigned long flags;
+
+       flags = arch_local_save_flags();
+       __hard_irq_disable();
+
+       return flags;
 }
 
-static inline void arch_local_irq_enable(void)
+static inline void hard_irq_disable(void)
 {
-#ifdef CONFIG_BOOKE
-       asm volatile("wrteei 1" : : : "memory");
-#else
-       unsigned long msr = mfmsr();
-       SET_MSR_EE(msr | MSR_EE);
-#endif
+       __hard_irq_disable();
 }
 
 static inline bool arch_irqs_disabled_flags(unsigned long flags)
@@ -132,15 +115,18 @@ static inline bool arch_irqs_disabled_flags(unsigned long 
flags)
        return (flags & MSR_EE) == 0;
 }
 
+#endif /* CONFIG_PPC64 && CONFIG_PPC_LAZY_EE */
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       return arch_local_irq_disable();
+}
+
 static inline bool arch_irqs_disabled(void)
 {
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
-#define hard_irq_disable()             arch_local_irq_disable()
-
-#endif /* CONFIG_PPC64 */
-
 #define ARCH_IRQ_INIT_FLAGS    IRQ_NOREQUEST
 
 /*
diff --git a/arch/powerpc/include/asm/irqflags.h 
b/arch/powerpc/include/asm/irqflags.h
index b0b06d8..9685b75c 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -39,6 +39,8 @@
 #define TRACE_ENABLE_INTS      TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
 #define TRACE_DISABLE_INTS     TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
 
+#ifdef CONFIG_PPC_LAZY_EE
+
 #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)         \
        cmpdi   en,0;                                   \
        bne     95f;                                    \
@@ -51,12 +53,32 @@
        TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);  \
        stb     en,PACASOFTIRQEN(r13);          \
 96:
+
+#else /* CONFIG_PPC_LAZY_EE */
+
+#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)         \
+       cmpdi   en,0;                                   \
+       bne     95f;                                    \
+       TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)    \
+       b       skip;                                   \
+95:    TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)     \
+       li      en,1;
+#define TRACE_AND_RESTORE_IRQ(en)              \
+       TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f);  \
+96:
+
+#endif /* CONFIG_PPC_LAZY_EE */
+
 #else
 #define TRACE_ENABLE_INTS
 #define TRACE_DISABLE_INTS
 #define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip)
+#ifdef CONFIG_PPC_LAZY_EE
 #define TRACE_AND_RESTORE_IRQ(en)              \
        stb     en,PACASOFTIRQEN(r13)
+#else
+#define TRACE_AND_RESTORE_IRQ(en)
+#endif
 #endif
 #endif
 
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 269c05a..b74c2b1 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -131,8 +131,12 @@ struct paca_struct {
        u64 saved_r1;                   /* r1 save for RTAS calls or PM */
        u64 saved_msr;                  /* MSR saved here by enter_rtas */
        u16 trap_save;                  /* Used when bad stack is encountered */
+
+#ifdef CONFIG_PPC_LAZY_EE
        u8 soft_enabled;                /* irq soft-enable flag */
        u8 hard_enabled;                /* set if irqs are enabled in MSR */
+#endif
+
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while 
soft-disable */
        u8 nap_state_lost;              /* NV GPR values lost in power7_idle */
diff --git a/arch/powerpc/kernel/asm-offsets.c 
b/arch/powerpc/kernel/asm-offsets.c
index 04caee7..5b1fac9 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -146,8 +146,11 @@ int main(void)
        DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
        DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
        DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
+#ifdef CONFIG_PPC_LAZY_EE
        DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
        DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
+#endif
+
        DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
 #ifdef CONFIG_PPC_MM_SLICES
        DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d834425..ce7620b 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -124,8 +124,10 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
        ld      r12,_MSR(r1)
 #endif /* CONFIG_TRACE_IRQFLAGS */
        li      r10,1
+#ifdef CONFIG_PPC_LAZY_EE
        stb     r10,PACASOFTIRQEN(r13)
        stb     r10,PACAHARDIRQEN(r13)
+#endif
        std     r10,SOFTE(r1)
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
@@ -602,10 +604,12 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
 2:
        TRACE_AND_RESTORE_IRQ(r5);
 
+#ifdef CONFIG_PPC_LAZY_EE
        /* extract EE bit and use it to restore paca->hard_enabled */
        ld      r3,_MSR(r1)
        rldicl  r4,r3,49,63             /* r0 = (r3 >> 15) & 1 */
        stb     r4,PACAHARDIRQEN(r13)
+#endif
 
 #ifdef CONFIG_PPC_BOOK3E
        b       .exception_return_book3e
diff --git a/arch/powerpc/kernel/exceptions-64e.S 
b/arch/powerpc/kernel/exceptions-64e.S
index 429983c..d17abb3 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -96,11 +96,6 @@
 #define PROLOG_ADDITION_NONE_DBG
 #define PROLOG_ADDITION_NONE_MC
 
-#define PROLOG_ADDITION_MASKABLE_GEN                                       \
-       lbz     r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
-       cmpwi   cr0,r11,0;              /* yes -> go out of line */         \
-       beq     masked_interrupt_book3e;
-
 #define PROLOG_ADDITION_2REGS_GEN                                          \
        std     r14,PACA_EXGEN+EX_R14(r13);                                 \
        std     r15,PACA_EXGEN+EX_R15(r13)
@@ -120,11 +115,29 @@
        std     r14,PACA_EXMC+EX_R14(r13);                                  \
        std     r15,PACA_EXMC+EX_R15(r13)
 
+#ifdef CONFIG_PPC_LAZY_EE
+#define PROLOG_ADDITION_MASKABLE_GEN                                       \
+       lbz     r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
+       cmpwi   cr0,r11,0;              /* yes -> go out of line */         \
+       beq     masked_interrupt_book3e;
+
 #define PROLOG_ADDITION_DOORBELL_GEN                                       \
        lbz     r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
        cmpwi   cr0,r11,0;              /* yes -> go out of line */         \
        beq     masked_doorbell_book3e
-
+#else /* CONFIG_PPC_LAZY_EE */
+#define PROLOG_ADDITION_MASKABLE_GEN
+#define PROLOG_ADDITION_DOORBELL_GEN
+#endif /* CONFIG_PPC_LAZY_EE */
+
+#ifdef CONFIG_PPC_LAZY_EE
+#define GET_IRQ_SOFT_ENABLED                                               \
+       lbz     r11,PACASOFTIRQEN(r13)
+#else
+#define GET_IRQ_SOFT_ENABLED                                               \
+       mfmsr   r11;                                                        \
+       rlwimi  r11,r11,0,16,16
+#endif
 
 /* Core exception code for all exceptions except TLB misses.
  * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
@@ -148,7 +161,7 @@
        mfspr   r8,SPRN_XER;            /* save XER in stackframe */        \
        ld      r9,excf+EX_R1(r13);     /* load orig r1 back from PACA */   \
        lwz     r10,excf+EX_CR(r13);    /* load orig CR back from PACA  */  \
-       lbz     r11,PACASOFTIRQEN(r13); /* get current IRQ softe */         \
+       GET_IRQ_SOFT_ENABLED;           /* get current IRQ softe */         \
        ld      r12,exception_marker@toc(r2);                               \
        li      r0,0;                                                       \
        std     r3,GPR10(r1);           /* save r10 to stackframe */        \
@@ -169,11 +182,18 @@
 
 /* Variants for the "ints" argument */
 #define INTS_KEEP
+
+#ifdef CONFIG_PPC_LAZY_EE
 #define INTS_DISABLE_SOFT                                                  \
        stb     r0,PACASOFTIRQEN(r13);  /* mark interrupts soft-disabled */ \
        TRACE_DISABLE_INTS;
 #define INTS_DISABLE_HARD                                                  \
        stb     r0,PACAHARDIRQEN(r13); /* and hard disabled */
+#else
+#define INTS_DISABLE_SOFT
+#define INTS_DISABLE_HARD
+#endif
+
 #define INTS_DISABLE_ALL                                                   \
        INTS_DISABLE_SOFT                                                   \
        INTS_DISABLE_HARD
@@ -553,6 +573,7 @@ kernel_dbg_exc:
        MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
 
 
+#ifdef CONFIG_PPC_LAZY_EE
 /*
  * An interrupt came in while soft-disabled; clear EE in SRR1,
  * clear paca->hard_enabled and return.
@@ -577,6 +598,7 @@ masked_interrupt_book3e_common:
        mfspr   r13,SPRN_SPRG_GEN_SCRATCH;
        rfi
        b       .
+#endif /* CONFIG_PPC_LAZY_EE */
 
 /*
  * This is called from 0x300 and 0x400 handlers after the prologs with
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 06c7251..017d669 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -559,12 +559,14 @@ _GLOBAL(pmac_secondary_start)
        add     r13,r13,r4              /* for this processor.          */
        SET_PACA(r13)                   /* Save vaddr of paca in an SPRG*/
 
+#ifdef CONFIG_PPC_LAZY_EE
        /* Mark interrupts soft and hard disabled (they might be enabled
         * in the PACA when doing hotplug)
         */
        li      r0,0
        stb     r0,PACASOFTIRQEN(r13)
        stb     r0,PACAHARDIRQEN(r13)
+#endif
 
        /* Create a temp kernel stack for use before relocation is on.  */
        ld      r1,PACAEMERGSP(r13)
@@ -621,14 +623,18 @@ __secondary_start:
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
        ori     r4,r4,MSR_EE
+#ifdef CONFIG_PPC_LAZY_EE
        li      r8,1
        stb     r8,PACAHARDIRQEN(r13)
+#endif
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_PPC_LAZY_EE
 BEGIN_FW_FTR_SECTION
        stb     r7,PACAHARDIRQEN(r13)
 END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
        stb     r7,PACASOFTIRQEN(r13)
+#endif
 
        mtspr   SPRN_SRR0,r3
        mtspr   SPRN_SRR1,r4
@@ -775,8 +781,10 @@ _INIT_GLOBAL(start_here_common)
 
        /* Load up the kernel context */
 5:
+#ifdef CONFIG_PPC_LAZY_EE
        li      r5,0
        stb     r5,PACASOFTIRQEN(r13)   /* Soft Disabled */
+#endif
 #ifdef CONFIG_PPC_ISERIES
 BEGIN_FW_FTR_SECTION
        mfmsr   r5
@@ -785,7 +793,9 @@ BEGIN_FW_FTR_SECTION
        li      r5,1
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
+#ifdef CONFIG_PPC_LAZY_EE
        stb     r5,PACAHARDIRQEN(r13)   /* Hard Disabled on others */
+#endif
 
        bl      .start_kernel
 
diff --git a/arch/powerpc/kernel/idle_book3e.S 
b/arch/powerpc/kernel/idle_book3e.S
index 16c002d..34b09e0 100644
--- a/arch/powerpc/kernel/idle_book3e.S
+++ b/arch/powerpc/kernel/idle_book3e.S
@@ -28,6 +28,7 @@ _GLOBAL(book3e_idle)
        /* Hard disable interrupts */
        wrteei  0
 
+#ifdef CONFIG_PPC_LAZY_EE
        /* Now check if an interrupt came in while we were soft disabled
         * since we may otherwise lose it (doorbells etc...). We know
         * that since PACAHARDIRQEN will have been cleared in that case.
@@ -35,6 +36,7 @@ _GLOBAL(book3e_idle)
        lbz     r3,PACAHARDIRQEN(r13)
        cmpwi   cr0,r3,0
        beqlr
+#endif
 
        /* Now we are going to mark ourselves as soft and hard enables in
         * order to be able to take interrupts while asleep. We inform lockdep
@@ -44,9 +46,12 @@ _GLOBAL(book3e_idle)
        stdu    r1,-128(r1)
        bl      .trace_hardirqs_on
 #endif
+
+#ifdef CONFIG_PPC_LAZY_EE
        li      r0,1
        stb     r0,PACASOFTIRQEN(r13)
        stb     r0,PACAHARDIRQEN(r13)
+#endif
        
        /* Interrupts will make use return to LR, so get something we want
         * in there
@@ -56,10 +61,12 @@ _GLOBAL(book3e_idle)
        /* Hard disable interrupts again */
        wrteei  0
 
+#ifdef CONFIG_PPC_LAZY_EE
        /* Mark them off again in the PACA as well */
        li      r0,0
        stb     r0,PACASOFTIRQEN(r13)
        stb     r0,PACAHARDIRQEN(r13)
+#endif
 
        /* Tell lockdep about it */
 #ifdef CONFIG_TRACE_IRQFLAGS
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 701d4ac..e2d1784 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -99,6 +99,8 @@ EXPORT_SYMBOL(irq_desc);
 
 int distribute_irqs = 1;
 
+#ifdef CONFIG_PPC_LAZY_EE
+
 static inline notrace unsigned long get_hard_enabled(void)
 {
        unsigned long enabled;
@@ -193,6 +195,9 @@ notrace void arch_local_irq_restore(unsigned long en)
        __hard_irq_enable();
 }
 EXPORT_SYMBOL(arch_local_irq_restore);
+
+#endif /* CONFIG_PPC_LAZY_EE */
+
 #endif /* CONFIG_PPC64 */
 
 int arch_show_interrupts(struct seq_file *p, int prec)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4cb8f1e..06f5b19 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -233,8 +233,10 @@ void __init early_setup(unsigned long dt_ptr)
 #ifdef CONFIG_SMP
 void early_setup_secondary(void)
 {
+#ifdef CONFIG_PPC_LAZY_EE
        /* Mark interrupts enabled in PACA */
        get_paca()->soft_enabled = 0;
+#endif
 
        /* Initialize the hash table or TLB handling */
        early_init_mmu_secondary();
-- 
1.7.5.1


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to