From b4b7ff4b08e691656c9d77c758fc355833128ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Wed, 20 Jan 2016 14:01:31 -0300 Subject: Linux-libre 4.4-gnu --- drivers/usb/dwc3/gadget.c | 64 +++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'drivers/usb/dwc3/gadget.c') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9c38e4b0a..a58376fd6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -948,7 +948,6 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, dwc3_trace(trace_dwc3_gadget, "%s: endpoint busy", dep->name); return -EBUSY; } - dep->flags &= ~DWC3_EP_PENDING_REQUEST; /* * If we are getting here after a short-out-packet we don't enqueue any @@ -1050,6 +1049,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) req->direction = dep->direction; req->epnum = dep->number; + trace_dwc3_ep_queue(req); + /* * We only add to our list of requests now and * start consuming the list once we get XferNotReady @@ -1069,6 +1070,20 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) list_add_tail(&req->list, &dep->request_list); + /* + * If there are no pending requests and the endpoint isn't already + * busy, we will just start the request straight away. + * + * This will save one IRQ (XFER_NOT_READY) and possibly make it a + * little bit faster. + */ + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) && + !usb_endpoint_xfer_int(dep->endpoint.desc) && + !(dep->flags & DWC3_EP_BUSY)) { + ret = __dwc3_gadget_kick_transfer(dep, 0, true); + goto out; + } + /* * There are a few special cases: * @@ -1096,10 +1111,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) } ret = __dwc3_gadget_kick_transfer(dep, 0, true); - if (ret && ret != -EBUSY) - dev_dbg(dwc->dev, "%s: failed to kick transfers\n", - dep->name); - return ret; + if (!ret) + dep->flags &= ~DWC3_EP_PENDING_REQUEST; + + goto out; } /* @@ -1113,10 +1128,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) WARN_ON_ONCE(!dep->resource_index); ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, false); - if (ret && ret != -EBUSY) - dev_dbg(dwc->dev, "%s: failed to kick transfers\n", - dep->name); - return ret; + goto out; } /* @@ -1124,14 +1136,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * right away, otherwise host will not know we have streams to be * handled. */ - if (dep->stream_capable) { + if (dep->stream_capable) ret = __dwc3_gadget_kick_transfer(dep, 0, true); - if (ret && ret != -EBUSY) - dev_dbg(dwc->dev, "%s: failed to kick transfers\n", - dep->name); - } - return 0; +out: + if (ret && ret != -EBUSY) + dev_dbg(dwc->dev, "%s: failed to kick transfers\n", + dep->name); + if (ret == -EBUSY) + ret = 0; + + return ret; } static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, @@ -1159,8 +1174,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, goto out; } - trace_dwc3_ep_queue(req); - ret = __dwc3_gadget_ep_queue(dep, req); out: @@ -1960,6 +1973,14 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, dwc->u1u2 = 0; } + + if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + int ret; + + ret = __dwc3_gadget_kick_transfer(dep, 0, is_xfer_complete); + if (!ret || ret == -EBUSY) + return; + } } static void dwc3_endpoint_interrupt(struct dwc3 *dwc, @@ -1997,15 +2018,16 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dwc3_gadget_start_isoc(dwc, dep, event); } else { + int active; int ret; + active = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE; + dwc3_trace(trace_dwc3_gadget, "%s: reason %s", - dep->name, event->status & - DEPEVT_STATUS_TRANSFER_ACTIVE - ? "Transfer Active" + dep->name, active ? "Transfer Active" : "Transfer Not Active"); - ret = __dwc3_gadget_kick_transfer(dep, 0, 1); + ret = __dwc3_gadget_kick_transfer(dep, 0, !active); if (!ret || ret == -EBUSY) return; -- cgit v1.2.3