Commit a3199ad90ac33c1afae0fa3dbf2e0fe4ee827fa7
1 parent
9f1ad51b32
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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 |