Commit a3199ad90ac33c1afae0fa3dbf2e0fe4ee827fa7

Authored by Jesper Nilsson
1 parent 9f1ad51b32

CRISv32: ETRAXFS: Fix recursive spinlock

Move pinmux alloc/dealloc code into functions that don't take
the spinlock so we can use from code that has the spinlock already.

CRISv32 has no working SMP, so spinlocks becomes a NOP,
so deadlock was never seen.

Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>

Showing 2 changed files with 83 additions and 71 deletions Side-by-side Diff

arch/cris/arch-v32/mach-fs/pinmux.c
... ... @@ -26,8 +26,30 @@
26 26  
27 27 static void crisv32_pinmux_set(int port);
28 28  
29   -int crisv32_pinmux_init(void)
  29 +static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
  30 + enum pin_mode mode)
30 31 {
  32 + int i;
  33 +
  34 + for (i = first_pin; i <= last_pin; i++) {
  35 + if ((pins[port][i] != pinmux_none)
  36 + && (pins[port][i] != pinmux_gpio)
  37 + && (pins[port][i] != mode)) {
  38 +#ifdef DEBUG
  39 + panic("Pinmux alloc failed!\n");
  40 +#endif
  41 + return -EPERM;
  42 + }
  43 + }
  44 +
  45 + for (i = first_pin; i <= last_pin; i++)
  46 + pins[port][i] = mode;
  47 +
  48 + crisv32_pinmux_set(port);
  49 +}
  50 +
  51 +static int crisv32_pinmux_init(void)
  52 +{
31 53 static int initialized;
32 54  
33 55 if (!initialized) {
34 56  
35 57  
36 58  
... ... @@ -37,20 +59,20 @@
37 59 pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
38 60 pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
39 61 REG_WR(pinmux, regi_pinmux, rw_pa, pa);
40   - crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
41   - crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
42   - crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
43   - crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
  62 + __crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
  63 + __crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
  64 + __crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
  65 + __crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
44 66 }
45 67  
46 68 return 0;
47 69 }
48 70  
49   -int
50   -crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
  71 +int crisv32_pinmux_alloc(int port, int first_pin, int last_pin,
  72 + enum pin_mode mode)
51 73 {
52   - int i;
53 74 unsigned long flags;
  75 + int ret;
54 76  
55 77 crisv32_pinmux_init();
56 78  
57 79  
58 80  
... ... @@ -59,26 +81,11 @@
59 81  
60 82 spin_lock_irqsave(&pinmux_lock, flags);
61 83  
62   - for (i = first_pin; i <= last_pin; i++) {
63   - if ((pins[port][i] != pinmux_none)
64   - && (pins[port][i] != pinmux_gpio)
65   - && (pins[port][i] != mode)) {
66   - spin_unlock_irqrestore(&pinmux_lock, flags);
67   -#ifdef DEBUG
68   - panic("Pinmux alloc failed!\n");
69   -#endif
70   - return -EPERM;
71   - }
72   - }
  84 + ret = __crisv32_pinmux_alloc(port, first_pin, last_pin, mode);
73 85  
74   - for (i = first_pin; i <= last_pin; i++)
75   - pins[port][i] = mode;
76   -
77   - crisv32_pinmux_set(port);
78   -
79 86 spin_unlock_irqrestore(&pinmux_lock, flags);
80 87  
81   - return 0;
  88 + return ret;
82 89 }
83 90  
84 91 int crisv32_pinmux_alloc_fixed(enum fixed_function function)
85 92  
86 93  
87 94  
88 95  
89 96  
90 97  
91 98  
92 99  
93 100  
94 101  
95 102  
... ... @@ -98,58 +105,58 @@
98 105  
99 106 switch (function) {
100 107 case pinmux_ser1:
101   - ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
  108 + ret = __crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
102 109 hwprot.ser1 = regk_pinmux_yes;
103 110 break;
104 111 case pinmux_ser2:
105   - ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
  112 + ret = __crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
106 113 hwprot.ser2 = regk_pinmux_yes;
107 114 break;
108 115 case pinmux_ser3:
109   - ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
  116 + ret = __crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
110 117 hwprot.ser3 = regk_pinmux_yes;
111 118 break;
112 119 case pinmux_sser0:
113   - ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
114   - ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
  120 + ret = __crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
  121 + ret |= __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
115 122 hwprot.sser0 = regk_pinmux_yes;
116 123 break;
117 124 case pinmux_sser1:
118   - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
  125 + ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
119 126 hwprot.sser1 = regk_pinmux_yes;
120 127 break;
121 128 case pinmux_ata0:
122   - ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
123   - ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
  129 + ret = __crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
  130 + ret |= __crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
124 131 hwprot.ata0 = regk_pinmux_yes;
125 132 break;
126 133 case pinmux_ata1:
127   - ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
128   - ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
  134 + ret = __crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
  135 + ret |= __crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
129 136 hwprot.ata1 = regk_pinmux_yes;
130 137 break;
131 138 case pinmux_ata2:
132   - ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
133   - ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
  139 + ret = __crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
  140 + ret |= __crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
134 141 hwprot.ata2 = regk_pinmux_yes;
135 142 break;
136 143 case pinmux_ata3:
137   - ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
138   - ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
  144 + ret = __crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
  145 + ret |= __crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
139 146 hwprot.ata2 = regk_pinmux_yes;
140 147 break;
141 148 case pinmux_ata:
142   - ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
143   - ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
  149 + ret = __crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
  150 + ret |= __crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
144 151 hwprot.ata = regk_pinmux_yes;
145 152 break;
146 153 case pinmux_eth1:
147   - ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
  154 + ret = __crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
148 155 hwprot.eth1 = regk_pinmux_yes;
149 156 hwprot.eth1_mgm = regk_pinmux_yes;
150 157 break;
151 158 case pinmux_timer:
152   - ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
  159 + ret = __crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
153 160 hwprot.timer = regk_pinmux_yes;
154 161 spin_unlock_irqrestore(&pinmux_lock, flags);
155 162 return ret;
156 163  
... ... @@ -188,9 +195,19 @@
188 195 #endif
189 196 }
190 197  
191   -int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
  198 +static int __crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
