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