aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs/fifo.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-06-06 01:18:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 12:10:09 -0400
commit97664a207bc2601a03a300f00e6922038cd5b99c (patch)
tree19202c1dc78068e52a337cf34bff79d7c6e1b92f /drivers/usb/renesas_usbhs/fifo.c
parent8a2c225ddb2d23a9b3f70af2ec70d28e4abd0b8e (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.c138
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 */
25static int usbhsf_null_handle(struct usbhs_pkt *pkt) 25static 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
68void usbhs_pkt_pop(struct usbhs_pkt *pkt) 75static 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
73struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe) 80static 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
88struct 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
108int __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 */
191static int usbhsf_try_push(struct usbhs_pkt *pkt) 263static 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
289static int usbhsf_prepare_pop(struct usbhs_pkt *pkt) 358static 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
307static int usbhsf_try_pop(struct usbhs_pkt *pkt) 376static 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
368usbhs_fifo_read_end: 436usbhs_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 */
397static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt) 459static 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 }