usb: gadget: aspeed: Rework the reset logic
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 26 Jul 2019 05:05:35 +0000 (15:05 +1000)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 12 Aug 2019 05:54:49 +0000 (08:54 +0300)
We had some dodgy code using the speed setting to decide whether a
port reset would reset the device or just enable it.

Instead, if the device is disabled and has a gadget attached, a
reset will enable it. If it's already enabled, a reset will
reset it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/udc/aspeed-vhub/dev.c

index 5f7e3b6..79d3cb6 100644 (file)
@@ -50,7 +50,7 @@ void ast_vhub_dev_irq(struct ast_vhub_dev *d)
 
 static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
 {
-       u32 reg, hmsk;
+       u32 reg, hmsk, i;
 
        if (d->enabled)
                return;
@@ -76,6 +76,20 @@ static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
        /* Set EP0 DMA buffer address */
        writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA);
 
+       /* Clear stall on all EPs */
+       for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
+               struct ast_vhub_ep *ep = d->epns[i];
+
+               if (ep && (ep->epn.stalled || ep->epn.wedged)) {
+                       ep->epn.stalled = false;
+                       ep->epn.wedged = false;
+                       ast_vhub_update_epn_stall(ep);
+               }
+       }
+
+       /* Additional cleanups */
+       d->wakeup_en = false;
+       d->suspended = false;
        d->enabled = true;
 }
 
@@ -477,46 +491,28 @@ void ast_vhub_dev_resume(struct ast_vhub_dev *d)
 
 void ast_vhub_dev_reset(struct ast_vhub_dev *d)
 {
-       /*
-        * If speed is not set, we enable the port. If it is,
-        * send reset to the gadget and reset "speed".
-        *
-        * Speed is an indication that we have got the first
-        * setup packet to the device.
-        */
-       if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) {
-               DDBG(d, "Reset at unknown speed of disabled device, enabling...\n");
-               ast_vhub_dev_enable(d);
-               d->suspended = false;
+       /* No driver, just disable the device and return */
+       if (!d->driver) {
+               ast_vhub_dev_disable(d);
+               return;
        }
-       if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) {
-               unsigned int i;
 
-               DDBG(d, "Reset at known speed of bound device, resetting...\n");
+       /* If the port isn't enabled, just enable it */
+       if (!d->enabled) {
+               DDBG(d, "Reset of disabled device, enabling...\n");
+               ast_vhub_dev_enable(d);
+       } else {
+               DDBG(d, "Reset of enabled device, resetting...\n");
                spin_unlock(&d->vhub->lock);
-               d->driver->reset(&d->gadget);
+               usb_gadget_udc_reset(&d->gadget, d->driver);
                spin_lock(&d->vhub->lock);
 
                /*
-                * Disable/re-enable HW, this will clear the address
+                * Disable and maybe re-enable HW, this will clear the address
                 * and speed setting.
                 */
                ast_vhub_dev_disable(d);
                ast_vhub_dev_enable(d);
-
-               /* Clear stall on all EPs */
-               for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
-                       struct ast_vhub_ep *ep = d->epns[i];
-
-                       if (ep && ep->epn.stalled) {
-                               ep->epn.stalled = false;
-                               ast_vhub_update_epn_stall(ep);
-                       }
-               }
-
-               /* Additional cleanups */
-               d->wakeup_en = false;
-               d->suspended = false;
        }
 }