Merge remote-tracking branch 'usb-gadget/next'
[linux] / drivers / usb / dwc3 / gadget.c
index 6c9b76b..e83f84e 100644 (file)
@@ -174,7 +174,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
 {
        struct dwc3                     *dwc = dep->dwc;
 
-       req->started = false;
        list_del(&req->list);
        req->remaining = 0;
        req->needs_extra_trb = false;
@@ -209,6 +208,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        struct dwc3                     *dwc = dep->dwc;
 
        dwc3_gadget_del_and_unmap_request(dep, req, status);
+       req->status = DWC3_REQUEST_STATUS_COMPLETED;
 
        spin_unlock(&dwc->lock);
        usb_gadget_giveback_request(&dep->endpoint, &req->request);
@@ -384,19 +384,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
 
        trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
 
-       if (ret == 0) {
-               switch (DWC3_DEPCMD_CMD(cmd)) {
-               case DWC3_DEPCMD_STARTTRANSFER:
-                       dep->flags |= DWC3_EP_TRANSFER_STARTED;
-                       dwc3_gadget_ep_get_transfer_index(dep);
-                       break;
-               case DWC3_DEPCMD_ENDTRANSFER:
-                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-                       break;
-               default:
-                       /* nothing */
-                       break;
-               }
+       if (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
+               dep->flags |= DWC3_EP_TRANSFER_STARTED;
+               dwc3_gadget_ep_get_transfer_index(dep);
        }
 
        if (saved_config) {
@@ -642,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
 
                dep->type = usb_endpoint_type(desc);
                dep->flags |= DWC3_EP_ENABLED;
-               dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
 
                reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
                reg |= DWC3_DALEPENA_EP(dep->number);
@@ -748,7 +737,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
        dep->stream_capable = false;
        dep->type = 0;
-       dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
+       dep->flags = 0;
 
        /* Clear out the ep descriptors for non-ep0 */
        if (dep->number > 1) {
@@ -847,6 +836,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep,
        req->direction  = dep->direction;
        req->epnum      = dep->number;
        req->dep        = dep;
+       req->status     = DWC3_REQUEST_STATUS_UNKNOWN;
 
        trace_dwc3_alloc_request(req);
 
@@ -1435,6 +1425,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                                &req->request, req->dep->name))
                return -EINVAL;
 
+       if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED,
+                               "%s: request %pK already in flight\n",
+                               dep->name, &req->request))
+               return -EINVAL;
+
        pm_runtime_get(dwc->dev);
 
        req->request.actual     = 0;
@@ -1443,6 +1438,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
        trace_dwc3_ep_queue(req);
 
        list_add_tail(&req->list, &dep->pending_list);
+       req->status = DWC3_REQUEST_STATUS_QUEUED;
 
        /*
         * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
@@ -1553,7 +1549,10 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
                                goto out0;
 
                        dwc3_gadget_move_cancelled_request(req);
-                       goto out0;
+                       if (dep->flags & DWC3_EP_TRANSFER_STARTED)
+                               goto out0;
+                       else
+                               goto out1;
                }
                dev_err(dwc->dev, "request %pK was not queued to %s\n",
                                request, ep->name);
@@ -1561,6 +1560,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
                goto out0;
        }
 
+out1:
        dwc3_gadget_giveback(dep, req, -ECONNRESET);
 
 out0:
@@ -2547,7 +2547,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
        dep = dwc->eps[epnum];
 
        if (!(dep->flags & DWC3_EP_ENABLED)) {
-               if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+               if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
                        return;
 
                /* Handle only EPCMDCMPLT when EP disabled */
@@ -2571,7 +2571,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
                if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
-                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
+                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
                        dwc3_gadget_ep_cleanup_cancelled_requests(dep);
                }
                break;
@@ -2628,8 +2628,7 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
        u32 cmd;
        int ret;
 
-       if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) ||
-           !dep->resource_index)
+       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
                return;
 
        /*
@@ -2672,10 +2671,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
-       if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) {
-               dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+       if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
                udelay(100);
-       }
 }
 
 static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
@@ -3339,6 +3336,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err4;
        }
 
+       dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
+
        return 0;
 
 err4: