brcm63xx: update bmips patches with upstream submission
[openwrt.git] / target / linux / brcm63xx / patches-3.10 / 314-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch
1 From 7447daa9a0768db157bbb64585f5411389712d59 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 06/14] MIPS: BCM63XX: replace irq dispatch code with a
5  generic version
6
7 The generic version uses a variable length of u32 registers of u32/u64.
8 This allows easier support for longer registers without having to rewrite
9 verything.
10
11 This "generic" version is not slower than 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 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
15 ---
16  arch/mips/bcm63xx/irq.c |  130 ++++++++++++++++++++---------------------------
17  1 file changed, 56 insertions(+), 74 deletions(-)
18
19 --- a/arch/mips/bcm63xx/irq.c
20 +++ b/arch/mips/bcm63xx/irq.c
21 @@ -258,47 +258,65 @@ static inline void handle_internal(int i
22   * will resume the loop where it ended the last time we left this
23   * function.
24   */
25 -static void __dispatch_internal_32(void)
26 -{
27 -       u32 pending;
28 -       static int i;
29 -
30 -       pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
31 -
32 -       if (!pending)
33 -               return ;
34 -
35 -       while (1) {
36 -               int to_call = i;
37  
38 -               i = (i + 1) & 0x1f;
39 -               if (pending & (1 << to_call)) {
40 -                       handle_internal(to_call);
41 -                       break;
42 -               }
43 -       }
44 +#define BUILD_IPIC_INTERNAL(width)                                     \
45 +void __dispatch_internal_##width(void)                                 \
46 +{                                                                      \
47 +       u32 pending[width / 32];                                        \
48 +       unsigned int src, tgt;                                          \
49 +       bool irqs_pending = false;                                      \
50 +       static int i;                                                   \
51 +                                                                       \
52 +       /* read registers in reverse order */                           \
53 +       for (src = 0, tgt = (width / 32); src < (width / 32); src++) {  \
54 +               u32 val;                                                \
55 +                                                                       \
56 +               val = bcm_readl(irq_stat_addr + src * sizeof(u32));     \
57 +               val &= bcm_readl(irq_mask_addr + src * sizeof(u32));    \
58 +               pending[--tgt] = val;                                   \
59 +                                                                       \
60 +               if (val)                                                \
61 +                       irqs_pending = true;                            \
62 +       }                                                               \
63 +                                                                       \
64 +       if (!irqs_pending)                                              \
65 +               return;                                                 \
66 +                                                                       \
67 +       while (1) {                                                     \
68 +               int to_call = i;                                        \
69 +                                                                       \
70 +               i = (i + 1) & (width - 1);                              \
71 +               if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {  \
72 +                       handle_internal(to_call);                       \
73 +                       break;                                          \
74 +               }                                                       \
75 +       }                                                               \
76 +}                                                                      \
77 +                                                                       \
78 +static void __internal_irq_mask_##width(unsigned int irq)              \
79 +{                                                                      \
80 +       u32 val;                                                        \
81 +       unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
82 +       unsigned bit = irq & 0x1f;                                      \
83 +                                                                       \
84 +       val = bcm_readl(irq_mask_addr + reg * sizeof(u32));             \
85 +       val &= ~(1 << bit);                                             \
86 +       bcm_writel(val, irq_mask_addr + reg * sizeof(u32));             \
87 +}                                                                      \
88 +                                                                       \
89 +static void __internal_irq_unmask_##width(unsigned int irq)            \
90 +{                                                                      \
91 +       u32 val;                                                        \
92 +       unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
93 +       unsigned bit = irq & 0x1f;                                      \
94 +                                                                       \
95 +       val = bcm_readl(irq_mask_addr + reg * sizeof(u32));             \
96 +       val |= (1 << bit);                                              \
97 +       bcm_writel(val, irq_mask_addr + reg * sizeof(u32));             \
98  }
99  
100 -static void __dispatch_internal_64(void)
101 -{
102 -       u64 pending;
103 -       static int i;
104 -
105 -       pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
106 -
107 -       if (!pending)
108 -               return ;
109 -
110 -       while (1) {
111 -               int to_call = i;
112 -
113 -               i = (i + 1) & 0x3f;
114 -               if (pending & (1ull << to_call)) {
115 -                       handle_internal(to_call);
116 -                       break;
117 -               }
118 -       }
119 -}
120 +BUILD_IPIC_INTERNAL(32);
121 +BUILD_IPIC_INTERNAL(64);
122  
123  asmlinkage void plat_irq_dispatch(void)
124  {
125 @@ -335,42 +353,6 @@ asmlinkage void plat_irq_dispatch(void)
126   * internal IRQs operations: only mask/unmask on PERF irq mask
127   * register.
128   */
129 -static void __internal_irq_mask_32(unsigned int irq)
130 -{
131 -       u32 mask;
132 -
133 -       mask = bcm_readl(irq_mask_addr);
134 -       mask &= ~(1 << irq);
135 -       bcm_writel(mask, irq_mask_addr);
136 -}
137 -
138 -static void __internal_irq_mask_64(unsigned int irq)
139 -{
140 -       u64 mask;
141 -
142 -       mask = bcm_readq(irq_mask_addr);
143 -       mask &= ~(1ull << irq);
144 -       bcm_writeq(mask, irq_mask_addr);
145 -}
146 -
147 -static void __internal_irq_unmask_32(unsigned int irq)
148 -{
149 -       u32 mask;
150 -
151 -       mask = bcm_readl(irq_mask_addr);
152 -       mask |= (1 << irq);
153 -       bcm_writel(mask, irq_mask_addr);
154 -}
155 -
156 -static void __internal_irq_unmask_64(unsigned int irq)
157 -{
158 -       u64 mask;
159 -
160 -       mask = bcm_readq(irq_mask_addr);
161 -       mask |= (1ull << irq);
162 -       bcm_writeq(mask, irq_mask_addr);
163 -}
164 -
165  static void bcm63xx_internal_irq_mask(struct irq_data *d)
166  {
167         internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);