Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/nick-nhusb]: src/sys/external/bsd/dwc2 Improve the transfer abort process.



details:   https://anonhg.NetBSD.org/src/rev/0b8e4036387f
branches:  nick-nhusb
changeset: 804736:0b8e4036387f
user:      skrll <skrll%NetBSD.org@localhost>
date:      Thu Dec 29 08:15:18 2016 +0000

description:
Improve the transfer abort process.

diffstat:

 sys/external/bsd/dwc2/dwc2.c |  52 +++++++++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 17 deletions(-)

diffs (112 lines):

diff -r 4f0184e9da1d -r 0b8e4036387f sys/external/bsd/dwc2/dwc2.c
--- a/sys/external/bsd/dwc2/dwc2.c      Thu Dec 29 08:04:08 2016 +0000
+++ b/sys/external/bsd/dwc2/dwc2.c      Thu Dec 29 08:15:18 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dwc2.c,v 1.32.2.29 2016/12/05 10:55:25 skrll Exp $     */
+/*     $NetBSD: dwc2.c,v 1.32.2.30 2016/12/29 08:15:18 skrll Exp $     */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.32.2.29 2016/12/05 10:55:25 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.32.2.30 2016/12/29 08:15:18 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -316,24 +316,30 @@
 dwc2_timeout(void *addr)
 {
        struct usbd_xfer *xfer = addr;
-       struct dwc2_xfer *dxfer = DWC2_XFER2DXFER(xfer);
-//     struct dwc2_pipe *dpipe = DWC2_XFER2DPIPE(xfer);
        struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
+       bool timeout = false;
 
        DPRINTF("dxfer=%p\n", dxfer);
-
+       mutex_enter(&sc->sc_lock);
        if (sc->sc_dying) {
-               mutex_enter(&sc->sc_lock);
-               dwc2_abort_xfer(&dxfer->xfer, USBD_TIMEOUT);
                mutex_exit(&sc->sc_lock);
                return;
        }
+       if (xfer->ux_status != USBD_CANCELLED) {
+               xfer->ux_status = USBD_TIMEOUT;
+               timeout = true;
+       }
+       mutex_exit(&sc->sc_lock);
 
-       /* Execute the abort in a process context. */
-       usb_init_task(&xfer->ux_aborttask, dwc2_timeout_task, addr,
-           USB_TASKQ_MPSAFE);
-       usb_add_task(dxfer->xfer.ux_pipe->up_dev, &xfer->ux_aborttask,
-           USB_TASKQ_HC);
+       if (timeout) {
+               struct usbd_device *dev = xfer->ux_pipe->up_dev;
+
+               /* Execute the abort in a process context. */
+               usb_init_task(&xfer->ux_aborttask, dwc2_timeout_task, addr,
+                   USB_TASKQ_MPSAFE);
+               usb_add_task(dev, &xfer->ux_aborttask, USB_TASKQ_HC);
+
+       }
 }
 
 Static void
@@ -345,6 +351,7 @@
        DPRINTF("xfer=%p\n", xfer);
 
        mutex_enter(&sc->sc_lock);
+       KASSERT(xfer->ux_status == USBD_TIMEOUT);
        dwc2_abort_xfer(xfer, USBD_TIMEOUT);
        mutex_exit(&sc->sc_lock);
 }
@@ -455,11 +462,12 @@
        DPRINTF("xfer=%p\n", xfer);
 
        KASSERT(mutex_owned(&sc->sc_lock));
-       KASSERT(!cpu_intr_p() && !cpu_softintr_p());
+       ASSERT_SLEEPABLE();
 
        if (sc->sc_dying) {
                xfer->ux_status = status;
-               callout_stop(&xfer->ux_callout);
+               callout_halt(&xfer->ux_callout, &sc->sc_lock);
+               KASSERT(xfer->ux_status == status);
                usb_transfer_complete(xfer);
                return;
        }
@@ -479,16 +487,26 @@
        /*
         * Step 1: Make the stack ignore it and stop the callout.
         */
-       mutex_spin_enter(&hsotg->lock);
        xfer->ux_hcflags |= UXFER_ABORTING;
 
-       xfer->ux_status = status;       /* make software ignore it */
-       callout_stop(&xfer->ux_callout);
+       /*
+        * Step 1: When cancelling a transfer make sure the timeout handler
+        * didn't run or ran to the end and saw the USBD_CANCELLED status.
+        * Otherwise we must have got here via a timeout.
+        */
+       if (status == USBD_CANCELLED) {
+               xfer->ux_status = status;
+               callout_halt(&xfer->ux_callout, &sc->sc_lock);
+       } else {
+               KASSERT(xfer->ux_status == USBD_TIMEOUT);
+       }
 
+       mutex_spin_enter(&hsotg->lock);
        /* XXXNH suboptimal */
        TAILQ_FOREACH_SAFE(d, &sc->sc_complete, xnext, tmp) {
                if (d == dxfer) {
                        TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext);
+                       break;
                }
        }
 



Home | Main Index | Thread Index | Old Index