Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Cancel command when command times out. From t-h...



details:   https://anonhg.NetBSD.org/src/rev/918ef4a06bd7
branches:  trunk
changeset: 344976:918ef4a06bd7
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sat Apr 30 15:00:24 2016 +0000

description:
Cancel command when command times out.  From t-hash.

XXX interrupt context?

diffstat:

 sys/dev/usb/xhci.c |  47 +++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 43 insertions(+), 4 deletions(-)

diffs (89 lines):

diff -r 6efe002b04f8 -r 918ef4a06bd7 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Sat Apr 30 14:56:20 2016 +0000
+++ b/sys/dev/usb/xhci.c        Sat Apr 30 15:00:24 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.38 2016/04/30 14:56:20 skrll Exp $  */
+/*     $NetBSD: xhci.c,v 1.39 2016/04/30 15:00:24 skrll Exp $  */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.38 2016/04/30 14:56:20 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.39 2016/04/30 15:00:24 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -289,7 +289,6 @@
        bus_space_write_4(sc->sc_iot, sc->sc_obh, offset, value);
 }
 
-#if 0 /* unused */
 static inline uint64_t
 xhci_op_read_8(const struct xhci_softc * const sc, bus_size_t offset)
 {
@@ -309,7 +308,6 @@
 
        return value;
 }
-#endif /* unused */
 
 static inline void
 xhci_op_write_8(const struct xhci_softc * const sc, bus_size_t offset,
@@ -2536,6 +2534,46 @@
 }
 
 /*
+ * Stop execution commands, purge all commands on command ring, and
+ * rewind enqueue pointer.
+ */
+static void
+xhci_abort_command(struct xhci_softc *sc)
+{
+       struct xhci_ring * const cr = &sc->sc_cr;
+       uint64_t crcr;
+       int i;
+
+       XHCIHIST_FUNC(); XHCIHIST_CALLED();
+       DPRINTFN(14, "command %#"PRIx64" timeout, aborting",
+           sc->sc_command_addr, 0, 0, 0);
+
+       mutex_enter(&cr->xr_lock);
+
+       /* 4.6.1.2 Aborting a Command */
+       crcr = xhci_op_read_8(sc, XHCI_CRCR);
+       xhci_op_write_8(sc, XHCI_CRCR, crcr | XHCI_CRCR_LO_CA);
+
+       for (i = 0; i < 500; i++) {
+               crcr = xhci_op_read_8(sc, XHCI_CRCR);
+               if ((crcr & XHCI_CRCR_LO_CRR) == 0)
+                       break;
+               usb_delay_ms(&sc->sc_bus, 1);
+       }
+       if ((crcr & XHCI_CRCR_LO_CRR) != 0) {
+               DPRINTFN(1, "Command Abort timeout", 0, 0, 0, 0);
+               /* reset HC here? */
+       }
+
+       /* reset command ring dequeue pointer */
+       cr->xr_ep = 0;
+       cr->xr_cs = 1;
+       xhci_op_write_8(sc, XHCI_CRCR, xhci_ring_trbp(cr, 0) | cr->xr_cs);
+
+       mutex_exit(&cr->xr_lock);
+}
+
+/*
  * Put a command on command ring, ring bell, set timer, and cv_timedwait.
  * Command completion is notified by cv_signal from xhci_handle_event
  * (called from interrupt from xHCI), or timed-out.
@@ -2568,6 +2606,7 @@
 
        if (cv_timedwait(&sc->sc_command_cv, &sc->sc_lock,
            MAX(1, mstohz(timeout))) == EWOULDBLOCK) {
+               xhci_abort_command(sc);
                err = USBD_TIMEOUT;
                goto timedout;
        }



Home | Main Index | Thread Index | Old Index