From: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx> calling rx routine directly if request is still pending. removing the use of m_ep_restart for rx. Signed-off-by: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx> [ make it actually compile and do something useful ] Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> --- drivers/usb/musb/musb_gadget.c | 34 ++++++++++++++++++++++------------ drivers/usb/musb/musb_gadget.h | 6 +++++- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 9e4ba68..ad6b735 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -430,7 +430,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) if (request) musb_g_giveback(musb_ep, request, -EPIPE); - goto done; + return; } if (csr & MUSB_RXCSR_P_OVERRUN) { @@ -448,15 +448,14 @@ void musb_g_rx(struct musb *musb, u8 epnum) } /* analyze request if the ep is hot */ - if (request) + if (request) { do_pio_rx(musb, to_musb_request(request)); - else + } else { DBG(3, "packet waiting for %s%s request\n", musb_ep->desc ? "" : "inactive ", musb_ep->end_point.name); - -done: - return; + musb_ep->rx_pending = true; + } } /* ------------------------------------------------------------ */ @@ -690,10 +689,7 @@ static void musb_ep_restart(struct musb *musb, struct musb_request *req) &req->request, req->request.length, req->epnum); musb_ep_select(musb->mregs, req->epnum); - if (req->tx) - do_pio_tx(musb, req); - else - do_pio_rx(musb, req); + do_pio_tx(musb, req); } static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, @@ -745,9 +741,23 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, /* add request to the list */ list_add_tail(&(request->request.list), &(musb_ep->req_list)); - /* it this is the head of the queue, start i/o ... */ - if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next) + /* we can only start i/o if this is the head of the queue and + * endpoint is not stalled (halted) or busy + */ + if (!musb_ep->stalled && !musb_ep->busy && + &request->request.list == musb_ep->req_list.next && + request->tx) { + DBG(1, "restarting\n"); musb_ep_restart(musb, request); + } + + /* if we received an RX packet before the request was queued, + * process it here. */ + if (!request->tx && musb_ep->rx_pending) { + DBG(1, "processing pending RX\n"); + musb_ep->rx_pending = false; + musb_g_rx(musb, musb_ep->current_epnum); + } cleanup: spin_unlock_irqrestore(&musb->lock, lockflags); diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 59502da..f9cb3a8 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -76,7 +76,11 @@ struct musb_ep { struct list_head req_list; /* true if lock must be dropped but req_list may not be advanced */ - u8 busy; + u8 busy:1; + u8 rx_pending:1; + + /* true if endpoint is stalled */ + u8 stalled:1; }; static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) -- 1.6.4.2.253.g0b1fac -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html