mac80211: update brcmfmac backporting brcmf_err cleanups
[openwrt/openwrt.git] / target / linux / generic / patches-4.9 / 040-04-MIPS-Switch-to-the-irq_stack-in-interrupts.patch
1 From: Matt Redfearn <matt.redfearn@imgtec.com>
2 Date: Mon, 19 Dec 2016 14:20:59 +0000
3 Subject: [PATCH] MIPS: Switch to the irq_stack in interrupts
4
5 When enterring interrupt context via handle_int or except_vec_vi, switch
6 to the irq_stack of the current CPU if it is not already in use.
7
8 The current stack pointer is masked with the thread size and compared to
9 the base or the irq stack. If it does not match then the stack pointer
10 is set to the top of that stack, otherwise this is a nested irq being
11 handled on the irq stack so the stack pointer should be left as it was.
12
13 The in-use stack pointer is placed in the callee saved register s1. It
14 will be saved to the stack when plat_irq_dispatch is invoked and can be
15 restored once control returns here.
16
17 Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com>
18 ---
19
20 --- a/arch/mips/kernel/genex.S
21 +++ b/arch/mips/kernel/genex.S
22 @@ -187,9 +187,44 @@ NESTED(handle_int, PT_SIZE, sp)
23
24 LONG_L s0, TI_REGS($28)
25 LONG_S sp, TI_REGS($28)
26 - PTR_LA ra, ret_from_irq
27 - PTR_LA v0, plat_irq_dispatch
28 - jr v0
29 +
30 + /*
31 + * SAVE_ALL ensures we are using a valid kernel stack for the thread.
32 + * Check if we are already using the IRQ stack.
33 + */
34 + move s1, sp # Preserve the sp
35 +
36 + /* Get IRQ stack for this CPU */
37 + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
38 +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
39 + lui k1, %hi(irq_stack)
40 +#else
41 + lui k1, %highest(irq_stack)
42 + daddiu k1, %higher(irq_stack)
43 + dsll k1, 16
44 + daddiu k1, %hi(irq_stack)
45 + dsll k1, 16
46 +#endif
47 + LONG_SRL k0, SMP_CPUID_PTRSHIFT
48 + LONG_ADDU k1, k0
49 + LONG_L t0, %lo(irq_stack)(k1)
50 +
51 + # Check if already on IRQ stack
52 + PTR_LI t1, ~(_THREAD_SIZE-1)
53 + and t1, t1, sp
54 + beq t0, t1, 2f
55 +
56 + /* Switch to IRQ stack */
57 + li t1, _IRQ_STACK_SIZE
58 + PTR_ADD sp, t0, t1
59 +
60 +2:
61 + jal plat_irq_dispatch
62 +
63 + /* Restore sp */
64 + move sp, s1
65 +
66 + j ret_from_irq
67 #ifdef CONFIG_CPU_MICROMIPS
68 nop
69 #endif
70 @@ -262,8 +297,44 @@ NESTED(except_vec_vi_handler, 0, sp)
71
72 LONG_L s0, TI_REGS($28)
73 LONG_S sp, TI_REGS($28)
74 - PTR_LA ra, ret_from_irq
75 - jr v0
76 +
77 + /*
78 + * SAVE_ALL ensures we are using a valid kernel stack for the thread.
79 + * Check if we are already using the IRQ stack.
80 + */
81 + move s1, sp # Preserve the sp
82 +
83 + /* Get IRQ stack for this CPU */
84 + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
85 +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
86 + lui k1, %hi(irq_stack)
87 +#else
88 + lui k1, %highest(irq_stack)
89 + daddiu k1, %higher(irq_stack)
90 + dsll k1, 16
91 + daddiu k1, %hi(irq_stack)
92 + dsll k1, 16
93 +#endif
94 + LONG_SRL k0, SMP_CPUID_PTRSHIFT
95 + LONG_ADDU k1, k0
96 + LONG_L t0, %lo(irq_stack)(k1)
97 +
98 + # Check if already on IRQ stack
99 + PTR_LI t1, ~(_THREAD_SIZE-1)
100 + and t1, t1, sp
101 + beq t0, t1, 2f
102 +
103 + /* Switch to IRQ stack */
104 + li t1, _IRQ_STACK_SIZE
105 + PTR_ADD sp, t0, t1
106 +
107 +2:
108 + jal plat_irq_dispatch
109 +
110 + /* Restore sp */
111 + move sp, s1
112 +
113 + j ret_from_irq
114 END(except_vec_vi_handler)
115
116 /*