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 /drivers/usb/renesas_usbhs/fifo.c | |
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>
Diffstat (limited to 'drivers/usb/renesas_usbhs/fifo.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 138 |
1 files changed, 96 insertions, 42 deletions
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 | } |