brcm63xx: update irq affinity code to latest version
[openwrt/svn-archive/archive.git] / target / linux / brcm63xx / patches-3.10 / 320-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch
1 From 39b46ed1c9fe71890566e129d9ac5feb8421b3b4 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jogo@openwrt.org>
3 Date: Thu, 18 Apr 2013 21:14:49 +0200
4 Subject: [PATCH 03/10] MIPS: BCM63XX: replace irq dispatch code with a generic
5 version
6
7 The generic version uses a variable length of u32 registers instead of u32/u64.
8 This allows easier support for "wider" registers without having to rewrite
9 everything.
10
11 This "generic" version is as fast as the old version in the best case
12 (i == next set bit), and twice as fast in the worst case in 64 bits.
13
14 Using a macro was chosen over a (forced) inline version because gcc generated
15 more compact code with the macro.
16
17 The change from (signed) int to unsigned int for i and to_call was intentional
18 as the value can be only between 0 and (width - 1) anyway, and allowed gcc to
19 optimise the code a bit further.
20
21 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
22 ---
23 arch/mips/bcm63xx/irq.c | 130 +++++++++++++++++++++---------------------------
24 1 file changed, 56 insertions(+), 74 deletions(-)
25
26 --- a/arch/mips/bcm63xx/irq.c
27 +++ b/arch/mips/bcm63xx/irq.c
28 @@ -51,47 +51,65 @@ static inline void handle_internal(int i
29 * will resume the loop where it ended the last time we left this
30 * function.
31 */
32 -static void __dispatch_internal_32(void)
33 -{
34 - u32 pending;
35 - static int i;
36 -
37 - pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
38 -
39 - if (!pending)
40 - return ;
41 -
42 - while (1) {
43 - int to_call = i;
44
45 - i = (i + 1) & 0x1f;
46 - if (pending & (1 << to_call)) {
47 - handle_internal(to_call);
48 - break;
49 - }
50 - }
51 +#define BUILD_IPIC_INTERNAL(width) \
52 +void __dispatch_internal_##width(void) \
53 +{ \
54 + u32 pending[width / 32]; \
55 + unsigned int src, tgt; \
56 + bool irqs_pending = false; \
57 + static unsigned int i; \
58 + \
59 + /* read registers in reverse order */ \
60 + for (src = 0, tgt = (width / 32); src < (width / 32); src++) { \
61 + u32 val; \
62 + \
63 + val = bcm_readl(irq_stat_addr + src * sizeof(u32)); \
64 + val &= bcm_readl(irq_mask_addr + src * sizeof(u32)); \
65 + pending[--tgt] = val; \
66 + \
67 + if (val) \
68 + irqs_pending = true; \
69 + } \
70 + \
71 + if (!irqs_pending) \
72 + return; \
73 + \
74 + while (1) { \
75 + unsigned int to_call = i; \
76 + \
77 + i = (i + 1) & (width - 1); \
78 + if (pending[to_call / 32] & (1 << (to_call & 0x1f))) { \
79 + handle_internal(to_call); \
80 + break; \
81 + } \
82 + } \
83 +} \
84 + \
85 +static void __internal_irq_mask_##width(unsigned int irq) \
86 +{ \
87 + u32 val; \
88 + unsigned reg = (irq / 32) ^ (width/32 - 1); \
89 + unsigned bit = irq & 0x1f; \
90 + \
91 + val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
92 + val &= ~(1 << bit); \
93 + bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
94 +} \
95 + \
96 +static void __internal_irq_unmask_##width(unsigned int irq) \
97 +{ \
98 + u32 val; \
99 + unsigned reg = (irq / 32) ^ (width/32 - 1); \
100 + unsigned bit = irq & 0x1f; \
101 + \
102 + val = bcm_readl(irq_mask_addr + reg * sizeof(u32)); \
103 + val |= (1 << bit); \
104 + bcm_writel(val, irq_mask_addr + reg * sizeof(u32)); \
105 }
106
107 -static void __dispatch_internal_64(void)
108 -{
109 - u64 pending;
110 - static int i;
111 -
112 - pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
113 -
114 - if (!pending)
115 - return ;
116 -
117 - while (1) {
118 - int to_call = i;
119 -
120 - i = (i + 1) & 0x3f;
121 - if (pending & (1ull << to_call)) {
122 - handle_internal(to_call);
123 - break;
124 - }
125 - }
126 -}
127 +BUILD_IPIC_INTERNAL(32);
128 +BUILD_IPIC_INTERNAL(64);
129
130 asmlinkage void plat_irq_dispatch(void)
131 {
132 @@ -128,42 +146,6 @@ asmlinkage void plat_irq_dispatch(void)
133 * internal IRQs operations: only mask/unmask on PERF irq mask
134 * register.
135 */
136 -static void __internal_irq_mask_32(unsigned int irq)
137 -{
138 - u32 mask;
139 -
140 - mask = bcm_readl(irq_mask_addr);
141 - mask &= ~(1 << irq);
142 - bcm_writel(mask, irq_mask_addr);
143 -}
144 -
145 -static void __internal_irq_mask_64(unsigned int irq)
146 -{
147 - u64 mask;
148 -
149 - mask = bcm_readq(irq_mask_addr);
150 - mask &= ~(1ull << irq);
151 - bcm_writeq(mask, irq_mask_addr);
152 -}
153 -
154 -static void __internal_irq_unmask_32(unsigned int irq)
155 -{
156 - u32 mask;
157 -
158 - mask = bcm_readl(irq_mask_addr);
159 - mask |= (1 << irq);
160 - bcm_writel(mask, irq_mask_addr);
161 -}
162 -
163 -static void __internal_irq_unmask_64(unsigned int irq)
164 -{
165 - u64 mask;
166 -
167 - mask = bcm_readq(irq_mask_addr);
168 - mask |= (1ull << irq);
169 - bcm_writeq(mask, irq_mask_addr);
170 -}
171 -
172 static void bcm63xx_internal_irq_mask(struct irq_data *d)
173 {
174 internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);