Commit ad1adb89 authored by Felipe Balbi's avatar Felipe Balbi

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: default avatarFelipe Balbi <balbi@ti.com>
parent 63eed2b5
...@@ -328,7 +328,7 @@ struct musb_hw_ep { ...@@ -328,7 +328,7 @@ struct musb_hw_ep {
#endif #endif
}; };
static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep) static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
{ {
#ifdef CONFIG_USB_GADGET_MUSB_HDRC #ifdef CONFIG_USB_GADGET_MUSB_HDRC
return next_request(&hw_ep->ep_in); 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,7 +337,7 @@ static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
#endif #endif
} }
static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
{ {
#ifdef CONFIG_USB_GADGET_MUSB_HDRC #ifdef CONFIG_USB_GADGET_MUSB_HDRC
return next_request(&hw_ep->ep_out); return next_request(&hw_ep->ep_out);
......
...@@ -189,7 +189,7 @@ __acquires(ep->musb->lock) ...@@ -189,7 +189,7 @@ __acquires(ep->musb->lock)
req = to_musb_request(request); req = to_musb_request(request);
list_del(&request->list); list_del(&req->list);
if (req->request.status == -EINPROGRESS) if (req->request.status == -EINPROGRESS)
req->request.status = status; req->request.status = status;
musb = req->musb; musb = req->musb;
...@@ -251,9 +251,8 @@ static void nuke(struct musb_ep *ep, const int status) ...@@ -251,9 +251,8 @@ static void nuke(struct musb_ep *ep, const int status)
ep->dma = NULL; ep->dma = NULL;
} }
while (!list_empty(&(ep->req_list))) { while (!list_empty(&ep->req_list)) {
req = container_of(ep->req_list.next, struct musb_request, req = list_first_entry(&ep->req_list, struct musb_request, list);
request.list);
musb_g_giveback(ep, &req->request, status); musb_g_giveback(ep, &req->request, status);
} }
} }
...@@ -485,6 +484,7 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -485,6 +484,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
void musb_g_tx(struct musb *musb, u8 epnum) void musb_g_tx(struct musb *musb, u8 epnum)
{ {
u16 csr; u16 csr;
struct musb_request *req;
struct usb_request *request; struct usb_request *request;
u8 __iomem *mbase = musb->mregs; u8 __iomem *mbase = musb->mregs;
struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in; struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in;
...@@ -492,7 +492,8 @@ void musb_g_tx(struct musb *musb, u8 epnum) ...@@ -492,7 +492,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
struct dma_channel *dma; struct dma_channel *dma;
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
request = next_request(musb_ep); req = next_request(musb_ep);
request = &req->request;
csr = musb_readw(epio, MUSB_TXCSR); csr = musb_readw(epio, MUSB_TXCSR);
DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); 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,15 +572,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
if (request->actual == request->length) { if (request->actual == request->length) {
musb_g_giveback(musb_ep, request, 0); musb_g_giveback(musb_ep, request, 0);
request = musb_ep->desc ? next_request(musb_ep) : NULL; req = musb_ep->desc ? next_request(musb_ep) : NULL;
if (!request) { if (!req) {
DBG(4, "%s idle now\n", DBG(4, "%s idle now\n",
musb_ep->end_point.name); musb_ep->end_point.name);
return; return;
} }
} }
txstate(musb, to_musb_request(request)); txstate(musb, req);
} }
} }
...@@ -821,6 +822,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -821,6 +822,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
void musb_g_rx(struct musb *musb, u8 epnum) void musb_g_rx(struct musb *musb, u8 epnum)
{ {
u16 csr; u16 csr;
struct musb_request *req;
struct usb_request *request; struct usb_request *request;
void __iomem *mbase = musb->mregs; void __iomem *mbase = musb->mregs;
struct musb_ep *musb_ep; struct musb_ep *musb_ep;
...@@ -835,10 +837,12 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -835,10 +837,12 @@ void musb_g_rx(struct musb *musb, u8 epnum)
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
request = next_request(musb_ep); req = next_request(musb_ep);
if (!request) if (!req)
return; return;
request = &req->request;
csr = musb_readw(epio, MUSB_RXCSR); csr = musb_readw(epio, MUSB_RXCSR);
dma = is_dma_capable() ? musb_ep->dma : NULL; dma = is_dma_capable() ? musb_ep->dma : NULL;
...@@ -914,15 +918,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -914,15 +918,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
#endif #endif
musb_g_giveback(musb_ep, request, 0); musb_g_giveback(musb_ep, request, 0);
request = next_request(musb_ep); req = next_request(musb_ep);
if (!request) if (!req)
return; return;
} }
#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
exit: exit:
#endif #endif
/* Analyze request */ /* Analyze request */
rxstate(musb, to_musb_request(request)); rxstate(musb, req);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
...@@ -1171,7 +1175,6 @@ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) ...@@ -1171,7 +1175,6 @@ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
return NULL; return NULL;
} }
INIT_LIST_HEAD(&request->request.list);
request->request.dma = DMA_ADDR_INVALID; request->request.dma = DMA_ADDR_INVALID;
request->epnum = musb_ep->current_epnum; request->epnum = musb_ep->current_epnum;
request->ep = musb_ep; request->ep = musb_ep;
...@@ -1257,10 +1260,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1257,10 +1260,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
} }
/* add request to the list */ /* add request to the list */
list_add_tail(&(request->request.list), &(musb_ep->req_list)); list_add_tail(&request->list, &musb_ep->req_list);
/* it this is the head of the queue, start i/o ... */ /* it this is the head of the queue, start i/o ... */
if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next) if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
musb_ep_restart(musb, request); musb_ep_restart(musb, request);
cleanup: cleanup:
...@@ -1349,7 +1352,7 @@ static int musb_gadget_set_halt(struct usb_ep *ep, int value) ...@@ -1349,7 +1352,7 @@ static int musb_gadget_set_halt(struct usb_ep *ep, int value)
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
request = to_musb_request(next_request(musb_ep)); request = next_request(musb_ep);
if (value) { if (value) {
if (request) { if (request) {
DBG(3, "request in progress, cannot halt %s\n", DBG(3, "request in progress, cannot halt %s\n",
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#ifndef __MUSB_GADGET_H #ifndef __MUSB_GADGET_H
#define __MUSB_GADGET_H #define __MUSB_GADGET_H
#include <linux/list.h>
enum buffer_map_state { enum buffer_map_state {
UN_MAPPED = 0, UN_MAPPED = 0,
PRE_MAPPED, PRE_MAPPED,
...@@ -43,6 +45,7 @@ enum buffer_map_state { ...@@ -43,6 +45,7 @@ enum buffer_map_state {
struct musb_request { struct musb_request {
struct usb_request request; struct usb_request request;
struct list_head list;
struct musb_ep *ep; struct musb_ep *ep;
struct musb *musb; struct musb *musb;
u8 tx; /* endpoint direction */ u8 tx; /* endpoint direction */
...@@ -94,13 +97,13 @@ static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) ...@@ -94,13 +97,13 @@ static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
return ep ? container_of(ep, struct musb_ep, end_point) : NULL; return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
} }
static inline struct usb_request *next_request(struct musb_ep *ep) static inline struct musb_request *next_request(struct musb_ep *ep)
{ {
struct list_head *queue = &ep->req_list; struct list_head *queue = &ep->req_list;
if (list_empty(queue)) if (list_empty(queue))
return NULL; return NULL;
return container_of(queue->next, struct usb_request, list); return container_of(queue->next, struct musb_request, list);
} }
extern void musb_g_tx(struct musb *musb, u8 epnum); extern void musb_g_tx(struct musb *musb, u8 epnum);
......
...@@ -304,8 +304,7 @@ __acquires(musb->lock) ...@@ -304,8 +304,7 @@ __acquires(musb->lock)
} }
/* Maybe start the first request in the queue */ /* Maybe start the first request in the queue */
request = to_musb_request( request = next_request(musb_ep);
next_request(musb_ep));
if (!musb_ep->busy && request) { if (!musb_ep->busy && request) {
DBG(3, "restarting the request\n"); DBG(3, "restarting the request\n");
musb_ep_restart(musb, request); musb_ep_restart(musb, request);
...@@ -491,10 +490,12 @@ __acquires(musb->lock) ...@@ -491,10 +490,12 @@ __acquires(musb->lock)
static void ep0_rxstate(struct musb *musb) static void ep0_rxstate(struct musb *musb)
{ {
void __iomem *regs = musb->control_ep->regs; void __iomem *regs = musb->control_ep->regs;
struct musb_request *request;
struct usb_request *req; struct usb_request *req;
u16 count, csr; u16 count, csr;
req = next_ep0_request(musb); request = next_ep0_request(musb);
req = &request->request;
/* read packet and ack; or stall because of gadget driver bug: /* read packet and ack; or stall because of gadget driver bug:
* should have provided the rx buffer before setup() returned. * should have provided the rx buffer before setup() returned.
...@@ -544,17 +545,20 @@ static void ep0_rxstate(struct musb *musb) ...@@ -544,17 +545,20 @@ static void ep0_rxstate(struct musb *musb)
static void ep0_txstate(struct musb *musb) static void ep0_txstate(struct musb *musb)
{ {
void __iomem *regs = musb->control_ep->regs; void __iomem *regs = musb->control_ep->regs;
struct usb_request *request = next_ep0_request(musb); struct musb_request *req = next_ep0_request(musb);
struct usb_request *request;
u16 csr = MUSB_CSR0_TXPKTRDY; u16 csr = MUSB_CSR0_TXPKTRDY;
u8 *fifo_src; u8 *fifo_src;
u8 fifo_count; u8 fifo_count;
if (!request) { if (!req) {
/* WARN_ON(1); */ /* WARN_ON(1); */
DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
return; return;
} }
request = &req->request;
/* load the data */ /* load the data */
fifo_src = (u8 *) request->buf + request->actual; fifo_src = (u8 *) request->buf + request->actual;
fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
...@@ -598,7 +602,7 @@ static void ep0_txstate(struct musb *musb) ...@@ -598,7 +602,7 @@ static void ep0_txstate(struct musb *musb)
static void static void
musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
{ {
struct usb_request *r; struct musb_request *r;
void __iomem *regs = musb->control_ep->regs; void __iomem *regs = musb->control_ep->regs;
musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); 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,7 +620,7 @@ musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
/* clean up any leftover transfers */ /* clean up any leftover transfers */
r = next_ep0_request(musb); r = next_ep0_request(musb);
if (r) if (r)
musb_g_ep0_giveback(musb, r); musb_g_ep0_giveback(musb, &r->request);
/* For zero-data requests we want to delay the STATUS stage to /* For zero-data requests we want to delay the STATUS stage to
* avoid SETUPEND errors. If we read data (OUT), delay accepting * avoid SETUPEND errors. If we read data (OUT), delay accepting
...@@ -758,11 +762,11 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) ...@@ -758,11 +762,11 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
case MUSB_EP0_STAGE_STATUSOUT: case MUSB_EP0_STAGE_STATUSOUT:
/* end of sequence #1: write to host (TX state) */ /* end of sequence #1: write to host (TX state) */
{ {
struct usb_request *req; struct musb_request *req;
req = next_ep0_request(musb); req = next_ep0_request(musb);
if (req) if (req)
musb_g_ep0_giveback(musb, req); musb_g_ep0_giveback(musb, &req->request);
} }
/* /*
...@@ -961,7 +965,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) ...@@ -961,7 +965,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags)
} }
/* add request to the list */ /* add request to the list */
list_add_tail(&(req->request.list), &(ep->req_list)); list_add_tail(&req->list, &ep->req_list);
DBG(3, "queue to %s (%s), length=%d\n", DBG(3, "queue to %s (%s), length=%d\n",
ep->name, ep->is_in ? "IN/TX" : "OUT/RX", ep->name, ep->is_in ? "IN/TX" : "OUT/RX",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment