diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-06-06 01:18:38 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-07 12:10:09 -0400 |
commit | 97664a207bc2601a03a300f00e6922038cd5b99c (patch) | |
tree | 19202c1dc78068e52a337cf34bff79d7c6e1b92f | |
parent | 8a2c225ddb2d23a9b3f70af2ec70d28e4abd0b8e (diff) |
usb: renesas_usbhs: shrink spin lock area
spin lock was very effective while doing 1 packet send/recv on
current renesas_usbhs driver.
But this lock is enough only
- modify packet/pipe link
- modify interrpt mask
- modify fifo access
This patch shrink spin lock area
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 4 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 138 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.h | 17 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 309 |
4 files changed, 177 insertions, 291 deletions
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index 0aadcb402764..7bf675c23a5e 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -204,6 +204,10 @@ void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data); | |||
204 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); | 204 | void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data); |
205 | 205 | ||
206 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev); | 206 | int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev); |
207 | |||
208 | #define usbhs_lock(p, f) spin_lock_irqsave(usbhs_priv_to_lock(p), f) | ||
209 | #define usbhs_unlock(p, f) spin_unlock_irqrestore(usbhs_priv_to_lock(p), f) | ||
210 | |||
207 | /* | 211 | /* |
208 | * sysconfig | 212 | * sysconfig |
209 | */ | 213 | */ |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index e9c4d3d8ef6e..3cda71e5a35a 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -22,7 +22,7 @@ | |||
22 | /* | 22 | /* |
23 | * packet info function | 23 | * packet info function |
24 | */ | 24 | */ |
25 | static int usbhsf_null_handle(struct usbhs_pkt *pkt) | 25 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) |
26 | { | 26 | { |
27 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | 27 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); |
28 | struct device *dev = usbhs_priv_to_dev(priv); | 28 | struct device *dev = usbhs_priv_to_dev(priv); |
@@ -48,6 +48,10 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | |||
48 | { | 48 | { |
49 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 49 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
50 | struct device *dev = usbhs_priv_to_dev(priv); | 50 | struct device *dev = usbhs_priv_to_dev(priv); |
51 | unsigned long flags; | ||
52 | |||
53 | /******************** spin lock ********************/ | ||
54 | usbhs_lock(priv, flags); | ||
51 | 55 | ||
52 | if (!handler) { | 56 | if (!handler) { |
53 | dev_err(dev, "no handler function\n"); | 57 | dev_err(dev, "no handler function\n"); |
@@ -63,14 +67,17 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | |||
63 | pkt->length = len; | 67 | pkt->length = len; |
64 | pkt->zero = zero; | 68 | pkt->zero = zero; |
65 | pkt->actual = 0; | 69 | pkt->actual = 0; |
70 | |||
71 | usbhs_unlock(priv, flags); | ||
72 | /******************** spin unlock ******************/ | ||
66 | } | 73 | } |
67 | 74 | ||
68 | void usbhs_pkt_pop(struct usbhs_pkt *pkt) | 75 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) |
69 | { | 76 | { |
70 | list_del_init(&pkt->node); | 77 | list_del_init(&pkt->node); |
71 | } | 78 | } |
72 | 79 | ||
73 | struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe) | 80 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) |
74 | { | 81 | { |
75 | if (list_empty(&pipe->list)) | 82 | if (list_empty(&pipe->list)) |
76 | return NULL; | 83 | return NULL; |
@@ -78,6 +85,71 @@ struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe) | |||
78 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | 85 | return list_entry(pipe->list.next, struct usbhs_pkt, node); |
79 | } | 86 | } |
80 | 87 | ||
88 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | ||
89 | { | ||
90 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
91 | unsigned long flags; | ||
92 | |||
93 | /******************** spin lock ********************/ | ||
94 | usbhs_lock(priv, flags); | ||
95 | |||
96 | if (!pkt) | ||
97 | pkt = __usbhsf_pkt_get(pipe); | ||
98 | |||
99 | if (pkt) | ||
100 | __usbhsf_pkt_del(pkt); | ||
101 | |||
102 | usbhs_unlock(priv, flags); | ||
103 | /******************** spin unlock ******************/ | ||
104 | |||
105 | return pkt; | ||
106 | } | ||
107 | |||
108 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) | ||
109 | { | ||
110 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
111 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
112 | struct usbhs_pkt *pkt; | ||
113 | struct device *dev = usbhs_priv_to_dev(priv); | ||
114 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | ||
115 | unsigned long flags; | ||
116 | int ret = 0; | ||
117 | int is_done = 0; | ||
118 | |||
119 | /******************** spin lock ********************/ | ||
120 | usbhs_lock(priv, flags); | ||
121 | |||
122 | pkt = __usbhsf_pkt_get(pipe); | ||
123 | if (!pkt) | ||
124 | goto __usbhs_pkt_handler_end; | ||
125 | |||
126 | switch (type) { | ||
127 | case USBHSF_PKT_PREPARE: | ||
128 | func = pkt->handler->prepare; | ||
129 | break; | ||
130 | case USBHSF_PKT_TRY_RUN: | ||
131 | func = pkt->handler->try_run; | ||
132 | break; | ||
133 | default: | ||
134 | dev_err(dev, "unknown pkt hander\n"); | ||
135 | goto __usbhs_pkt_handler_end; | ||
136 | } | ||
137 | |||
138 | ret = func(pkt, &is_done); | ||
139 | |||
140 | if (is_done) | ||
141 | __usbhsf_pkt_del(pkt); | ||
142 | |||
143 | __usbhs_pkt_handler_end: | ||
144 | usbhs_unlock(priv, flags); | ||
145 | /******************** spin unlock ******************/ | ||
146 | |||
147 | if (is_done) | ||
148 | info->done(pkt); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
81 | /* | 153 | /* |
82 | * irq enable/disable function | 154 | * irq enable/disable function |
83 | */ | 155 | */ |
@@ -188,18 +260,17 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write) | |||
188 | /* | 260 | /* |
189 | * PIO fifo functions | 261 | * PIO fifo functions |
190 | */ | 262 | */ |
191 | static int usbhsf_try_push(struct usbhs_pkt *pkt) | 263 | static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done) |
192 | { | 264 | { |
193 | struct usbhs_pipe *pipe = pkt->pipe; | 265 | struct usbhs_pipe *pipe = pkt->pipe; |
194 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 266 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
195 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
196 | struct device *dev = usbhs_priv_to_dev(priv); | 267 | struct device *dev = usbhs_priv_to_dev(priv); |
197 | void __iomem *addr = priv->base + CFIFO; | 268 | void __iomem *addr = priv->base + CFIFO; |
198 | u8 *buf; | 269 | u8 *buf; |
199 | int maxp = usbhs_pipe_get_maxpacket(pipe); | 270 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
200 | int total_len; | 271 | int total_len; |
201 | int i, ret, len; | 272 | int i, ret, len; |
202 | int is_short, is_done; | 273 | int is_short; |
203 | 274 | ||
204 | ret = usbhsf_fifo_select(pipe, 1); | 275 | ret = usbhsf_fifo_select(pipe, 1); |
205 | if (ret < 0) | 276 | if (ret < 0) |
@@ -240,11 +311,11 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt) | |||
240 | pkt->actual += total_len; | 311 | pkt->actual += total_len; |
241 | 312 | ||
242 | if (pkt->actual < pkt->length) | 313 | if (pkt->actual < pkt->length) |
243 | is_done = 0; /* there are remainder data */ | 314 | *is_done = 0; /* there are remainder data */ |
244 | else if (is_short) | 315 | else if (is_short) |
245 | is_done = 1; /* short packet */ | 316 | *is_done = 1; /* short packet */ |
246 | else | 317 | else |
247 | is_done = !pkt->zero; /* send zero packet ? */ | 318 | *is_done = !pkt->zero; /* send zero packet ? */ |
248 | 319 | ||
249 | /* | 320 | /* |
250 | * pipe/irq handling | 321 | * pipe/irq handling |
@@ -252,21 +323,19 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt) | |||
252 | if (is_short) | 323 | if (is_short) |
253 | usbhsf_send_terminator(pipe); | 324 | usbhsf_send_terminator(pipe); |
254 | 325 | ||
255 | usbhsf_tx_irq_ctrl(pipe, !is_done); | 326 | usbhsf_tx_irq_ctrl(pipe, !*is_done); |
256 | usbhs_pipe_enable(pipe); | 327 | usbhs_pipe_enable(pipe); |
257 | 328 | ||
258 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | 329 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", |
259 | usbhs_pipe_number(pipe), | 330 | usbhs_pipe_number(pipe), |
260 | pkt->length, pkt->actual, is_done, pkt->zero); | 331 | pkt->length, pkt->actual, *is_done, pkt->zero); |
261 | 332 | ||
262 | /* | 333 | /* |
263 | * Transmission end | 334 | * Transmission end |
264 | */ | 335 | */ |
265 | if (is_done) { | 336 | if (*is_done) { |
266 | if (usbhs_pipe_is_dcp(pipe)) | 337 | if (usbhs_pipe_is_dcp(pipe)) |
267 | usbhs_dcp_control_transfer_done(pipe); | 338 | usbhs_dcp_control_transfer_done(pipe); |
268 | |||
269 | info->done(pkt); | ||
270 | } | 339 | } |
271 | 340 | ||
272 | return 0; | 341 | return 0; |
@@ -286,7 +355,7 @@ struct usbhs_pkt_handle usbhs_fifo_push_handler = { | |||
286 | .try_run = usbhsf_try_push, | 355 | .try_run = usbhsf_try_push, |
287 | }; | 356 | }; |
288 | 357 | ||
289 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt) | 358 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) |
290 | { | 359 | { |
291 | struct usbhs_pipe *pipe = pkt->pipe; | 360 | struct usbhs_pipe *pipe = pkt->pipe; |
292 | int ret; | 361 | int ret; |
@@ -304,7 +373,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt) | |||
304 | return ret; | 373 | return ret; |
305 | } | 374 | } |
306 | 375 | ||
307 | static int usbhsf_try_pop(struct usbhs_pkt *pkt) | 376 | static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done) |
308 | { | 377 | { |
309 | struct usbhs_pipe *pipe = pkt->pipe; | 378 | struct usbhs_pipe *pipe = pkt->pipe; |
310 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 379 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
@@ -316,7 +385,6 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt) | |||
316 | int rcv_len, len; | 385 | int rcv_len, len; |
317 | int i, ret; | 386 | int i, ret; |
318 | int total_len = 0; | 387 | int total_len = 0; |
319 | int is_done = 0; | ||
320 | 388 | ||
321 | ret = usbhsf_fifo_select(pipe, 0); | 389 | ret = usbhsf_fifo_select(pipe, 0); |
322 | if (ret < 0) | 390 | if (ret < 0) |
@@ -367,22 +435,16 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt) | |||
367 | 435 | ||
368 | usbhs_fifo_read_end: | 436 | usbhs_fifo_read_end: |
369 | if ((pkt->actual == pkt->length) || /* receive all data */ | 437 | if ((pkt->actual == pkt->length) || /* receive all data */ |
370 | (total_len < maxp)) /* short packet */ | 438 | (total_len < maxp)) { /* short packet */ |
371 | is_done = 1; | 439 | *is_done = 1; |
372 | |||
373 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | ||
374 | usbhs_pipe_number(pipe), | ||
375 | pkt->length, pkt->actual, is_done, pkt->zero); | ||
376 | |||
377 | if (is_done) { | ||
378 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
379 | |||
380 | usbhsf_rx_irq_ctrl(pipe, 0); | 440 | usbhsf_rx_irq_ctrl(pipe, 0); |
381 | usbhs_pipe_disable(pipe); | 441 | usbhs_pipe_disable(pipe); |
382 | |||
383 | info->done(pkt); | ||
384 | } | 442 | } |
385 | 443 | ||
444 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", | ||
445 | usbhs_pipe_number(pipe), | ||
446 | pkt->length, pkt->actual, *is_done, pkt->zero); | ||
447 | |||
386 | return 0; | 448 | return 0; |
387 | } | 449 | } |
388 | 450 | ||
@@ -394,15 +456,11 @@ struct usbhs_pkt_handle usbhs_fifo_pop_handler = { | |||
394 | /* | 456 | /* |
395 | * handler function | 457 | * handler function |
396 | */ | 458 | */ |
397 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt) | 459 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) |
398 | { | 460 | { |
399 | struct usbhs_pipe *pipe = pkt->pipe; | 461 | usbhs_dcp_control_transfer_done(pkt->pipe); |
400 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | ||
401 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | ||
402 | 462 | ||
403 | usbhs_dcp_control_transfer_done(pipe); | 463 | *is_done = 1; |
404 | |||
405 | info->done(pkt); | ||
406 | 464 | ||
407 | return 0; | 465 | return 0; |
408 | } | 466 | } |
@@ -419,7 +477,6 @@ static int usbhsf_irq_empty(struct usbhs_priv *priv, | |||
419 | struct usbhs_irq_state *irq_state) | 477 | struct usbhs_irq_state *irq_state) |
420 | { | 478 | { |
421 | struct usbhs_pipe *pipe; | 479 | struct usbhs_pipe *pipe; |
422 | struct usbhs_pkt *pkt; | ||
423 | struct device *dev = usbhs_priv_to_dev(priv); | 480 | struct device *dev = usbhs_priv_to_dev(priv); |
424 | int i, ret; | 481 | int i, ret; |
425 | 482 | ||
@@ -438,8 +495,7 @@ static int usbhsf_irq_empty(struct usbhs_priv *priv, | |||
438 | if (!(irq_state->bempsts & (1 << i))) | 495 | if (!(irq_state->bempsts & (1 << i))) |
439 | continue; | 496 | continue; |
440 | 497 | ||
441 | pkt = usbhs_pkt_get(pipe); | 498 | ret = usbhs_pkt_run(pipe); |
442 | ret = usbhs_pkt_run(pkt); | ||
443 | if (ret < 0) | 499 | if (ret < 0) |
444 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | 500 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); |
445 | } | 501 | } |
@@ -451,7 +507,6 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv, | |||
451 | struct usbhs_irq_state *irq_state) | 507 | struct usbhs_irq_state *irq_state) |
452 | { | 508 | { |
453 | struct usbhs_pipe *pipe; | 509 | struct usbhs_pipe *pipe; |
454 | struct usbhs_pkt *pkt; | ||
455 | struct device *dev = usbhs_priv_to_dev(priv); | 510 | struct device *dev = usbhs_priv_to_dev(priv); |
456 | int i, ret; | 511 | int i, ret; |
457 | 512 | ||
@@ -470,8 +525,7 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv, | |||
470 | if (!(irq_state->brdysts & (1 << i))) | 525 | if (!(irq_state->brdysts & (1 << i))) |
471 | continue; | 526 | continue; |
472 | 527 | ||
473 | pkt = usbhs_pkt_get(pipe); | 528 | ret = usbhs_pkt_run(pipe); |
474 | ret = usbhs_pkt_run(pkt); | ||
475 | if (ret < 0) | 529 | if (ret < 0) |
476 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | 530 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); |
477 | } | 531 | } |
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index eab3258e9834..fcb1ecef57da 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h | |||
@@ -31,8 +31,8 @@ struct usbhs_pkt { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct usbhs_pkt_handle { | 33 | struct usbhs_pkt_handle { |
34 | int (*prepare)(struct usbhs_pkt *pkt); | 34 | int (*prepare)(struct usbhs_pkt *pkt, int *is_done); |
35 | int (*try_run)(struct usbhs_pkt *pkt); | 35 | int (*try_run)(struct usbhs_pkt *pkt, int *is_done); |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* | 38 | /* |
@@ -44,6 +44,11 @@ void usbhs_fifo_quit(struct usbhs_priv *priv); | |||
44 | /* | 44 | /* |
45 | * packet info | 45 | * packet info |
46 | */ | 46 | */ |
47 | enum { | ||
48 | USBHSF_PKT_PREPARE, | ||
49 | USBHSF_PKT_TRY_RUN, | ||
50 | }; | ||
51 | |||
47 | extern struct usbhs_pkt_handle usbhs_fifo_push_handler; | 52 | extern struct usbhs_pkt_handle usbhs_fifo_push_handler; |
48 | extern struct usbhs_pkt_handle usbhs_fifo_pop_handler; | 53 | extern struct usbhs_pkt_handle usbhs_fifo_pop_handler; |
49 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; | 54 | extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; |
@@ -52,10 +57,10 @@ void usbhs_pkt_init(struct usbhs_pkt *pkt); | |||
52 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | 57 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
53 | struct usbhs_pkt_handle *handler, | 58 | struct usbhs_pkt_handle *handler, |
54 | void *buf, int len, int zero); | 59 | void *buf, int len, int zero); |
55 | void usbhs_pkt_pop(struct usbhs_pkt *pkt); | 60 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); |
56 | struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe); | 61 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type); |
57 | 62 | ||
58 | #define usbhs_pkt_start(p) ((p)->handler->prepare(p)) | 63 | #define usbhs_pkt_start(p) __usbhs_pkt_handler(p, USBHSF_PKT_PREPARE) |
59 | #define usbhs_pkt_run(p) ((p)->handler->try_run(p)) | 64 | #define usbhs_pkt_run(p) __usbhs_pkt_handler(p, USBHSF_PKT_TRY_RUN) |
60 | 65 | ||
61 | #endif /* RENESAS_USB_FIFO_H */ | 66 | #endif /* RENESAS_USB_FIFO_H */ |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 28b2b37f9661..b5a5ba7efb5e 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -92,7 +92,6 @@ struct usbhsg_recip_handle { | |||
92 | container_of(r, struct usbhsg_request, req) | 92 | container_of(r, struct usbhsg_request, req) |
93 | 93 | ||
94 | #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) | 94 | #define usbhsg_ep_to_uep(e) container_of(e, struct usbhsg_uep, ep) |
95 | #define usbhsg_gpriv_to_lock(gp) usbhs_priv_to_lock((gp)->mod.priv) | ||
96 | #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) | 95 | #define usbhsg_gpriv_to_dev(gp) usbhs_priv_to_dev((gp)->mod.priv) |
97 | #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) | 96 | #define usbhsg_gpriv_to_priv(gp) ((gp)->mod.priv) |
98 | #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) | 97 | #define usbhsg_gpriv_to_dcp(gp) ((gp)->uep) |
@@ -115,35 +114,6 @@ struct usbhsg_recip_handle { | |||
115 | #define usbhsg_status_has(gp, b) (gp->status & b) | 114 | #define usbhsg_status_has(gp, b) (gp->status & b) |
116 | 115 | ||
117 | /* | 116 | /* |
118 | * usbhsg_trylock | ||
119 | * | ||
120 | * This driver don't use spin_try_lock | ||
121 | * to avoid warning of CONFIG_DEBUG_SPINLOCK | ||
122 | */ | ||
123 | static spinlock_t *usbhsg_trylock(struct usbhsg_gpriv *gpriv, | ||
124 | unsigned long *flags) | ||
125 | { | ||
126 | spinlock_t *lock = usbhsg_gpriv_to_lock(gpriv); | ||
127 | |||
128 | /* check spin lock status | ||
129 | * to avoid deadlock/nest */ | ||
130 | if (spin_is_locked(lock)) | ||
131 | return NULL; | ||
132 | |||
133 | spin_lock_irqsave(lock, *flags); | ||
134 | |||
135 | return lock; | ||
136 | } | ||
137 | |||
138 | static void usbhsg_unlock(spinlock_t *lock, unsigned long *flags) | ||
139 | { | ||
140 | if (!lock) | ||
141 | return; | ||
142 | |||
143 | spin_unlock_irqrestore(lock, *flags); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * list push/pop | 117 | * list push/pop |
148 | */ | 118 | */ |
149 | static void usbhsg_queue_push(struct usbhsg_uep *uep, | 119 | static void usbhsg_queue_push(struct usbhsg_uep *uep, |
@@ -155,9 +125,6 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, | |||
155 | struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); | 125 | struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); |
156 | struct usb_request *req = &ureq->req; | 126 | struct usb_request *req = &ureq->req; |
157 | 127 | ||
158 | /* | ||
159 | ********* assume under spin lock ********* | ||
160 | */ | ||
161 | usbhs_pkt_push(pipe, pkt, uep->handler, | 128 | usbhs_pkt_push(pipe, pkt, uep->handler, |
162 | req->buf, req->length, req->zero); | 129 | req->buf, req->length, req->zero); |
163 | req->actual = 0; | 130 | req->actual = 0; |
@@ -168,44 +135,11 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, | |||
168 | req->length); | 135 | req->length); |
169 | } | 136 | } |
170 | 137 | ||
171 | static int usbhsg_queue_start(struct usbhsg_uep *uep) | 138 | static void usbhsg_queue_start(struct usbhsg_uep *uep) |
172 | { | 139 | { |
173 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
174 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 140 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
175 | struct usbhs_pkt *pkt; | ||
176 | spinlock_t *lock; | ||
177 | unsigned long flags; | ||
178 | int ret = 0; | ||
179 | |||
180 | /* | ||
181 | * CAUTION [*queue handler*] | ||
182 | * | ||
183 | * This function will be called for start/restart queue operation. | ||
184 | * OTOH the most much worry for USB driver is spinlock nest. | ||
185 | * Specially it are | ||
186 | * - usb_ep_ops :: queue | ||
187 | * - usb_request :: complete | ||
188 | * | ||
189 | * But the caller of this function need not care about spinlock. | ||
190 | * This function is using usbhsg_trylock for it. | ||
191 | * if "is_locked" is 1, this mean this function lock it. | ||
192 | * but if it is 0, this mean it is already under spin lock. | ||
193 | * see also | ||
194 | * CAUTION [*endpoint queue*] | ||
195 | * CAUTION [*request complete*] | ||
196 | */ | ||
197 | |||
198 | /****************** spin try lock *******************/ | ||
199 | lock = usbhsg_trylock(gpriv, &flags); | ||
200 | |||
201 | pkt = usbhs_pkt_get(pipe); | ||
202 | if (pkt) | ||
203 | ret = usbhs_pkt_start(pkt); | ||
204 | |||
205 | usbhsg_unlock(lock, &flags); | ||
206 | /******************** spin unlock ******************/ | ||
207 | 141 | ||
208 | return ret; | 142 | usbhs_pkt_start(pipe); |
209 | } | 143 | } |
210 | 144 | ||
211 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, | 145 | static void usbhsg_queue_pop(struct usbhsg_uep *uep, |
@@ -215,34 +149,9 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, | |||
215 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 149 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
216 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 150 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
217 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 151 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
218 | struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); | ||
219 | |||
220 | /* | ||
221 | ********* assume under spin lock ********* | ||
222 | */ | ||
223 | |||
224 | /* | ||
225 | * CAUTION [*request complete*] | ||
226 | * | ||
227 | * There is a possibility not to be called in correct order | ||
228 | * if "complete" is called without spinlock. | ||
229 | * | ||
230 | * So, this function assume it is under spinlock, | ||
231 | * and call usb_request :: complete. | ||
232 | * | ||
233 | * But this "complete" will push next usb_request. | ||
234 | * It mean "usb_ep_ops :: queue" which is using spinlock is called | ||
235 | * under spinlock. | ||
236 | * | ||
237 | * To avoid dead-lock, this driver is using usbhsg_trylock. | ||
238 | * CAUTION [*endpoint queue*] | ||
239 | * CAUTION [*queue handler*] | ||
240 | */ | ||
241 | 152 | ||
242 | dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); | 153 | dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); |
243 | 154 | ||
244 | usbhs_pkt_pop(pkt); | ||
245 | |||
246 | ureq->req.status = status; | 155 | ureq->req.status = status; |
247 | ureq->req.complete(&uep->ep, &ureq->req); | 156 | ureq->req.complete(&uep->ep, &ureq->req); |
248 | 157 | ||
@@ -293,8 +202,6 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, | |||
293 | 202 | ||
294 | usbhsg_recip_handler_std_control_done(priv, uep, ctrl); | 203 | usbhsg_recip_handler_std_control_done(priv, uep, ctrl); |
295 | 204 | ||
296 | usbhsg_queue_start(uep); | ||
297 | |||
298 | return 0; | 205 | return 0; |
299 | } | 206 | } |
300 | 207 | ||
@@ -325,7 +232,8 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | |||
325 | uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); | 232 | uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); |
326 | if (!usbhsg_uep_to_pipe(uep)) { | 233 | if (!usbhsg_uep_to_pipe(uep)) { |
327 | dev_err(dev, "wrong recip request\n"); | 234 | dev_err(dev, "wrong recip request\n"); |
328 | return -EINVAL; | 235 | ret = -EINVAL; |
236 | goto usbhsg_recip_run_handle_end; | ||
329 | } | 237 | } |
330 | 238 | ||
331 | switch (recip) { | 239 | switch (recip) { |
@@ -348,10 +256,20 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, | |||
348 | } | 256 | } |
349 | 257 | ||
350 | if (func) { | 258 | if (func) { |
259 | unsigned long flags; | ||
260 | |||
351 | dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); | 261 | dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); |
262 | |||
263 | /******************** spin lock ********************/ | ||
264 | usbhs_lock(priv, flags); | ||
352 | ret = func(priv, uep, ctrl); | 265 | ret = func(priv, uep, ctrl); |
266 | usbhs_unlock(priv, flags); | ||
267 | /******************** spin unlock ******************/ | ||
353 | } | 268 | } |
354 | 269 | ||
270 | usbhsg_recip_run_handle_end: | ||
271 | usbhsg_queue_start(uep); | ||
272 | |||
355 | return ret; | 273 | return ret; |
356 | } | 274 | } |
357 | 275 | ||
@@ -445,44 +363,17 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
445 | * usb_dcp_ops | 363 | * usb_dcp_ops |
446 | * | 364 | * |
447 | */ | 365 | */ |
448 | static int usbhsg_dcp_enable(struct usbhsg_uep *uep) | ||
449 | { | ||
450 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
451 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
452 | struct usbhs_pipe *pipe; | ||
453 | |||
454 | /* | ||
455 | ********* assume under spin lock ********* | ||
456 | */ | ||
457 | |||
458 | pipe = usbhs_dcp_malloc(priv); | ||
459 | if (!pipe) | ||
460 | return -EIO; | ||
461 | |||
462 | uep->pipe = pipe; | ||
463 | uep->pipe->mod_private = uep; | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | #define usbhsg_dcp_disable usbhsg_pipe_disable | ||
469 | static int usbhsg_pipe_disable(struct usbhsg_uep *uep) | 366 | static int usbhsg_pipe_disable(struct usbhsg_uep *uep) |
470 | { | 367 | { |
471 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 368 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
472 | struct usbhs_pkt *pkt; | 369 | struct usbhs_pkt *pkt; |
473 | 370 | ||
474 | /* | ||
475 | ********* assume under spin lock ********* | ||
476 | */ | ||
477 | |||
478 | usbhs_pipe_disable(pipe); | 371 | usbhs_pipe_disable(pipe); |
479 | 372 | ||
480 | while (1) { | 373 | while (1) { |
481 | pkt = usbhs_pkt_get(pipe); | 374 | pkt = usbhs_pkt_pop(pipe, NULL); |
482 | if (!pkt) | 375 | if (!pkt) |
483 | break; | 376 | break; |
484 | |||
485 | usbhs_pkt_pop(pkt); | ||
486 | } | 377 | } |
487 | 378 | ||
488 | return 0; | 379 | return 0; |
@@ -509,8 +400,6 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
509 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 400 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
510 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | 401 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); |
511 | struct usbhs_pipe *pipe; | 402 | struct usbhs_pipe *pipe; |
512 | spinlock_t *lock; | ||
513 | unsigned long flags; | ||
514 | int ret = -EIO; | 403 | int ret = -EIO; |
515 | 404 | ||
516 | /* | 405 | /* |
@@ -520,9 +409,6 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
520 | if (uep->pipe) | 409 | if (uep->pipe) |
521 | return 0; | 410 | return 0; |
522 | 411 | ||
523 | /******************** spin lock ********************/ | ||
524 | lock = usbhsg_trylock(gpriv, &flags); | ||
525 | |||
526 | pipe = usbhs_pipe_malloc(priv, desc); | 412 | pipe = usbhs_pipe_malloc(priv, desc); |
527 | if (pipe) { | 413 | if (pipe) { |
528 | uep->pipe = pipe; | 414 | uep->pipe = pipe; |
@@ -536,29 +422,14 @@ static int usbhsg_ep_enable(struct usb_ep *ep, | |||
536 | ret = 0; | 422 | ret = 0; |
537 | } | 423 | } |
538 | 424 | ||
539 | usbhsg_unlock(lock, &flags); | ||
540 | /******************** spin unlock ******************/ | ||
541 | |||
542 | return ret; | 425 | return ret; |
543 | } | 426 | } |
544 | 427 | ||
545 | static int usbhsg_ep_disable(struct usb_ep *ep) | 428 | static int usbhsg_ep_disable(struct usb_ep *ep) |
546 | { | 429 | { |
547 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 430 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
548 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
549 | spinlock_t *lock; | ||
550 | unsigned long flags; | ||
551 | int ret; | ||
552 | 431 | ||
553 | /******************** spin lock ********************/ | 432 | return usbhsg_pipe_disable(uep); |
554 | lock = usbhsg_trylock(gpriv, &flags); | ||
555 | |||
556 | ret = usbhsg_pipe_disable(uep); | ||
557 | |||
558 | usbhsg_unlock(lock, &flags); | ||
559 | /******************** spin unlock ******************/ | ||
560 | |||
561 | return ret; | ||
562 | } | 433 | } |
563 | 434 | ||
564 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | 435 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, |
@@ -591,69 +462,28 @@ static int usbhsg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
591 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 462 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
592 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | 463 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); |
593 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 464 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
594 | spinlock_t *lock; | ||
595 | unsigned long flags; | ||
596 | int ret = 0; | ||
597 | |||
598 | /* | ||
599 | * CAUTION [*endpoint queue*] | ||
600 | * | ||
601 | * This function will be called from usb_request :: complete | ||
602 | * or usb driver timing. | ||
603 | * If this function is called from usb_request :: complete, | ||
604 | * it is already under spinlock on this driver. | ||
605 | * but it is called frm usb driver, this function should call spinlock. | ||
606 | * | ||
607 | * This function is using usbshg_trylock to solve this issue. | ||
608 | * if "is_locked" is 1, this mean this function lock it. | ||
609 | * but if it is 0, this mean it is already under spin lock. | ||
610 | * see also | ||
611 | * CAUTION [*queue handler*] | ||
612 | * CAUTION [*request complete*] | ||
613 | */ | ||
614 | |||
615 | /******************** spin lock ********************/ | ||
616 | lock = usbhsg_trylock(gpriv, &flags); | ||
617 | 465 | ||
618 | /* param check */ | 466 | /* param check */ |
619 | if (usbhsg_is_not_connected(gpriv) || | 467 | if (usbhsg_is_not_connected(gpriv) || |
620 | unlikely(!gpriv->driver) || | 468 | unlikely(!gpriv->driver) || |
621 | unlikely(!pipe)) | 469 | unlikely(!pipe)) |
622 | ret = -ESHUTDOWN; | 470 | return -ESHUTDOWN; |
623 | else | ||
624 | usbhsg_queue_push(uep, ureq); | ||
625 | |||
626 | usbhsg_unlock(lock, &flags); | ||
627 | /******************** spin unlock ******************/ | ||
628 | 471 | ||
472 | usbhsg_queue_push(uep, ureq); | ||
629 | usbhsg_queue_start(uep); | 473 | usbhsg_queue_start(uep); |
630 | 474 | ||
631 | return ret; | 475 | return 0; |
632 | } | 476 | } |
633 | 477 | ||
634 | static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) | 478 | static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) |
635 | { | 479 | { |
636 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 480 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
637 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); | 481 | struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); |
638 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 482 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
639 | spinlock_t *lock; | ||
640 | unsigned long flags; | ||
641 | |||
642 | /* | ||
643 | * see | ||
644 | * CAUTION [*queue handler*] | ||
645 | * CAUTION [*endpoint queue*] | ||
646 | * CAUTION [*request complete*] | ||
647 | */ | ||
648 | |||
649 | /******************** spin lock ********************/ | ||
650 | lock = usbhsg_trylock(gpriv, &flags); | ||
651 | 483 | ||
484 | usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); | ||
652 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); | 485 | usbhsg_queue_pop(uep, ureq, -ECONNRESET); |
653 | 486 | ||
654 | usbhsg_unlock(lock, &flags); | ||
655 | /******************** spin unlock ******************/ | ||
656 | |||
657 | return 0; | 487 | return 0; |
658 | } | 488 | } |
659 | 489 | ||
@@ -662,42 +492,32 @@ static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge) | |||
662 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 492 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
663 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 493 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
664 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 494 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
495 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | ||
665 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 496 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); |
666 | spinlock_t *lock; | ||
667 | unsigned long flags; | 497 | unsigned long flags; |
668 | int ret = -EAGAIN; | ||
669 | 498 | ||
670 | /* | 499 | usbhsg_pipe_disable(uep); |
671 | * see | ||
672 | * CAUTION [*queue handler*] | ||
673 | * CAUTION [*endpoint queue*] | ||
674 | * CAUTION [*request complete*] | ||
675 | */ | ||
676 | |||
677 | /******************** spin lock ********************/ | ||
678 | lock = usbhsg_trylock(gpriv, &flags); | ||
679 | if (!usbhs_pkt_get(pipe)) { | ||
680 | 500 | ||
681 | dev_dbg(dev, "set halt %d (pipe %d)\n", | 501 | dev_dbg(dev, "set halt %d (pipe %d)\n", |
682 | halt, usbhs_pipe_number(pipe)); | 502 | halt, usbhs_pipe_number(pipe)); |
683 | 503 | ||
684 | if (halt) | 504 | /******************** spin lock ********************/ |
685 | usbhs_pipe_stall(pipe); | 505 | usbhs_lock(priv, flags); |
686 | else | ||
687 | usbhs_pipe_disable(pipe); | ||
688 | 506 | ||
689 | if (halt && wedge) | 507 | if (halt) |
690 | usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); | 508 | usbhs_pipe_stall(pipe); |
691 | else | 509 | else |
692 | usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); | 510 | usbhs_pipe_disable(pipe); |
693 | 511 | ||
694 | ret = 0; | 512 | if (halt && wedge) |
695 | } | 513 | usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE); |
514 | else | ||
515 | usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE); | ||
696 | 516 | ||
697 | usbhsg_unlock(lock, &flags); | 517 | usbhs_unlock(priv, flags); |
698 | /******************** spin unlock ******************/ | 518 | /******************** spin unlock ******************/ |
699 | 519 | ||
700 | return ret; | 520 | return 0; |
701 | } | 521 | } |
702 | 522 | ||
703 | static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) | 523 | static int usbhsg_ep_set_halt(struct usb_ep *ep, int value) |
@@ -733,20 +553,26 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
733 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | 553 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); |
734 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 554 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
735 | struct device *dev = usbhs_priv_to_dev(priv); | 555 | struct device *dev = usbhs_priv_to_dev(priv); |
736 | spinlock_t *lock; | ||
737 | unsigned long flags; | 556 | unsigned long flags; |
557 | int ret = 0; | ||
738 | 558 | ||
739 | /******************** spin lock ********************/ | 559 | /******************** spin lock ********************/ |
740 | lock = usbhsg_trylock(gpriv, &flags); | 560 | usbhs_lock(priv, flags); |
741 | 561 | ||
742 | /* | ||
743 | * enable interrupt and systems if ready | ||
744 | */ | ||
745 | usbhsg_status_set(gpriv, status); | 562 | usbhsg_status_set(gpriv, status); |
746 | if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | 563 | if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && |
747 | usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) | 564 | usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) |
748 | goto usbhsg_try_start_unlock; | 565 | ret = -1; /* not ready */ |
566 | |||
567 | usbhs_unlock(priv, flags); | ||
568 | /******************** spin unlock ********************/ | ||
569 | |||
570 | if (ret < 0) | ||
571 | return 0; /* not ready is not error */ | ||
749 | 572 | ||
573 | /* | ||
574 | * enable interrupt and systems if ready | ||
575 | */ | ||
750 | dev_dbg(dev, "start gadget\n"); | 576 | dev_dbg(dev, "start gadget\n"); |
751 | 577 | ||
752 | /* | 578 | /* |
@@ -756,7 +582,10 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
756 | usbhsg_queue_done); | 582 | usbhsg_queue_done); |
757 | usbhs_fifo_init(priv); | 583 | usbhs_fifo_init(priv); |
758 | usbhsg_uep_init(gpriv); | 584 | usbhsg_uep_init(gpriv); |
759 | usbhsg_dcp_enable(dcp); | 585 | |
586 | /* dcp init */ | ||
587 | dcp->pipe = usbhs_dcp_malloc(priv); | ||
588 | dcp->pipe->mod_private = dcp; | ||
760 | 589 | ||
761 | /* | 590 | /* |
762 | * system config enble | 591 | * system config enble |
@@ -775,10 +604,6 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
775 | mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; | 604 | mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; |
776 | usbhs_irq_callback_update(priv, mod); | 605 | usbhs_irq_callback_update(priv, mod); |
777 | 606 | ||
778 | usbhsg_try_start_unlock: | ||
779 | usbhsg_unlock(lock, &flags); | ||
780 | /******************** spin unlock ********************/ | ||
781 | |||
782 | return 0; | 607 | return 0; |
783 | } | 608 | } |
784 | 609 | ||
@@ -788,20 +613,26 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
788 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 613 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
789 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); | 614 | struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); |
790 | struct device *dev = usbhs_priv_to_dev(priv); | 615 | struct device *dev = usbhs_priv_to_dev(priv); |
791 | spinlock_t *lock; | ||
792 | unsigned long flags; | 616 | unsigned long flags; |
617 | int ret = 0; | ||
793 | 618 | ||
794 | /******************** spin lock ********************/ | 619 | /******************** spin lock ********************/ |
795 | lock = usbhsg_trylock(gpriv, &flags); | 620 | usbhs_lock(priv, flags); |
796 | 621 | ||
797 | /* | ||
798 | * disable interrupt and systems if 1st try | ||
799 | */ | ||
800 | usbhsg_status_clr(gpriv, status); | 622 | usbhsg_status_clr(gpriv, status); |
801 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && | 623 | if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && |
802 | !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) | 624 | !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) |
803 | goto usbhsg_try_stop_unlock; | 625 | ret = -1; /* already done */ |
626 | |||
627 | usbhs_unlock(priv, flags); | ||
628 | /******************** spin unlock ********************/ | ||
629 | |||
630 | if (ret < 0) | ||
631 | return 0; /* already done is not error */ | ||
804 | 632 | ||
633 | /* | ||
634 | * disable interrupt and systems if 1st try | ||
635 | */ | ||
805 | usbhs_fifo_quit(priv); | 636 | usbhs_fifo_quit(priv); |
806 | 637 | ||
807 | /* disable all irq */ | 638 | /* disable all irq */ |
@@ -809,8 +640,6 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
809 | mod->irq_ctrl_stage = NULL; | 640 | mod->irq_ctrl_stage = NULL; |
810 | usbhs_irq_callback_update(priv, mod); | 641 | usbhs_irq_callback_update(priv, mod); |
811 | 642 | ||
812 | usbhsg_dcp_disable(dcp); | ||
813 | |||
814 | gpriv->gadget.speed = USB_SPEED_UNKNOWN; | 643 | gpriv->gadget.speed = USB_SPEED_UNKNOWN; |
815 | 644 | ||
816 | /* disable sys */ | 645 | /* disable sys */ |
@@ -818,8 +647,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
818 | usbhs_sys_function_ctrl(priv, 0); | 647 | usbhs_sys_function_ctrl(priv, 0); |
819 | usbhs_sys_usb_ctrl(priv, 0); | 648 | usbhs_sys_usb_ctrl(priv, 0); |
820 | 649 | ||
821 | usbhsg_unlock(lock, &flags); | 650 | usbhsg_pipe_disable(dcp); |
822 | /******************** spin unlock ********************/ | ||
823 | 651 | ||
824 | if (gpriv->driver && | 652 | if (gpriv->driver && |
825 | gpriv->driver->disconnect) | 653 | gpriv->driver->disconnect) |
@@ -828,11 +656,6 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
828 | dev_dbg(dev, "stop gadget\n"); | 656 | dev_dbg(dev, "stop gadget\n"); |
829 | 657 | ||
830 | return 0; | 658 | return 0; |
831 | |||
832 | usbhsg_try_stop_unlock: | ||
833 | usbhsg_unlock(lock, &flags); | ||
834 | |||
835 | return 0; | ||
836 | } | 659 | } |
837 | 660 | ||
838 | /* | 661 | /* |