192 199 {
193 200 int i;
  201 +
  202 + for (i = first_pin; i <= last_pin; i++)
  203 + pins[port][i] = pinmux_none;
  204 +
  205 + crisv32_pinmux_set(port);
  206 + return 0;
  207 +}
  208 +
  209 +int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
  210 +{
194 211 unsigned long flags;
195 212  
196 213 crisv32_pinmux_init();
... ... @@ -199,11 +216,7 @@
199 216 return -EINVAL;
200 217  
201 218 spin_lock_irqsave(&pinmux_lock, flags);
202   -
203   - for (i = first_pin; i <= last_pin; i++)
204   - pins[port][i] = pinmux_none;
205   -
206   - crisv32_pinmux_set(port);
  219 + __crisv32_pinmux_dealloc(port, first_pin, last_pin);
207 220 spin_unlock_irqrestore(&pinmux_lock, flags);
208 221  
209 222 return 0;
210 223  
211 224  
212 225  
213 226  
214 227  
215 228  
216 229  
217 230  
218 231  
219 232  
220 233  
... ... @@ -226,58 +239,58 @@
226 239  
227 240 switch (function) {
228 241 case pinmux_ser1:
229   - ret = crisv32_pinmux_dealloc(PORT_C, 4, 7);
  242 + ret = __crisv32_pinmux_dealloc(PORT_C, 4, 7);
230 243 hwprot.ser1 = regk_pinmux_no;
231 244 break;
232 245 case pinmux_ser2:
233   - ret = crisv32_pinmux_dealloc(PORT_C, 8, 11);
  246 + ret = __crisv32_pinmux_dealloc(PORT_C, 8, 11);
234 247 hwprot.ser2 = regk_pinmux_no;
235 248 break;
236 249 case pinmux_ser3:
237   - ret = crisv32_pinmux_dealloc(PORT_C, 12, 15);
  250 + ret = __crisv32_pinmux_dealloc(PORT_C, 12, 15);
238 251 hwprot.ser3 = regk_pinmux_no;
239 252 break;
240 253 case pinmux_sser0:
241   - ret = crisv32_pinmux_dealloc(PORT_C, 0, 3);
242   - ret |= crisv32_pinmux_dealloc(PORT_C, 16, 16);
  254 + ret = __crisv32_pinmux_dealloc(PORT_C, 0, 3);
  255 + ret |= __crisv32_pinmux_dealloc(PORT_C, 16, 16);
243 256 hwprot.sser0 = regk_pinmux_no;
244 257 break;
245 258 case pinmux_sser1:
246   - ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
  259 + ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
247 260 hwprot.sser1 = regk_pinmux_no;
248 261 break;
249 262 case pinmux_ata0:
250   - ret = crisv32_pinmux_dealloc(PORT_D, 5, 7);
251   - ret |= crisv32_pinmux_dealloc(PORT_D, 15, 17);
  263 + ret = __crisv32_pinmux_dealloc(PORT_D, 5, 7);
  264 + ret |= __crisv32_pinmux_dealloc(PORT_D, 15, 17);
252 265 hwprot.ata0 = regk_pinmux_no;
253 266 break;
254 267 case pinmux_ata1:
255   - ret = crisv32_pinmux_dealloc(PORT_D, 0, 4);
256   - ret |= crisv32_pinmux_dealloc(PORT_E, 17, 17);
  268 + ret = __crisv32_pinmux_dealloc(PORT_D, 0, 4);
  269 + ret |= __crisv32_pinmux_dealloc(PORT_E, 17, 17);
257 270 hwprot.ata1 = regk_pinmux_no;
258 271 break;
259 272 case pinmux_ata2:
260   - ret = crisv32_pinmux_dealloc(PORT_C, 11, 15);
261   - ret |= crisv32_pinmux_dealloc(PORT_E, 3, 3);
  273 + ret = __crisv32_pinmux_dealloc(PORT_C, 11, 15);
  274 + ret |= __crisv32_pinmux_dealloc(PORT_E, 3, 3);
262 275 hwprot.ata2 = regk_pinmux_no;
263 276 break;
264 277 case pinmux_ata3:
265   - ret = crisv32_pinmux_dealloc(PORT_C, 8, 10);
266   - ret |= crisv32_pinmux_dealloc(PORT_C, 0, 2);
  278 + ret = __crisv32_pinmux_dealloc(PORT_C, 8, 10);
  279 + ret |= __crisv32_pinmux_dealloc(PORT_C, 0, 2);
267 280 hwprot.ata2 = regk_pinmux_no;
268 281 break;
269 282 case pinmux_ata:
270   - ret = crisv32_pinmux_dealloc(PORT_B, 0, 15);
271   - ret |= crisv32_pinmux_dealloc(PORT_D, 8, 15);
  283 + ret = __crisv32_pinmux_dealloc(PORT_B, 0, 15);
  284 + ret |= __crisv32_pinmux_dealloc(PORT_D, 8, 15);
272 285 hwprot.ata = regk_pinmux_no;
273 286 break;
274 287 case pinmux_eth1:
275   - ret = crisv32_pinmux_dealloc(PORT_E, 0, 17);
  288 + ret = __crisv32_pinmux_dealloc(PORT_E, 0, 17);
276 289 hwprot.eth1 = regk_pinmux_no;
277 290 hwprot.eth1_mgm = regk_pinmux_no;
278 291 break;
279 292 case pinmux_timer:
280   - ret = crisv32_pinmux_dealloc(PORT_C, 16, 16);
  293 + ret = __crisv32_pinmux_dealloc(PORT_C, 16, 16);
281 294 hwprot.timer = regk_pinmux_no;
282 295 spin_unlock_irqrestore(&pinmux_lock, flags);
283 296 return ret;
... ... @@ -293,7 +306,8 @@
293 306 return ret;
294 307 }
295 308  
296   -void crisv32_pinmux_dump(void)
  309 +#ifdef DEBUG
  310 +static void crisv32_pinmux_dump(void)
297 311 {
298 312 int i, j;
299 313  
... ... @@ -305,6 +319,6 @@
305 319 printk(KERN_DEBUG " Pin %d = %d\n", j, pins[i][j]);
306 320 }
307 321 }
308   -
  322 +#endif
309 323 __initcall(crisv32_pinmux_init);
arch/cris/include/arch-v32/mach-fs/mach/pinmux.h
... ... @@ -28,12 +28,10 @@
28 28 pinmux_timer
29 29 };
30 30  
31   -int crisv32_pinmux_init(void);
32 31 int crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode);
33 32 int crisv32_pinmux_alloc_fixed(enum fixed_function function);
34 33 int crisv32_pinmux_dealloc(int port, int first_pin, int last_pin);
35 34 int crisv32_pinmux_dealloc_fixed(enum fixed_function function);
36   -void crisv32_pinmux_dump(void);
37 35  
38 36 #endif