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