Source-Changes-HG archive

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

[src/netbsd-8]: src/sys/dev/usb Fixup for ticket #1037 - parts of the patch w...



details:   https://anonhg.NetBSD.org/src/rev/fb513474f9ef
branches:  netbsd-8
changeset: 435285:fb513474f9ef
user:      martin <martin%NetBSD.org@localhost>
date:      Fri Sep 28 08:33:43 2018 +0000

description:
Fixup for ticket #1037 - parts of the patch were accidently missing.

diffstat:

 sys/dev/usb/ehci.c    |  110 +++++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/usb/ehcivar.h |   12 +++++-
 sys/dev/usb/xhci.c    |   13 +++--
 3 files changed, 119 insertions(+), 16 deletions(-)

diffs (253 lines):

diff -r fa35d9507151 -r fb513474f9ef sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Thu Sep 27 15:57:07 2018 +0000
+++ b/sys/dev/usb/ehci.c        Fri Sep 28 08:33:43 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ehci.c,v 1.254.8.5 2018/09/27 14:52:26 martin Exp $ */
+/*     $NetBSD: ehci.c,v 1.254.8.6 2018/09/28 08:33:43 martin Exp $ */
 
 /*
  * Copyright (c) 2004-2012 The NetBSD Foundation, Inc.
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.254.8.5 2018/09/27 14:52:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.254.8.6 2018/09/28 08:33:43 martin Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -75,6 +75,7 @@
 #include <sys/select.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
+#include <sys/reboot.h>
 
 #include <machine/endian.h>
 
@@ -446,8 +447,9 @@
        }
        if (sc->sc_ncomp > 0) {
                KASSERT(!(sc->sc_flags & EHCIF_ETTF));
-               aprint_normal("%s: %d companion controller%s, %d port%s%s",
-                   device_xname(sc->sc_dev), sc->sc_ncomp,
+               aprint_normal_dev(sc->sc_dev,
+                   "%d companion controller%s, %d port%s%s",
+                   sc->sc_ncomp,
                    sc->sc_ncomp!=1 ? "s" : "",
                    EHCI_HCS_N_PCC(sparams),
                    EHCI_HCS_N_PCC(sparams)!=1 ? "s" : "",
@@ -459,6 +461,11 @@
                                    device_xname(sc->sc_comps[i]));
                }
                aprint_normal("\n");
+
+               mutex_init(&sc->sc_complock, MUTEX_DEFAULT, IPL_USB);
+               callout_init(&sc->sc_compcallout, CALLOUT_MPSAFE);
+               cv_init(&sc->sc_compcv, "ehciccv");
+               sc->sc_comp_state = CO_EARLY;
        }
        sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
        sc->sc_hasppc = EHCI_HCS_PPC(sparams);
@@ -1337,6 +1344,19 @@
        if (rv != 0)
                return rv;
 
+       if (sc->sc_ncomp > 0) {
+               mutex_enter(&sc->sc_complock);
+               /* XXX try to halt callout instead of waiting */
+               while (sc->sc_comp_state == CO_SCHED)
+                       cv_wait(&sc->sc_compcv, &sc->sc_complock);
+               mutex_exit(&sc->sc_complock);
+
+               callout_halt(&sc->sc_compcallout, NULL);
+               callout_destroy(&sc->sc_compcallout);
+               cv_destroy(&sc->sc_compcv);
+               mutex_destroy(&sc->sc_complock);
+       }
+
        callout_halt(&sc->sc_tmo_intrlist, NULL);
        callout_destroy(&sc->sc_tmo_intrlist);
 
@@ -2597,6 +2617,72 @@
        return totlen;
 }
 
