Module Name:    src
Committed By:   martin
Date:           Thu Sep 27 14:52:27 UTC 2018

Modified Files:
        src/share/man/man4 [netbsd-8]: usb.4
        src/sys/ddb [netbsd-8]: db_command.c db_output.c
        src/sys/dev/pci [netbsd-8]: xhci_pci.c
        src/sys/dev/usb [netbsd-8]: ehci.c ohci.c uhci.c uhcivar.h uhub.c usb.c
            usb_subr.c usbdi.c xhci.c
        src/sys/external/bsd/dwc2 [netbsd-8]: dwc2.c
        src/sys/kern [netbsd-8]: subr_userconf.c

Log Message:
Pull up following revision(s) (requested by mrg in ticket #1037):

        sys/dev/usb/uhub.c: revision 1.139
        sys/external/bsd/dwc2/dwc2.c: revision 1.55
        sys/ddb/db_output.c: revision 1.34
        sys/ddb/db_command.c: revision 1.160
        sys/dev/usb/ehci.c: revision 1.264
        sys/dev/usb/xhci.c: revision 1.99
        sys/dev/usb/ehci.c: revision 1.265
        sys/kern/subr_userconf.c: revision 1.27
        sys/dev/usb/ehcivar.h: revision 1.46
        sys/dev/usb/ohci.c: revision 1.287
        sys/dev/usb/uhci.c: revision 1.284
        sys/dev/usb/usbdi.c: revision 1.178
        sys/dev/usb/usb.c: revision 1.172
        sys/dev/pci/xhci_pci.c: revision 1.14
        sys/dev/usb/usb.c: revision 1.173
        sys/dev/usb/usb.c: revision 1.174
        share/man/man4/usb.4: revision 1.110
        sys/ddb/db_command.c: revision 1.159
        sys/dev/usb/usb_subr.c: revision 1.227
        sys/dev/usb/uhcivar.h: revision 1.56
        (all via patch)

consolidate the handling of polling across HC drivers, and generic USB:
- don't take mutexes if polling
- normalise the code across all drivers
- add some not yet code to block discovery to/from polling
- minor CSE
- adjust comment for usbd_set_polling() to reality now i properly
  understand what it is used for and why.

this, with a hack to make RB_ASKNAME to wait 5 seconds allows boot -a
work with USB keyboards.  there are still multiple issues remaining:
- discovery and polling need to be mutually exclusive
- attachment of ukbd and wskbd is not handled by config_pending, and
  the 5 second delay isn't going to always be enough.

call cnpollc(1) and cnpollc(0) around cngetc().
(christos has a good idea to add a function that does all 3,
and we should switch all the callers in this sequence to use
it (and fix the MD ones missing it still).  not all can, as
eg, line-grabbing functions can use cngetsn(), which only
calls cnpollc() twice.)

When this file is used when not building the kernel (eg: /usr/sbin/crash)
make cnpollc() go away.

reorder some struct members to remove holes.

add config_pending usage to uhub and general USB device attachment.
- call config_pending_incr() and config_pending_decr() around attaching
  devices against "usbdevif" attribute.

uhub:
- convert sc_explorepending and sc_running to bool.  add new sc_first_explore.
- call config_pending_incr() at the start of uhub_attach().  dropped in
  uhub_explore(), if this is the first explore.

implement a gross hack to fix "boot -a" on systems with usb keyboards on
systems with ehci handover to uhci (and maybe ohci), and fix a similar
problem for "boot -s".

there is effort to ensure that all devices attached via USB are probed
before RB_ASKNAME or RB_SINGLE attempts to ask any questions on the console,
and largely this works, often by chance, today, for USB disks and root.
i've recently pushed this more into uhub and general USB device attachment
as well, and kept a config_pending reference across the first explore of
a bus.  these fix many issues with directly attached hubs.

however, on systems where devices connected to ehci ports are handed over
to a companion uhci or ohci port, it may not be the first, or even second,
bus explore that finds the device finally before attachment, and at this
point all config_pending references are dropped.

there is no direct communication between drivers, the potentials are
looked up but their device_t is only used for generic things like the name,
so informing the correct companion to expect a device and deal with the
config_pending references is not possible without some fairly ugly layer
violations or multi-level callbacks (eg, we have "ehci0", and usually an
the relevant companion, eg, "uhci2", but it is the uhub that uhci2 has
attached that will deal with the device attachment.)

with the above fixes to generic USB code, the disown happens during the
first explore.  the hack works by, at this point, checking if (a) root
is not mounted, (b) single user or ask name are set, and (c) if the hack
as not been triggered already.  if all 3 conditions are true, then a
config_pending_incr() is called and a callback is triggered for (default)
5 seconds to call config_pending_decr().  ehci detach pauses waiting for
this callback if scheduled.

this allows enough time for the uhub and the ukbd/wskbd to attach before
the RK_ASKROOT prompts appear.  testing shows it takes between 1.5 and
2 seconds for the keyboard to appear after the disown occurs.

Index: dev/usb/ehcivar.c
- new sc_compcallout, sc_compcallout, sc_complock, and a state for th
  handover hack.

Index: dev/usb/ehci.c
ehci_init():
- use aprint_normal_dev() instead of manual device_xname().
- initialise sc_compcallout, sc_compcallout, sc_complock, and sc_comp_state.
ehci_detach():
- if there are companion controllers, tear own the above, including waiting
  if there is a callback scheduled.
ehci_disown_callback():
- new callout to call config_pending_decr() in the the future.
  schedule this ca
ehci_disown_sched_callback():
- if booting to single user or asking names, call config_pending_incr() and
  schedule the callout above, default 5 second delay.
ehci_disown():
- if disowning a port call ehci_disown_sched_callback().
deal with partial attach failures in usb_attach vs usb_detach aka PR 53598.
- make sure xhci's sc->sc_ios is NULL if failure happens.
- rearrange usb_attach() / usb_doattach() to make it simpler to clean up.
- move usb_async_intr softint into usb_once_init().  previously, each USB
  controller would start a new one, and leave the old one leaked.
- handle controller interrupts without a bus attached

remove usb(4)'s "flags 1" code.  it has been dead for a while,
as it runs during the interrupts part of configuration now,
and all the devices try attach as early as possible, including
any root or boot required disk or keyboard device, which is
what this flag was for.


To generate a diff of this commit:
cvs rdiff -u -r1.105 -r1.105.4.1 src/share/man/man4/usb.4
cvs rdiff -u -r1.148.8.4 -r1.148.8.5 src/sys/ddb/db_command.c
cvs rdiff -u -r1.33 -r1.33.32.1 src/sys/ddb/db_output.c
cvs rdiff -u -r1.8 -r1.8.6.1 src/sys/dev/pci/xhci_pci.c
cvs rdiff -u -r1.254.8.4 -r1.254.8.5 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.273.6.3 -r1.273.6.4 src/sys/dev/usb/ohci.c
cvs rdiff -u -r1.275.2.4 -r1.275.2.5 src/sys/dev/usb/uhci.c
cvs rdiff -u -r1.53.10.1 -r1.53.10.2 src/sys/dev/usb/uhcivar.h
cvs rdiff -u -r1.136.2.1 -r1.136.2.2 src/sys/dev/usb/uhub.c
cvs rdiff -u -r1.165.6.3 -r1.165.6.4 src/sys/dev/usb/usb.c
cvs rdiff -u -r1.220.2.4 -r1.220.2.5 src/sys/dev/usb/usb_subr.c
cvs rdiff -u -r1.173.2.2 -r1.173.2.3 src/sys/dev/usb/usbdi.c
cvs rdiff -u -r1.72.2.7 -r1.72.2.8 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.46.2.2 -r1.46.2.3 src/sys/external/bsd/dwc2/dwc2.c
cvs rdiff -u -r1.26 -r1.26.22.1 src/sys/kern/subr_userconf.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/usb.4
diff -u src/share/man/man4/usb.4:1.105 src/share/man/man4/usb.4:1.105.4.1
--- src/share/man/man4/usb.4:1.105	Sat Jan 21 20:30:29 2017
+++ src/share/man/man4/usb.4	Thu Sep 27 14:52:27 2018
@@ -1,4 +1,4 @@
-.\" $NetBSD: usb.4,v 1.105 2017/01/21 20:30:29 jdolecek Exp $
+.\" $NetBSD: usb.4,v 1.105.4.1 2018/09/27 14:52:27 martin Exp $
 .\"
 .\" Copyright (c) 1999-2014 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -43,10 +43,10 @@
 .Cd "slhci*  at pcmcia? function ?"
 .Cd "uhci*   at cardbus? function ?"
 .Cd "uhci*   at pci? dev ? function ?"
-.Cd "usb*    at ehci? flags X"
-.Cd "usb*    at ohci? flags X"
-.Cd "usb*    at uhci? flags X"
-.Cd "usb*    at slhci? flags X"
+.Cd "usb*    at ehci?"
+.Cd "usb*    at ohci?"
+.Cd "usb*    at uhci?"
+.Cd "usb*    at slhci?"
 .Cd "uhub*   at usb?"
 .Cd "uhub*   at uhub? port ? configuration ? interface ? vendor ? product ? release ?"
 .Cd "XX*     at uhub? port ? configuration ? interface ? vendor ? product ? release ?"
@@ -92,26 +92,6 @@ hubs and must always be present since th
 .Tn USB
 system.
 .Pp
-The
-.Va flags
-argument to the
-.Va usb
-device affects the order in which the device detection happens
-during cold boot.
-Normally, only the USB host controller and the
-.Va usb
-device are detected during the autoconfiguration when the
-machine is booted.
-The rest of the devices are detected once
-the system becomes functional and the kernel thread for the
-.Va usb
-device is started.
-Sometimes it is desirable to have a device detected early in the
-boot process, e.g., the console keyboard.
-To achieve this use a
-.Va flags
-value of 1.
-.Pp
 .Nx
 supports the following machine-independent
 .Tn USB

Index: src/sys/ddb/db_command.c
diff -u src/sys/ddb/db_command.c:1.148.8.4 src/sys/ddb/db_command.c:1.148.8.5
--- src/sys/ddb/db_command.c:1.148.8.4	Sun Sep 23 17:28:25 2018
+++ src/sys/ddb/db_command.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_command.c,v 1.148.8.4 2018/09/23 17:28:25 martin Exp $	*/
+/*	$NetBSD: db_command.c,v 1.148.8.5 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997, 1998, 1999, 2002, 2009 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.148.8.4 2018/09/23 17:28:25 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.148.8.5 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_aio.h"
@@ -90,10 +90,10 @@ __KERNEL_RCSID(0, "$NetBSD: db_command.c
 #include <sys/module.h>
 #include <sys/kernhist.h>
 #include <sys/socketvar.h>
-
-/*include queue macros*/
 #include <sys/queue.h>
 
+#include <dev/cons.h>
+
 #include <ddb/ddb.h>
 
 #include <uvm/uvm_extern.h>
@@ -541,7 +541,14 @@ db_unregister_tbl(uint8_t type,const str
 	return ENOENT;
 }
 
-/* This function is called from machine trap code. */
+#ifndef _KERNEL
+#define	cnpollc(c)	__nothing
+#endif
+
+/*
+ * This function is called via db_trap() or directly from
+ * machine trap code.
+ */
 void
 db_command_loop(void)
 {
@@ -578,7 +585,9 @@ db_command_loop(void)
 		if (db_print_position() != 0)
 			db_printf("\n");
 		db_output_line = 0;
+		cnpollc(1);
 		(void) db_read_line();
+		cnpollc(0);
 		db_command(&db_last_command);
 	}
 

Index: src/sys/ddb/db_output.c
diff -u src/sys/ddb/db_output.c:1.33 src/sys/ddb/db_output.c:1.33.32.1
--- src/sys/ddb/db_output.c:1.33	Sat Sep  1 01:13:51 2012
+++ src/sys/ddb/db_output.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_output.c,v 1.33 2012/09/01 01:13:51 matt Exp $	*/
+/*	$NetBSD: db_output.c,v 1.33.32.1 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Mach Operating System
@@ -35,7 +35,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_output.c,v 1.33 2012/09/01 01:13:51 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_output.c,v 1.33.32.1 2018/09/27 14:52:26 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -111,7 +111,7 @@ db_more(void)
 
 	for (p = "--db_more--"; *p; p++)
 		cnputc(*p);
-	switch(cngetc()) {
+	switch (cngetc()) {
 	case ' ':
 		db_output_line = 0;
 		break;

Index: src/sys/dev/pci/xhci_pci.c
diff -u src/sys/dev/pci/xhci_pci.c:1.8 src/sys/dev/pci/xhci_pci.c:1.8.6.1
--- src/sys/dev/pci/xhci_pci.c:1.8	Thu Jan 19 16:05:00 2017
+++ src/sys/dev/pci/xhci_pci.c	Thu Sep 27 14:52:27 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci_pci.c,v 1.8 2017/01/19 16:05:00 skrll Exp $	*/
+/*	$NetBSD: xhci_pci.c,v 1.8.6.1 2018/09/27 14:52:27 martin Exp $	*/
 /*	OpenBSD: xhci_pci.c,v 1.4 2014/07/12 17:38:51 yuo Exp	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v 1.8 2017/01/19 16:05:00 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v 1.8.6.1 2018/09/27 14:52:27 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -138,6 +138,7 @@ xhci_pci_attach(device_t parent, device_
 	printf("%s: csr: %08x\n", __func__, csr);
 #endif
 	if ((csr & PCI_COMMAND_MEM_ENABLE) == 0) {
+		sc->sc_ios = 0;
 		aprint_error_dev(self, "memory access is disabled\n");
 		return;
 	}
@@ -155,6 +156,7 @@ xhci_pci_attach(device_t parent, device_
 		}
 		break;
 	default:
+		sc->sc_ios = 0;
 		aprint_error_dev(self, "BAR not 64 or 32-bit MMIO\n");
 		return;
 	}

Index: src/sys/dev/usb/ehci.c
diff -u src/sys/dev/usb/ehci.c:1.254.8.4 src/sys/dev/usb/ehci.c:1.254.8.5
--- src/sys/dev/usb/ehci.c:1.254.8.4	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/ehci.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci.c,v 1.254.8.4 2018/08/25 11:29:52 martin Exp $ */
+/*	$NetBSD: ehci.c,v 1.254.8.5 2018/09/27 14:52:26 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.4 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.254.8.5 2018/09/27 14:52:26 martin Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -2650,13 +2650,16 @@ Static usbd_status
 ehci_root_intr_start(struct usbd_xfer *xfer)
 {
 	ehci_softc_t *sc = EHCI_XFER2SC(xfer);
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	sc->sc_intrxfer = xfer;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3551,6 +3554,7 @@ ehci_device_ctrl_start(struct usbd_xfer 
 	ehci_softc_t *sc = EHCI_XFER2SC(xfer);
 	ehci_soft_qtd_t *setup, *status, *next;
 	ehci_soft_qh_t *sqh;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
@@ -3670,7 +3674,8 @@ ehci_device_ctrl_start(struct usbd_xfer 
 	DPRINTFN(5, "--- dump end ---", 0, 0, 0, 0);
 #endif
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	/* Insert qTD in QH list - also does usb_syncmem(sqh) */
 	ehci_set_qh_qtd(sqh, setup);
@@ -3680,7 +3685,8 @@ ehci_device_ctrl_start(struct usbd_xfer 
 	}
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG
@@ -3827,6 +3833,7 @@ ehci_device_bulk_start(struct usbd_xfer 
 	ehci_soft_qh_t *sqh;
 	ehci_soft_qtd_t *end;
 	int len, isread, endpt;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
@@ -3850,7 +3857,8 @@ ehci_device_bulk_start(struct usbd_xfer 
 #endif
 
 	/* Take lock here to protect nexttoggle */
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end);
 
@@ -3877,7 +3885,8 @@ ehci_device_bulk_start(struct usbd_xfer 
 	}
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG
@@ -4042,6 +4051,7 @@ ehci_device_intr_start(struct usbd_xfer 
 	ehci_soft_qtd_t *end;
 	ehci_soft_qh_t *sqh;
 	int len, isread, endpt;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 
@@ -4065,7 +4075,8 @@ ehci_device_intr_start(struct usbd_xfer 
 #endif
 
 	/* Take lock to protect nexttoggle */
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end);
 
@@ -4092,7 +4103,8 @@ ehci_device_intr_start(struct usbd_xfer 
 	}
 	ehci_add_intr_list(sc, exfer);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 #if 0
 #ifdef EHCI_DEBUG

Index: src/sys/dev/usb/ohci.c
diff -u src/sys/dev/usb/ohci.c:1.273.6.3 src/sys/dev/usb/ohci.c:1.273.6.4
--- src/sys/dev/usb/ohci.c:1.273.6.3	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/ohci.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohci.c,v 1.273.6.3 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: ohci.c,v 1.273.6.4 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2005, 2012 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.273.6.3 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.273.6.4 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2607,14 +2607,17 @@ Static usbd_status
 ohci_root_intr_start(struct usbd_xfer *xfer)
 {
 	ohci_softc_t *sc = OHCI_XFER2SC(xfer);
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2750,6 +2753,7 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	ohci_soft_ed_t *sed;
 	int isread;
 	int len;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
@@ -2768,7 +2772,8 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	    UGETW(req->wIndex));
 
 	/* Need to take lock here for pipe->tail.td */
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
@@ -2884,7 +2889,7 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	    sizeof(sed->ed.ed_tailp),
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
-	if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) {
+	if (xfer->ux_timeout && !polling) {
 		callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout),
 			    ohci_timeout, xfer);
 	}
@@ -2892,7 +2897,8 @@ ohci_device_ctrl_start(struct usbd_xfer 
 	DPRINTF("done", 0, 0, 0, 0);
 
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3019,6 +3025,7 @@ ohci_device_bulk_start(struct usbd_xfer 
 	ohci_soft_td_t *data, *tail, *tdp;
 	ohci_soft_ed_t *sed;
 	int len, isread, endpt;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
@@ -3036,7 +3043,8 @@ ohci_device_bulk_start(struct usbd_xfer 
 	    len, isread, xfer->ux_flags);
 	DPRINTFN(4, "endpt=%jd", endpt, 0, 0, 0);
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
@@ -3102,7 +3110,8 @@ ohci_device_bulk_start(struct usbd_xfer 
 	}
 
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3221,6 +3230,7 @@ ohci_device_intr_start(struct usbd_xfer 
 	ohci_soft_ed_t *sed = opipe->sed;
 	ohci_soft_td_t *data, *last, *tail;
 	int len, isread, endpt;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
@@ -3236,7 +3246,8 @@ ohci_device_intr_start(struct usbd_xfer 
 	endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress;
 	isread = UE_GET_DIR(endpt) == UE_DIR_IN;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	/*
 	 * Use the pipe "tail" TD as our first and loan our first TD to the
@@ -3288,7 +3299,8 @@ ohci_device_intr_start(struct usbd_xfer 
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }

Index: src/sys/dev/usb/uhci.c
diff -u src/sys/dev/usb/uhci.c:1.275.2.4 src/sys/dev/usb/uhci.c:1.275.2.5
--- src/sys/dev/usb/uhci.c:1.275.2.4	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/uhci.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhci.c,v 1.275.2.4 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: uhci.c,v 1.275.2.5 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.275.2.4 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.275.2.5 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -2256,6 +2256,7 @@ uhci_device_bulk_start(struct usbd_xfer 
 	uhci_softc_t *sc = UHCI_XFER2SC(xfer);
 	uhci_soft_td_t *data, *dataend;
 	uhci_soft_qh_t *sqh;
+	const bool polling = sc->sc_bus.ub_usepolling;
 	int len;
 	int endpt;
 	int isread;
@@ -2276,7 +2277,8 @@ uhci_device_bulk_start(struct usbd_xfer 
 	sqh = upipe->bulk.sqh;
 
 	/* Take lock here to protect nexttoggle */
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	uhci_reset_std_chain(sc, xfer, len, isread, &upipe->nexttoggle,
 	    &dataend);
@@ -2310,12 +2312,13 @@ uhci_device_bulk_start(struct usbd_xfer 
 	uhci_add_bulk(sc, sqh);
 	uhci_add_intr_list(sc, ux);
 
-	if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) {
+	if (xfer->ux_timeout && !polling) {
 		callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout),
 			    uhci_timeout, xfer);
 	}
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2540,6 +2543,7 @@ uhci_device_ctrl_start(struct usbd_xfer 
 	int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress;
 	uhci_soft_td_t *setup, *stat, *next, *dataend;
 	uhci_soft_qh_t *sqh;
+	const bool polling = sc->sc_bus.ub_usepolling;
 	int len;
 	int isread;
 
@@ -2567,7 +2571,8 @@ uhci_device_ctrl_start(struct usbd_xfer 
 	memcpy(KERNADDR(&upipe->ctrl.reqdma, 0), req, sizeof(*req));
 	usb_syncmem(&upipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE);
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 
 	/* Set up data transaction */
 	if (len != 0) {
@@ -2664,12 +2669,13 @@ uhci_device_ctrl_start(struct usbd_xfer 
 		DPRINTF("--- dump end ---", 0, 0, 0, 0);
 	}
 #endif
-	if (xfer->ux_timeout && !sc->sc_bus.ub_usepolling) {
+	if (xfer->ux_timeout && !polling) {
 		callout_reset(&xfer->ux_callout, mstohz(xfer->ux_timeout),
 			    uhci_timeout, xfer);
 	}
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -2742,6 +2748,7 @@ uhci_device_intr_start(struct usbd_xfer 
 	uhci_softc_t *sc = UHCI_XFER2SC(xfer);
 	uhci_soft_td_t *data, *dataend;
 	uhci_soft_qh_t *sqh;
+	const bool polling = sc->sc_bus.ub_usepolling;
 	int isread, endpt;
 	int i;
 
@@ -2767,7 +2774,8 @@ uhci_device_intr_start(struct usbd_xfer 
 #endif
 
 	/* Take lock to protect nexttoggle */
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread,
 	    &upipe->nexttoggle, &dataend);
 
@@ -2799,7 +2807,8 @@ uhci_device_intr_start(struct usbd_xfer 
 	}
 	uhci_add_intr_list(sc, ux);
 	xfer->ux_status = USBD_IN_PROGRESS;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 #ifdef UHCI_DEBUG
 	if (uhcidebug >= 10) {

Index: src/sys/dev/usb/uhcivar.h
diff -u src/sys/dev/usb/uhcivar.h:1.53.10.1 src/sys/dev/usb/uhcivar.h:1.53.10.2
--- src/sys/dev/usb/uhcivar.h:1.53.10.1	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/uhcivar.h	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhcivar.h,v 1.53.10.1 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: uhcivar.h,v 1.53.10.2 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -170,8 +170,8 @@ typedef struct uhci_softc {
 
 	pool_cache_t sc_xferpool;	/* free xfer pool */
 
-	uint8_t sc_saved_sof;
 	uint16_t sc_saved_frnum;
+	uint8_t sc_saved_sof;
 
 	char sc_isreset;
 	char sc_suspend;

Index: src/sys/dev/usb/uhub.c
diff -u src/sys/dev/usb/uhub.c:1.136.2.1 src/sys/dev/usb/uhub.c:1.136.2.2
--- src/sys/dev/usb/uhub.c:1.136.2.1	Thu Nov  2 21:29:52 2017
+++ src/sys/dev/usb/uhub.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhub.c,v 1.136.2.1 2017/11/02 21:29:52 snj Exp $	*/
+/*	$NetBSD: uhub.c,v 1.136.2.2 2018/09/27 14:52:26 martin Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $	*/
 /*	$OpenBSD: uhub.c,v 1.86 2015/06/29 18:27:40 mpi Exp $ */
 
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.136.2.1 2017/11/02 21:29:52 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.136.2.2 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -113,9 +113,9 @@ struct uhub_softc {
 	uint8_t			*sc_statuspend;
 	uint8_t			*sc_status;
 	size_t			 sc_statuslen;
-	int			 sc_explorepending;
-
-	u_char			 sc_running;
+	bool			 sc_explorepending;
+	bool			 sc_first_explore;
+	bool			 sc_running;
 };
 
 #define UHUB_IS_HIGH_SPEED(sc) \
@@ -262,6 +262,8 @@ uhub_attach(device_t parent, device_t se
 	usb_endpoint_descriptor_t *ed;
 	struct usbd_tt *tts = NULL;
 
+	config_pending_incr(self);
+
 	UHUBHIST_FUNC(); UHUBHIST_CALLED();
 
 	sc->sc_dev = self;
@@ -283,14 +285,14 @@ uhub_attach(device_t parent, device_t se
 	if (err) {
 		DPRINTF("configuration failed, sc %#jx error %jd",
 		    (uintptr_t)sc, err, 0, 0);
-		return;
+		goto bad2;
 	}
 
 	if (dev->ud_depth > USB_HUB_MAX_DEPTH) {
 		aprint_error_dev(self,
 		    "hub depth (%d) exceeded, hub ignored\n",
 		    USB_HUB_MAX_DEPTH);
-		return;
+		goto bad2;
 	}
 
 	/* Get hub descriptor. */
@@ -300,7 +302,7 @@ uhub_attach(device_t parent, device_t se
 	if (err) {
 		DPRINTF("getting hub descriptor failed, uhub%jd error %jd",
 		    device_unit(self), err, 0, 0);
-		return;
+		goto bad2;
 	}
 
 	for (nremov = 0, port = 1; port <= nports; port++)
@@ -364,7 +366,7 @@ uhub_attach(device_t parent, device_t se
 
 	/* force initial scan */
 	memset(sc->sc_status, 0xff, sc->sc_statuslen);
-	sc->sc_explorepending = 1;
+	sc->sc_explorepending = true;
 
 	err = usbd_open_pipe_intr(iface, ed->bEndpointAddress,
 		  USBD_SHORT_XFER_OK|USBD_MPSAFE, &sc->sc_ipipe, sc,
@@ -449,8 +451,8 @@ uhub_attach(device_t parent, device_t se
 		usbd_delay_ms(dev, pwrdly);
 
 	/* The usual exploration will finish the setup. */
-
-	sc->sc_running = 1;
+	sc->sc_running = true;
+	sc->sc_first_explore = true;
 
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
@@ -468,7 +470,8 @@ uhub_attach(device_t parent, device_t se
 		kmem_free(hub,
 		    sizeof(*hub) + (nports-1) * sizeof(struct usbd_port));
 	dev->ud_hub = NULL;
-	return;
+ bad2:
+	config_pending_decr(self);
 }
 
 usbd_status
@@ -777,7 +780,7 @@ uhub_explore(struct usbd_device *dev)
 		}
 	}
 	mutex_enter(&sc->sc_lock);
-	sc->sc_explorepending = 0;
+	sc->sc_explorepending = false;
 	for (int i = 0; i < sc->sc_statuslen; i++) {
 		if (sc->sc_statuspend[i] != 0) {
 			memcpy(sc->sc_status, sc->sc_statuspend,
@@ -788,6 +791,10 @@ uhub_explore(struct usbd_device *dev)
 		}
 	}
 	mutex_exit(&sc->sc_lock);
+	if (sc->sc_first_explore) {
+		config_pending_decr(sc->sc_dev);
+		sc->sc_first_explore = false;
+	}
 
 	return USBD_NORMAL_COMPLETION;
 }
@@ -942,7 +949,7 @@ uhub_intr(struct usbd_xfer *xfer, void *
 		}
 
 		if (!sc->sc_explorepending) {
-			sc->sc_explorepending = 1;
+			sc->sc_explorepending = true;
 
 			memcpy(sc->sc_status, sc->sc_statuspend,
 			    sc->sc_statuslen);

Index: src/sys/dev/usb/usb.c
diff -u src/sys/dev/usb/usb.c:1.165.6.3 src/sys/dev/usb/usb.c:1.165.6.4
--- src/sys/dev/usb/usb.c:1.165.6.3	Wed Aug  8 10:28:35 2018
+++ src/sys/dev/usb/usb.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb.c,v 1.165.6.3 2018/08/08 10:28:35 martin Exp $	*/
+/*	$NetBSD: usb.c,v 1.165.6.4 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2002, 2008, 2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.165.6.3 2018/08/08 10:28:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.165.6.4 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -138,6 +138,7 @@ struct usb_softc {
 	struct lwp	*sc_event_thread;
 
 	char		sc_dying;
+	bool		sc_pmf_registered;
 };
 
 struct usb_taskq {
@@ -189,6 +190,7 @@ Static int usb_nevents = 0;
 Static struct selinfo usb_selevent;
 Static kmutex_t usb_event_lock;
 Static kcondvar_t usb_event_cv;
+/* XXX this is gross and broken */
 Static proc_t *usb_async_proc;  /* process that wants USB SIGIO */
 Static void *usb_async_sih;
 Static int usb_dev_open = 0;
@@ -239,6 +241,9 @@ usb_attach(device_t parent, device_t sel
 	sc->sc_bus = aux;
 	usbrev = sc->sc_bus->ub_revision;
 
+	cv_init(&sc->sc_bus->ub_needsexplore_cv, "usbevt");
+	sc->sc_pmf_registered = false;
+
 	aprint_naive("\n");
 	aprint_normal(": USB revision %s", usbrev_str[usbrev]);
 	switch (usbrev) {
@@ -306,6 +311,11 @@ usb_once_init(void)
 		 * end up using them in usb_doattach().
 		 */
 	}
+
+	KASSERT(usb_async_sih == NULL);
+	usb_async_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
+	   usb_async_intr, NULL);
+
 	return 0;
 }
 
@@ -338,8 +348,6 @@ usb_doattach(device_t self)
 		panic("usb_doattach");
 	}
 
-	cv_init(&sc->sc_bus->ub_needsexplore_cv, "usbevt");
-
 	ue = usb_alloc_event();
 	ue->u.ue_ctrlr.ue_bus = device_unit(self);
 	usb_add_event(USB_EVENT_CTRLR_ATTACH, ue);
@@ -356,28 +364,22 @@ usb_doattach(device_t self)
 		}
 		sc->sc_bus->ub_roothub = dev;
 		usb_create_event_thread(self);
-#if 1
-		/*
-		 * Turning this code off will delay attachment of USB devices
-		 * until the USB event thread is running, which means that
-		 * the keyboard will not work until after cold boot.
-		 */
-		if (cold && (device_cfdata(self)->cf_flags & 1))
-			dev->ud_hub->uh_explore(sc->sc_bus->ub_roothub);
-#endif
 	} else {
 		aprint_error("%s: root hub problem, error=%s\n",
 			     device_xname(self), usbd_errstr(err));
 		sc->sc_dying = 1;
 	}
 
+	/*
+	 * Drop this reference after the first set of attachments in the
+	 * event thread.
+	 */
 	config_pending_incr(self);
 
 	if (!pmf_device_register(self, NULL, NULL))
 		aprint_error_dev(self, "couldn't establish power handler\n");
-
-	usb_async_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
-	   usb_async_intr, NULL);
+	else
+		sc->sc_pmf_registered = true;
 
 	return;
 }
@@ -525,6 +527,7 @@ void
 usb_event_thread(void *arg)
 {
 	struct usb_softc *sc = arg;
+	struct usbd_bus *bus = sc->sc_bus;
 
 	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
 
@@ -536,30 +539,37 @@ usb_event_thread(void *arg)
 	 * know how to synchronize the creation of the threads so it
 	 * will work.
 	 */
-	usb_delay_ms(sc->sc_bus, 500);
+	usb_delay_ms(bus, 500);
 
 	/* Make sure first discover does something. */
-	mutex_enter(sc->sc_bus->ub_lock);
+	mutex_enter(bus->ub_lock);
 	sc->sc_bus->ub_needsexplore = 1;
 	usb_discover(sc);
-	mutex_exit(sc->sc_bus->ub_lock);
-	config_pending_decr(sc->sc_bus->ub_usbctl);
+	mutex_exit(bus->ub_lock);
 
-	mutex_enter(sc->sc_bus->ub_lock);
+	/* Drop the config_pending reference from attach. */
+	config_pending_decr(bus->ub_usbctl);
+
+	mutex_enter(bus->ub_lock);
 	while (!sc->sc_dying) {
+#if 0 /* not yet */
+		while (sc->sc_bus->ub_usepolling)
+			kpause("usbpoll", true, hz, bus->ub_lock);
+#endif
+
 		if (usb_noexplore < 2)
 			usb_discover(sc);
 
-		cv_timedwait(&sc->sc_bus->ub_needsexplore_cv,
-		    sc->sc_bus->ub_lock, usb_noexplore ? 0 : hz * 60);
+		cv_timedwait(&bus->ub_needsexplore_cv,
+		    bus->ub_lock, usb_noexplore ? 0 : hz * 60);
 
 		DPRINTFN(2, "sc %#jx woke up", (uintptr_t)sc, 0, 0, 0);
 	}
 	sc->sc_event_thread = NULL;
 
 	/* In case parent is waiting for us to exit. */
-	cv_signal(&sc->sc_bus->ub_needsexplore_cv);
-	mutex_exit(sc->sc_bus->ub_lock);
+	cv_signal(&bus->ub_needsexplore_cv);
+	mutex_exit(bus->ub_lock);
 
 	DPRINTF("sc %#jx exit", (uintptr_t)sc, 0, 0, 0);
 	kthread_exit(0);
@@ -989,25 +999,28 @@ usbkqfilter(dev_t dev, struct knote *kn)
 Static void
 usb_discover(struct usb_softc *sc)
 {
+	struct usbd_bus *bus = sc->sc_bus;
 
 	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
 
-	KASSERT(mutex_owned(sc->sc_bus->ub_lock));
+	KASSERT(mutex_owned(bus->ub_lock));
 
 	if (usb_noexplore > 1)
 		return;
+
 	/*
 	 * We need mutual exclusion while traversing the device tree,
 	 * but this is guaranteed since this function is only called
 	 * from the event thread for the controller.
 	 *
-	 * Also, we now have sc_bus->ub_lock held.
+	 * Also, we now have bus->ub_lock held, and in combination
+	 * with ub_exploring, avoids interferring with polling.
 	 */
-	while (sc->sc_bus->ub_needsexplore && !sc->sc_dying) {
-		sc->sc_bus->ub_needsexplore = 0;
+	while (bus->ub_needsexplore && !sc->sc_dying) {
+		bus->ub_needsexplore = 0;
 		mutex_exit(sc->sc_bus->ub_lock);
-		sc->sc_bus->ub_roothub->ud_hub->uh_explore(sc->sc_bus->ub_roothub);
-		mutex_enter(sc->sc_bus->ub_lock);
+		bus->ub_roothub->ud_hub->uh_explore(bus->ub_roothub);
+		mutex_enter(bus->ub_lock);
 	}
 }
 
@@ -1156,6 +1169,10 @@ usb_schedsoftintr(struct usbd_bus *bus)
 
 	DPRINTFN(10, "polling=%jd", bus->ub_usepolling, 0, 0, 0);
 
+	/* In case the bus never finished setting up. */
+	if (__predict_false(bus->ub_soft == NULL))
+		return;
+
 	if (bus->ub_usepolling) {
 		bus->ub_methods->ubm_softint(bus);
 	} else {
@@ -1208,7 +1225,8 @@ usb_detach(device_t self, int flags)
 	    (rc = usb_disconnect_port(&sc->sc_port, self, flags)) != 0)
 		return rc;
 
-	pmf_device_deregister(self);
+	if (sc->sc_pmf_registered)
+		pmf_device_deregister(self);
 	/* Kill off event thread. */
 	sc->sc_dying = 1;
 	while (sc->sc_event_thread != NULL) {

Index: src/sys/dev/usb/usb_subr.c
diff -u src/sys/dev/usb/usb_subr.c:1.220.2.4 src/sys/dev/usb/usb_subr.c:1.220.2.5
--- src/sys/dev/usb/usb_subr.c:1.220.2.4	Sun Aug 26 08:05:16 2018
+++ src/sys/dev/usb/usb_subr.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_subr.c,v 1.220.2.4 2018/08/26 08:05:16 martin Exp $	*/
+/*	$NetBSD: usb_subr.c,v 1.220.2.5 2018/09/27 14:52:26 martin Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.220.2.4 2018/08/26 08:05:16 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.220.2.5 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -907,6 +907,7 @@ usbd_attachwholedevice(device_t parent, 
 	dlocs[USBDEVIFCF_INTERFACE] = -1;
 
 	KERNEL_LOCK(1, curlwp);
+	config_pending_incr(parent);
 	dv = config_found_sm_loc(parent, "usbdevif", dlocs, &uaa, usbd_print,
 				 config_stdsubmatch);
 	KERNEL_UNLOCK_ONE(curlwp);
@@ -917,6 +918,7 @@ usbd_attachwholedevice(device_t parent, 
 		dev->ud_nifaces_claimed = 1; /* XXX */
 		usbd_serialnumber(dv, dev);
 	}
+	config_pending_decr(parent);
 	return USBD_NORMAL_COMPLETION;
 }
 

Index: src/sys/dev/usb/usbdi.c
diff -u src/sys/dev/usb/usbdi.c:1.173.2.2 src/sys/dev/usb/usbdi.c:1.173.2.3
--- src/sys/dev/usb/usbdi.c:1.173.2.2	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/usbdi.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi.c,v 1.173.2.2 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: usbdi.c,v 1.173.2.3 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012, 2015 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.173.2.2 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.173.2.3 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -963,19 +963,19 @@ usb_transfer_complete(struct usbd_xfer *
 	    (uintptr_t)xfer, (uintptr_t)xfer->ux_callback, xfer->ux_status, 0);
 
 	if (xfer->ux_callback) {
-		if (!polling)
+		if (!polling) {
 			mutex_exit(pipe->up_dev->ud_bus->ub_lock);
-
-		if (!(pipe->up_flags & USBD_MPSAFE))
-			KERNEL_LOCK(1, curlwp);
+			if (!(pipe->up_flags & USBD_MPSAFE))
+				KERNEL_LOCK(1, curlwp);
+		}
 
 		xfer->ux_callback(xfer, xfer->ux_priv, xfer->ux_status);
 
-		if (!(pipe->up_flags & USBD_MPSAFE))
-			KERNEL_UNLOCK_ONE(curlwp);
-
-		if (!polling)
+		if (!polling) {
+			if (!(pipe->up_flags & USBD_MPSAFE))
+				KERNEL_UNLOCK_ONE(curlwp);
 			mutex_enter(pipe->up_dev->ud_bus->ub_lock);
+		}
 	}
 
 	if (sync && !polling) {
@@ -1143,7 +1143,8 @@ usbd_dopoll(struct usbd_interface *iface
 }
 
 /*
- * XXX use this more???  ub_usepolling it touched manually all over
+ * This is for keyboard driver as well, which only operates in polling
+ * mode from the ask root, etc., prompt and from DDB.
  */
 void
 usbd_set_polling(struct usbd_device *dev, int on)

Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.72.2.7 src/sys/dev/usb/xhci.c:1.72.2.8
--- src/sys/dev/usb/xhci.c:1.72.2.7	Sat Aug 25 11:29:52 2018
+++ src/sys/dev/usb/xhci.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.72.2.7 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: xhci.c,v 1.72.2.8 2018/09/27 14:52:26 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.7 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.72.2.8 2018/09/27 14:52:26 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -3711,15 +3711,18 @@ xhci_root_intr_start(struct usbd_xfer *x
 {
 	struct xhci_softc * const sc = XHCI_XFER2SC(xfer);
 	const size_t bn = XHCI_XFER2BUS(xfer) == &sc->sc_bus ? 0 : 1;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	sc->sc_intrxfer[bn] = xfer;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -3800,6 +3803,7 @@ xhci_device_ctrl_start(struct usbd_xfer 
 	uint32_t status;
 	uint32_t control;
 	u_int i;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 	DPRINTFN(12, "req: %04jx %04jx %04jx %04jx",
@@ -3846,9 +3850,11 @@ xhci_device_ctrl_start(struct usbd_xfer 
 	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);
 
@@ -3931,6 +3937,7 @@ xhci_device_bulk_start(struct usbd_xfer 
 	uint32_t status;
 	uint32_t control;
 	u_int i = 0;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
@@ -3964,9 +3971,11 @@ xhci_device_bulk_start(struct usbd_xfer 
 	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);
 

Index: src/sys/external/bsd/dwc2/dwc2.c
diff -u src/sys/external/bsd/dwc2/dwc2.c:1.46.2.2 src/sys/external/bsd/dwc2/dwc2.c:1.46.2.3
--- src/sys/external/bsd/dwc2/dwc2.c:1.46.2.2	Sat Aug 25 11:29:52 2018
+++ src/sys/external/bsd/dwc2/dwc2.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: dwc2.c,v 1.46.2.2 2018/08/25 11:29:52 martin Exp $	*/
+/*	$NetBSD: dwc2.c,v 1.46.2.3 2018/09/27 14:52:26 martin Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.46.2.2 2018/08/25 11:29:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.46.2.3 2018/09/27 14:52:26 martin Exp $");
 
 #include "opt_usb.h"
 
@@ -630,16 +630,19 @@ Static usbd_status
 dwc2_root_intr_start(struct usbd_xfer *xfer)
 {
 	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	DPRINTF("\n");
 
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	return USBD_IN_PROGRESS;
 }
@@ -709,13 +712,16 @@ dwc2_device_ctrl_start(struct usbd_xfer 
 {
 	struct dwc2_softc *sc = DWC2_XFER2SC(xfer);
 	usbd_status err;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
 	DPRINTF("\n");
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	xfer->ux_status = USBD_IN_PROGRESS;
 	err = dwc2_device_start(xfer);
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	if (err)
 		return err;
@@ -829,11 +835,14 @@ dwc2_device_intr_start(struct usbd_xfer 
 	struct usbd_device *dev = dpipe->pipe.up_dev;
 	struct dwc2_softc *sc = dev->ud_bus->ub_hcpriv;
 	usbd_status err;
+	const bool polling = sc->sc_bus.ub_usepolling;
 
-	mutex_enter(&sc->sc_lock);
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
 	xfer->ux_status = USBD_IN_PROGRESS;
 	err = dwc2_device_start(xfer);
-	mutex_exit(&sc->sc_lock);
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
 
 	if (err)
 		return err;

Index: src/sys/kern/subr_userconf.c
diff -u src/sys/kern/subr_userconf.c:1.26 src/sys/kern/subr_userconf.c:1.26.22.1
--- src/sys/kern/subr_userconf.c:1.26	Mon Dec 23 15:34:16 2013
+++ src/sys/kern/subr_userconf.c	Thu Sep 27 14:52:26 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_userconf.c,v 1.26 2013/12/23 15:34:16 skrll Exp $	*/
+/*	$NetBSD: subr_userconf.c,v 1.26.22.1 2018/09/27 14:52:26 martin Exp $	*/
 
 /*
  * Copyright (c) 1996 Mats O Jansson <m...@stacken.kth.se>
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_userconf.c,v 1.26 2013/12/23 15:34:16 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_userconf.c,v 1.26.22.1 2018/09/27 14:52:26 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -103,7 +103,9 @@ userconf_more(void)
 	if (userconf_cnt != -1) {
 		if (userconf_cnt == userconf_lines) {
 			printf("-- more --");
+			cnpollc(1);
 			c = cngetc();
+			cnpollc(0);
 			userconf_cnt = 0;
 			printf("\r            \r");
 		}
@@ -391,7 +393,9 @@ userconf_change(int devno)
 
 		while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
 			printf("change (y/n) ?");
+			cnpollc(1);
 			c = cngetc();
+			cnpollc(0);
 			printf("\n");
 		}
 

Reply via email to