aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-02-16 05:40:05 -0500
committerFelipe Balbi <balbi@ti.com>2011-02-17 14:11:46 -0500
commitad1adb89a0d9410345d573b6995a1fa9f9b7c74a (patch)
treeb07349993d6eec5dff875f5517b0c79667906a8b
parent63eed2b52494e35aaf38ac2db537d6ea0a55b0da (diff)
usb: musb: gadget: do not poke with gadget's list_head
struct usb_request's list_head is supposed to be used only by gadget drivers, but musb is abusing that. Give struct musb_request its own list_head and prevent musb from poking into other driver's business. Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/musb/musb_core.h4
-rw-r--r--drivers/usb/musb/musb_gadget.c37
-rw-r--r--drivers/usb/musb/musb_gadget.h7
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c24
4 files changed, 41 insertions, 31 deletions
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index d74a8113ae74..2c8dde6d23e0 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -328,7 +328,7 @@ struct musb_hw_ep {
328#endif 328#endif
329}; 329};
330 330
331static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep) 331static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
332{ 332{
333#ifdef CONFIG_USB_GADGET_MUSB_HDRC 333#ifdef CONFIG_USB_GADGET_MUSB_HDRC
334 return next_request(&hw_ep->ep_in); 334 return next_request(&hw_ep->ep_in);
@@ -337,7 +337,7 @@ static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
337#endif 337#endif
338} 338}
339 339
340static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) 340static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
341{ 341{
342#ifdef CONFIG_USB_GADGET_MUSB_HDRC 342#ifdef CONFIG_USB_GADGET_MUSB_HDRC
343 return next_request(&hw_ep->ep_out); 343 return next_request(&hw_ep->ep_out);
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 86decba48f28..0f59bf935c85 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -189,7 +189,7 @@ __acquires(ep->musb->lock)
189 189
190 req = to_musb_request(request); 190 req = to_musb_request(request);
191 191
192 list_del(&request->list); 192 list_del(&req->list);
193 if (req->request.status == -EINPROGRESS) 193 if (req->request.status == -EINPROGRESS)
194 req->request.status = status; 194 req->request.status = status;
195 musb = req->musb; 195 musb = req->musb;
@@ -251,9 +251,8 @@ static void nuke(struct musb_ep *ep, const int status)
251 ep->dma = NULL; 251 ep->dma = NULL;
252 } 252 }
253 253
254 while (!list_empty(&(ep->req_list))) { 254 while (!list_empty(&ep->req_list)) {
255 req = container_of(ep->req_list.next, struct musb_request, 255 req = list_first_entry(&ep->req_list, struct musb_request, list);
256 request.list);
257 musb_g_giveback(ep, &req->request, status); 256 musb_g_giveback(ep, &req->request, status);
258 } 257 }
259} 258}
@@ -485,6 +484,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
485void musb_g_tx(struct musb *musb, u8 epnum) 484void musb_g_tx(struct musb *musb, u8 epnum)
486{ 485{
487 u16 csr; 486 u16 csr;
487 struct musb_request *req;
488 struct usb_request *request; 488 struct usb_request *request;
489 u8 __iomem *mbase = musb->mregs; 489 u8 __iomem *mbase = musb->mregs;
490 struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in; 490 struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in;
@@ -492,7 +492,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
492 struct dma_channel *dma; 492 struct dma_channel *dma;
493 493
494 musb_ep_select(mbase, epnum); 494 musb_ep_select(mbase, epnum);
495 request = next_request(musb_ep); 495 req = next_request(musb_ep);
496 request = &req->request;
496 497
497 csr = musb_readw(epio, MUSB_TXCSR); 498 csr = musb_readw(epio, MUSB_TXCSR);
498 DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); 499 DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
@@ -571,15 +572,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
571 572
572 if (request->actual == request->length) { 573 if (request->actual == request->length) {
573 musb_g_giveback(musb_ep, request, 0); 574 musb_g_giveback(musb_ep, request, 0);
574 request = musb_ep->desc ? next_request(musb_ep) : NULL; 575 req = musb_ep->desc ? next_request(musb_ep) : NULL;
575 if (!request) { 576 if (!req) {
576 DBG(4, "%s idle now\n", 577 DBG(4, "%s idle now\n",
577 musb_ep->end_point.name); 578 musb_ep->end_point.name);
578 return; 579 return;
579 } 580 }
580 } 581 }
581 582
582 txstate(musb, to_musb_request(request)); 583 txstate(musb, req);
583 } 584 }
584} 585}
585 586
@@ -821,6 +822,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
821void musb_g_rx(struct musb *musb, u8 epnum) 822void musb_g_rx(struct musb *musb, u8 epnum)
822{ 823{
823 u16 csr; 824 u16 csr;
825 struct musb_request *req;
824 struct usb_request *request; 826 struct usb_request *request;
825 void __iomem *mbase = musb->mregs; 827 void __iomem *mbase = musb->mregs;
826 struct musb_ep *musb_ep; 828 struct musb_ep *musb_ep;
@@ -835,10 +837,12 @@ void musb_g_rx(struct musb *musb, u8 epnum)
835 837
836 musb_ep_select(mbase, epnum); 838 musb_ep_select(mbase, epnum);
837 839
838 request = next_request(musb_ep); 840 req = next_request(musb_ep);
839 if (!request) 841 if (!req)
840 return; 842 return;
841 843
844 request = &req->request;
845
842 csr = musb_readw(epio, MUSB_RXCSR); 846 csr = musb_readw(epio, MUSB_RXCSR);
843 dma = is_dma_capable() ? musb_ep->dma : NULL; 847 dma = is_dma_capable() ? musb_ep->dma : NULL;
844 848
@@ -914,15 +918,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
914#endif 918#endif
915 musb_g_giveback(musb_ep, request, 0); 919 musb_g_giveback(musb_ep, request, 0);
916 920
917 request = next_request(musb_ep); 921 req = next_request(musb_ep);
918 if (!request) 922 if (!req)
919 return; 923 return;
920 } 924 }
921#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) 925#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
922exit: 926exit:
923#endif 927#endif
924 /* Analyze request */ 928 /* Analyze request */
925 rxstate(musb, to_musb_request(request)); 929 rxstate(musb, req);
926} 930}
927 931
928/* ------------------------------------------------------------ */ 932/* ------------------------------------------------------------ */
@@ -1171,7 +1175,6 @@ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
1171 return NULL; 1175 return NULL;
1172 } 1176 }
1173 1177
1174 INIT_LIST_HEAD(&request->request.list);
1175 request->request.dma = DMA_ADDR_INVALID; 1178 request->request.dma = DMA_ADDR_INVALID;
1176 request->epnum = musb_ep->current_epnum; 1179 request->epnum = musb_ep->current_epnum;
1177 request->ep = musb_ep; 1180 request->ep = musb_ep;
@@ -1257,10 +1260,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
1257 } 1260 }
1258 1261
1259 /* add request to the list */ 1262 /* add request to the list */
1260 list_add_tail(&(request->request.list), &(musb_ep->req_list)); 1263 list_add_tail(&request->list, &musb_ep->req_list);
1261 1264
1262 /* it this is the head of the queue, start i/o ... */ 1265 /* it this is the head of the queue, start i/o ... */
1263 if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next) 1266 if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
1264 musb_ep_restart(musb, request); 1267 musb_ep_restart(musb, request);
1265 1268
1266cleanup: 1269cleanup:
@@ -1349,7 +1352,7 @@ static int musb_gadget_set_halt(struct usb_ep *ep, int value)
1349 1352
1350 musb_ep_select(mbase, epnum); 1353 musb_ep_select(mbase, epnum);
1351 1354
1352 request = to_musb_request(next_request(musb_ep)); 1355 request = next_request(musb_ep);
1353 if (value) { 1356 if (value) {
1354 if (request) { 1357 if (request) {
1355 DBG(3, "request in progress, cannot halt %s\n", 1358 DBG(3, "request in progress, cannot halt %s\n",
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index a55354fbccf5..66b7c5e0fb44 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -35,6 +35,8 @@
35#ifndef __MUSB_GADGET_H 35#ifndef __MUSB_GADGET_H
36#define __MUSB_GADGET_H 36#define __MUSB_GADGET_H
37 37
38#include <linux/list.h>
39
38enum buffer_map_state { 40enum buffer_map_state {
39 UN_MAPPED = 0, 41 UN_MAPPED = 0,
40 PRE_MAPPED, 42 PRE_MAPPED,
@@ -43,6 +45,7 @@ enum buffer_map_state {
43 45
44struct musb_request { 46struct musb_request {
45 struct usb_request request; 47 struct usb_request request;
48 struct list_head list;
46 struct musb_ep *ep; 49 struct musb_ep *ep;
47 struct musb *musb; 50 struct musb *musb;
48 u8 tx; /* endpoint direction */ 51 u8 tx; /* endpoint direction */
@@ -94,13 +97,13 @@ static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
94 return ep ? container_of(ep, struct musb_ep, end_point) : NULL; 97 return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
95} 98}
96 99
97static inline struct usb_request *next_request(struct musb_ep *ep) 100static inline struct musb_request *next_request(struct musb_ep *ep)
98{ 101{
99 struct list_head *queue = &ep->req_list; 102 struct list_head *queue = &ep->req_list;
100 103
101 if (list_empty(queue)) 104 if (list_empty(queue))
102 return NULL; 105 return NULL;
103 return container_of(queue->next, struct usb_request, list); 106 return container_of(queue->next, struct musb_request, list);
104} 107}
105 108
106extern void musb_g_tx(struct musb *musb, u8 epnum); 109extern void musb_g_tx(struct musb *musb, u8 epnum);
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 6dd03f4c5f49..75a542e42fdf 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -304,8 +304,7 @@ __acquires(musb->lock)
304 } 304 }
305 305
306 /* Maybe start the first request in the queue */ 306 /* Maybe start the first request in the queue */
307 request = to_musb_request( 307 request = next_request(musb_ep);
308 next_request(musb_ep));
309 if (!musb_ep->busy && request) { 308 if (!musb_ep->busy && request) {
310 DBG(3, "restarting the request\n"); 309 DBG(3, "restarting the request\n");
311 musb_ep_restart(musb, request); 310 musb_ep_restart(musb, request);
@@ -491,10 +490,12 @@ stall:
491static void ep0_rxstate(struct musb *musb) 490static void ep0_rxstate(struct musb *musb)
492{ 491{
493 void __iomem *regs = musb->control_ep->regs; 492 void __iomem *regs = musb->control_ep->regs;
493 struct musb_request *request;
494 struct usb_request *req; 494 struct usb_request *req;
495 u16 count, csr; 495 u16 count, csr;
496 496
497 req = next_ep0_request(musb); 497 request = next_ep0_request(musb);
498 req = &request->request;
498 499
499 /* read packet and ack; or stall because of gadget driver bug: 500 /* read packet and ack; or stall because of gadget driver bug:
500 * should have provided the rx buffer before setup() returned. 501 * should have provided the rx buffer before setup() returned.
@@ -544,17 +545,20 @@ static void ep0_rxstate(struct musb *musb)
544static void ep0_txstate(struct musb *musb) 545static void ep0_txstate(struct musb *musb)
545{ 546{
546 void __iomem *regs = musb->control_ep->regs; 547 void __iomem *regs = musb->control_ep->regs;
547 struct usb_request *request = next_ep0_request(musb); 548 struct musb_request *req = next_ep0_request(musb);
549 struct usb_request *request;
548 u16 csr = MUSB_CSR0_TXPKTRDY; 550 u16 csr = MUSB_CSR0_TXPKTRDY;
549 u8 *fifo_src; 551 u8 *fifo_src;
550 u8 fifo_count; 552 u8 fifo_count;
551 553
552 if (!request) { 554 if (!req) {
553 /* WARN_ON(1); */ 555 /* WARN_ON(1); */
554 DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); 556 DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
555 return; 557 return;
556 } 558 }
557 559
560 request = &req->request;
561
558 /* load the data */ 562 /* load the data */
559 fifo_src = (u8 *) request->buf + request->actual; 563 fifo_src = (u8 *) request->buf + request->actual;
560 fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, 564 fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
@@ -598,7 +602,7 @@ static void ep0_txstate(struct musb *musb)
598static void 602static void
599musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) 603musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
600{ 604{
601 struct usb_request *r; 605 struct musb_request *r;
602 void __iomem *regs = musb->control_ep->regs; 606 void __iomem *regs = musb->control_ep->regs;
603 607
604 musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); 608 musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req);
@@ -616,7 +620,7 @@ musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
616 /* clean up any leftover transfers */ 620 /* clean up any leftover transfers */
617 r = next_ep0_request(musb); 621 r = next_ep0_request(musb);
618 if (r) 622 if (r)
619 musb_g_ep0_giveback(musb, r); 623 musb_g_ep0_giveback(musb, &r->request);
620 624
621 /* For zero-data requests we want to delay the STATUS stage to 625 /* For zero-data requests we want to delay the STATUS stage to
622 * avoid SETUPEND errors. If we read data (OUT), delay accepting 626 * avoid SETUPEND errors. If we read data (OUT), delay accepting
@@ -758,11 +762,11 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
758 case MUSB_EP0_STAGE_STATUSOUT: 762 case MUSB_EP0_STAGE_STATUSOUT:
759 /* end of sequence #1: write to host (TX state) */ 763 /* end of sequence #1: write to host (TX state) */
760 { 764 {
761 struct usb_request *req; 765 struct musb_request *req;
762 766
763 req = next_ep0_request(musb); 767 req = next_ep0_request(musb);
764 if (req) 768 if (req)
765 musb_g_ep0_giveback(musb, req); 769 musb_g_ep0_giveback(musb, &req->request);
766 } 770 }
767 771
768 /* 772 /*
@@ -961,7 +965,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags)
961 } 965 }
962 966
963 /* add request to the list */ 967 /* add request to the list */
964 list_add_tail(&(req->request.list), &(ep->req_list)); 968 list_add_tail(&req->list, &ep->req_list);
965 969
966 DBG(3, "queue to %s (%s), length=%d\n", 970 DBG(3, "queue to %s (%s), length=%d\n",
967 ep->name, ep->is_in ? "IN/TX" : "OUT/RX", 971 ep->name, ep->is_in ? "IN/TX" : "OUT/RX",