+/*
+ * Handle ehci hand-off in early boot vs RB_ASKNAME/RB_SINGLE.
+ *
+ * This pile of garbage below works around the following problem without
+ * holding boots with no hand-over devices present, while penalising
+ * boots where the first ehci probe hands off devices with a 5 second
+ * delay, if RB_ASKNAME/RB_SINGLE is set.  This is typically not a problem
+ * for RB_SINGLE, but the same basic issue exists.
+ *
+ * The way ehci hand-off works, the companion controller does not get the
+ * device until after its' initial bus explore, so the reference dropped
+ * after the first explore is not enough.  5 seconds should be enough,
+ * and EHCI_DISOWN_DELAY_SECONDS can be set to another value.
+ *
+ * There are 3 states.  CO_EARLY is set during attach.  CO_SCHED is set
+ * if the callback is scheduled.  CO_DONE is set when the callout has
+ * called config_pending_decr().
+ *
+ * There's a mutex, a cv and a callout here, and we delay detach if the
+ * callout has been set.
+ */
+#ifndef EHCI_DISOWN_DELAY_SECONDS
+#define EHCI_DISOWN_DELAY_SECONDS 5
+#endif
+static int ehci_disown_delay_seconds = EHCI_DISOWN_DELAY_SECONDS;
+
+static void
+ehci_disown_callback(void *arg)
+{
+       ehci_softc_t *sc = arg;
+
+       config_pending_decr(sc->sc_dev);
+
+       mutex_enter(&sc->sc_complock);
+       KASSERT(sc->sc_comp_state == CO_SCHED);
+       sc->sc_comp_state = CO_DONE;
+       cv_signal(&sc->sc_compcv);
+       mutex_exit(&sc->sc_complock);
+}
+
+static void
+ehci_disown_sched_callback(ehci_softc_t *sc)
+{
+       extern bool root_is_mounted;
+
+       mutex_enter(&sc->sc_complock);
+
+       if (root_is_mounted ||
+           (boothowto & (RB_ASKNAME|RB_SINGLE)) == 0 ||
+           sc->sc_comp_state != CO_EARLY) {
+               mutex_exit(&sc->sc_complock);
+               return;
+       }
+
+       callout_reset(&sc->sc_compcallout, ehci_disown_delay_seconds * hz,
+           ehci_disown_callback, &sc->sc_dev);
+       sc->sc_comp_state = CO_SCHED;
+
+       mutex_exit(&sc->sc_complock);
+
+       config_pending_incr(sc->sc_dev);
+       aprint_normal("delaying %s by %u seconds due to USB owner change.",
+           (boothowto & RB_ASKNAME) == 0 ? "ask root" : "single user",
+           ehci_disown_delay_seconds);
+}
+
 Static void
 ehci_disown(ehci_softc_t *sc, int index, int lowspeed)
 {
@@ -2606,13 +2692,11 @@
        EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
        DPRINTF("index=%jd lowspeed=%jd", index, lowspeed, 0, 0);
-#ifdef DIAGNOSTIC
        if (sc->sc_npcomp != 0) {
                int i = (index-1) / sc->sc_npcomp;
-               if (i >= sc->sc_ncomp)
-                       printf("%s: strange port\n",
-                              device_xname(sc->sc_dev));
-               else
+               if (i < sc->sc_ncomp) {
+                       ehci_disown_sched_callback(sc);
+#ifdef DIAGNOSTIC
                        printf("%s: handing over %s speed device on "
                               "port %d to %s\n",
                               device_xname(sc->sc_dev),
@@ -2620,10 +2704,16 @@
                               index, sc->sc_comps[i] ?
                                 device_xname(sc->sc_comps[i]) :
                                 "companion controller");
+               } else {
+                       printf("%s: strange port\n",
+                              device_xname(sc->sc_dev));
+#endif
+               }
        } else {
+#ifdef DIAGNOSTIC
                printf("%s: npcomp == 0\n", device_xname(sc->sc_dev));
+#endif
        }
-#endif
        port = EHCI_PORTSC(index);
        v = EOREAD4(sc, port) &~ EHCI_PS_CLEAR;
        EOWRITE4(sc, port, v | EHCI_PS_PO);
diff -r fa35d9507151 -r fb513474f9ef sys/dev/usb/ehcivar.h
--- a/sys/dev/usb/ehcivar.h     Thu Sep 27 15:57:07 2018 +0000
+++ b/sys/dev/usb/ehcivar.h     Fri Sep 28 08:33:43 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ehcivar.h,v 1.43.10.1 2018/08/25 11:29:52 martin Exp $ */
+/*     $NetBSD: ehcivar.h,v 1.43.10.2 2018/09/28 08:33:43 martin Exp $ */
 
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -185,6 +185,16 @@
        u_int sc_npcomp;
        device_t sc_comps[EHCI_COMPANION_MAX];
 
+       /* This chunk to handle early RB_ASKNAME hand over. */
+       callout_t sc_compcallout;
+       kmutex_t sc_complock;
+       kcondvar_t sc_compcv;
+       enum {
+               CO_EARLY,
+               CO_SCHED,
+               CO_DONE,
+       } sc_comp_state;
+
        usb_dma_t sc_fldma;
        ehci_link_t *sc_flist;
        u_int sc_flsize;
diff -r fa35d9507151 -r fb513474f9ef sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Thu Sep 27 15:57:07 2018 +0000
+++ b/sys/dev/usb/xhci.c        Fri Sep 28 08:33:43 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.72.2.8 2018/09/27 14:52:26 martin Exp $     */
+/*     $NetBSD: xhci.c,v 1.72.2.9 2018/09/28 08:33:43 martin Exp $     */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.72.2.8 2018/09/27 14:52:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.72.2.9 2018/09/28 08:33:43 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -3979,7 +3979,7 @@
 
        xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci);
 
-       if (xfer->ux_timeout && !xhci_polling_p(sc)) {
+       if (xfer->ux_timeout && !polling) {
                callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout),
                    xhci_timeout, xfer);
        }
@@ -4055,6 +4055,7 @@
        struct xhci_ring * const tr = &xs->xs_ep[dci].xe_tr;
        struct xhci_xfer * const xx = XHCI_XFER2XXFER(xfer);
        const uint32_t len = xfer->ux_length;
+       const bool polling = xhci_polling_p(sc);
        usb_dma_t * const dma = &xfer->ux_dmabuf;
        uint64_t parameter;
        uint32_t status;
@@ -4082,9 +4083,11 @@
        xhci_trb_put(&xx->xx_trb[i++], parameter, status, control);
        xfer->ux_status = USBD_IN_PROGRESS;
 
-       mutex_enter(&tr->xr_lock);
+       if (!polling)
+               mutex_enter(&tr->xr_lock);
        xhci_ring_put(sc, tr, xfer, xx->xx_trb, i);
-       mutex_exit(&tr->xr_lock);
+       if (!polling)
+               mutex_exit(&tr->xr_lock);
 
        xhci_db_write_4(sc, XHCI_DOORBELL(xs->xs_idx), dci);
 



Home | Main Index | Thread Index | Old Index