Merge tag 'v3.10.105' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / dwc3 / gadget.c
index b5e5b35df49c8ff49ca5817ced0838e79dad9ccf..0dfee61f78783f1c76fdd451d0708acbefc7d738 100644 (file)
@@ -319,6 +319,8 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
                if (!(reg & DWC3_DGCMD_CMDACT)) {
                        dev_vdbg(dwc->dev, "Command Complete --> %d\n",
                                        DWC3_DGCMD_STATUS(reg));
+                       if (DWC3_DGCMD_STATUS(reg))
+                               return -EINVAL;
                        return 0;
                }
 
@@ -355,6 +357,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
                if (!(reg & DWC3_DEPCMD_CMDACT)) {
                        dev_vdbg(dwc->dev, "Command Complete --> %d\n",
                                        DWC3_DEPCMD_STATUS(reg));
+                       if (DWC3_DEPCMD_STATUS(reg))
+                               return -EINVAL;
                        return 0;
                }
 
@@ -550,12 +554,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
                if (!usb_endpoint_xfer_isoc(desc))
                        return 0;
 
-               memset(&trb_link, 0, sizeof(trb_link));
-
                /* Link TRB for ISOC. The HWO bit is never reset */
                trb_st_hw = &dep->trb_pool[0];
 
                trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
+               memset(trb_link, 0, sizeof(*trb_link));
 
                trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
                trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
@@ -604,6 +607,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
        dwc3_remove_requests(dwc, dep);
 
+       /* make sure HW endpoint isn't stalled */
+       if (dep->flags & DWC3_EP_STALL)
+               __dwc3_gadget_ep_set_halt(dep, 0, false);
+
        reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
        reg &= ~DWC3_DALEPENA_EP(dep->number);
        dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
@@ -904,8 +911,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
 
                                if (i == (request->num_mapped_sgs - 1) ||
                                                sg_is_last(s)) {
-                                       if (list_is_last(&req->list,
-                                                       &dep->request_list))
+                                       if (list_empty(&dep->request_list))
                                                last_one = true;
                                        chain = false;
                                }
@@ -923,6 +929,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
                                if (last_one)
                                        break;
                        }
+
+                       if (last_one)
+                               break;
                } else {
                        dma = req->request.dma;
                        length = req->request.length;
@@ -1202,7 +1211,7 @@ out0:
        return ret;
 }
 
-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
+int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
 {
        struct dwc3_gadget_ep_cmd_params        params;
        struct dwc3                             *dwc = dep->dwc;
@@ -1211,6 +1220,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
        memset(&params, 0x00, sizeof(params));
 
        if (value) {
+               if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
+                               (!list_empty(&dep->req_queued) ||
+                                !list_empty(&dep->request_list)))) {
+                       dev_dbg(dwc->dev, "%s: pending request, cannot halt\n",
+                                       dep->name);
+                       return -EAGAIN;
+               }
+
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_SETSTALL, &params);
                if (ret)
@@ -1220,9 +1237,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (dep->flags & DWC3_EP_WEDGE)
-                       return 0;
-
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_CLEARSTALL, &params);
                if (ret)
@@ -1230,7 +1244,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                                        value ? "set" : "clear",
                                        dep->name);
                else
-                       dep->flags &= ~DWC3_EP_STALL;
+                       dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
        }
 
        return ret;
@@ -1253,7 +1267,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
                goto out;
        }
 
-       ret = __dwc3_gadget_ep_set_halt(dep, value);
+       ret = __dwc3_gadget_ep_set_halt(dep, value, false);
 out:
        spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1273,7 +1287,7 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
        if (dep->number == 0 || dep->number == 1)
                return dwc3_gadget_ep0_set_halt(ep, 1);
        else
-               return dwc3_gadget_ep_set_halt(ep, 1);
+               return __dwc3_gadget_ep_set_halt(dep, 1, false);
 }
 
 /* -------------------------------------------------------------------------- */
@@ -1508,6 +1522,15 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        int                     irq;
        u32                     reg;
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+                               irq, ret);
+               goto err0;
+       }
+
        spin_lock_irqsave(&dwc->lock, flags);
 
        if (dwc->gadget_driver) {
@@ -1515,7 +1538,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
                                dwc->gadget.name,
                                dwc->gadget_driver->driver.name);
                ret = -EBUSY;
-               goto err0;
+               goto err1;
        }
 
        dwc->gadget_driver      = driver;
@@ -1551,41 +1574,38 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err0;
+               goto err2;
        }
 
        dep = dwc->eps[1];
        ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
        if (ret) {
                dev_err(dwc->dev, "failed to enable %s\n", dep->name);
-               goto err1;
+               goto err3;
        }
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
-                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-                               irq, ret);
-               goto err1;
-       }
-
        dwc3_gadget_enable_irq(dwc);
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
 
-err1:
+err3:
        __dwc3_gadget_ep_disable(dwc->eps[0]);
 
-err0:
+err2:
+       dwc->gadget_driver = NULL;
+
+err1:
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       free_irq(irq, dwc);
+
+err0:
        return ret;
 }
 
@@ -1599,9 +1619,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
        spin_lock_irqsave(&dwc->lock, flags);
 
        dwc3_gadget_disable_irq(dwc);
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-       free_irq(irq, dwc);
-
        __dwc3_gadget_ep_disable(dwc->eps[0]);
        __dwc3_gadget_ep_disable(dwc->eps[1]);
 
@@ -1609,6 +1626,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       free_irq(irq, dwc);
+
        return 0;
 }
 
@@ -1782,14 +1802,6 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
                        s_pkt = 1;
        }
 
-       /*
-        * We assume here we will always receive the entire data block
-        * which we should receive. Meaning, if we program RX to
-        * receive 4K but we receive only 2K, we assume that's all we
-        * should receive and we simply bounce the request back to the
-        * gadget driver for further processing.
-        */
-       req->request.actual += req->request.length - count;
        if (s_pkt)
                return 1;
        if ((event->status & DEPEVT_STATUS_LST) &&
@@ -1809,6 +1821,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
        struct dwc3_trb         *trb;
        unsigned int            slot;
        unsigned int            i;
+       int                     count = 0;
        int                     ret;
 
        do {
@@ -1825,6 +1838,8 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
                                slot++;
                        slot %= DWC3_TRB_NUM;
                        trb = &dep->trb_pool[slot];
+                       count += trb->size & DWC3_TRB_SIZE_MASK;
+
 
                        ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
                                        event, status);
@@ -1832,6 +1847,14 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
                                break;
                }while (++i < req->request.num_mapped_sgs);
 
+               /*
+                * We assume here we will always receive the entire data block
+                * which we should receive. Meaning, if we program RX to
+                * receive 4K but we receive only 2K, we assume that's all we
+                * should receive and we simply bounce the request back to the
+                * gadget driver for further processing.
+                */
+               req->request.actual += req->request.length - count;
                dwc3_gadget_giveback(dep, req, status);
 
                if (ret)