Index: dev/usb/uhci.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v retrieving revision 1.283 diff -p -u -r1.283 uhci.c --- dev/usb/uhci.c 3 Sep 2018 16:29:34 -0000 1.283 +++ dev/usb/uhci.c 16 Sep 2018 02:09:58 -0000 @@ -2257,6 +2257,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; + bool polling = sc->sc_bus.ub_usepolling; int len; int endpt; int isread; @@ -2277,7 +2278,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); @@ -2311,12 +2313,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; } @@ -2541,6 +2544,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; + bool polling = sc->sc_bus.ub_usepolling; int len; int isread; @@ -2568,7 +2572,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) { @@ -2665,12 +2670,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; } @@ -2743,6 +2749,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; + bool polling = sc->sc_bus.ub_usepolling; int isread, endpt; int i; @@ -2768,7 +2775,7 @@ uhci_device_intr_start(struct usbd_xfer #endif /* Take lock to protect nexttoggle */ - if (!sc->sc_bus.ub_usepolling) + if (!polling) mutex_enter(&sc->sc_lock); uhci_reset_std_chain(sc, xfer, xfer->ux_length, isread, &upipe->nexttoggle, &dataend); @@ -2801,7 +2808,7 @@ uhci_device_intr_start(struct usbd_xfer } uhci_add_intr_list(sc, ux); xfer->ux_status = USBD_IN_PROGRESS; - if (!sc->sc_bus.ub_usepolling) + if (!polling) mutex_exit(&sc->sc_lock); #ifdef UHCI_DEBUG Index: dev/usb/uhub.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/uhub.c,v retrieving revision 1.138 diff -p -u -r1.138 uhub.c --- dev/usb/uhub.c 1 Feb 2018 09:50:48 -0000 1.138 +++ dev/usb/uhub.c 16 Sep 2018 02:09:58 -0000 @@ -263,6 +263,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; @@ -284,14 +286,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. */ @@ -301,7 +303,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++) @@ -365,7 +367,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 = 2; err = usbd_open_pipe_intr(iface, ed->bEndpointAddress, USBD_SHORT_XFER_OK|USBD_MPSAFE, &sc->sc_ipipe, sc, @@ -469,6 +471,8 @@ uhub_attach(device_t parent, device_t se kmem_free(hub, sizeof(*hub) + (nports-1) * sizeof(struct usbd_port)); dev->ud_hub = NULL; + bad2: + config_pending_decr(self); return; } @@ -778,6 +782,8 @@ uhub_explore(struct usbd_device *dev) } } mutex_enter(&sc->sc_lock); + if (sc->sc_explorepending == 2) // XXXMRG - gross, should be bool? + config_pending_decr(sc->sc_dev); sc->sc_explorepending = 0; for (int i = 0; i < sc->sc_statuslen; i++) { if (sc->sc_statuspend[i] != 0) { Index: dev/usb/ukbd.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/ukbd.c,v retrieving revision 1.141 diff -p -u -r1.141 ukbd.c --- dev/usb/ukbd.c 9 Jan 2018 17:58:09 -0000 1.141 +++ dev/usb/ukbd.c 16 Sep 2018 02:09:58 -0000 @@ -400,6 +400,8 @@ ukbd_attach(device_t parent, device_t se const char *parseerr; struct wskbddev_attach_args a; + config_pending_incr(self); + sc->sc_hdev.sc_dev = self; sc->sc_hdev.sc_intr = ukbd_intr; sc->sc_hdev.sc_parent = uha->parent; @@ -417,6 +419,7 @@ ukbd_attach(device_t parent, device_t se if (parseerr != NULL) { aprint_normal("\n"); aprint_error_dev(self, "attach failed, %s\n", parseerr); + config_pending_incr(self); return; } @@ -485,6 +488,8 @@ ukbd_attach(device_t parent, device_t se sc->sc_wskbddev = config_found(self, &a, wskbddevprint); + config_pending_decr(self); + return; } @@ -935,6 +940,9 @@ ukbd_ioctl(void *v, u_long cmd, void *da return EPASSTHROUGH; } +#include +#include + /* * This is a hack to work around some broken ports that don't call * cnpollc() before cngetc(). @@ -955,6 +963,9 @@ ukbd_cngetc(void *v, u_int *type, int *d "This port is broken, it does not call cnpollc() before calling cngetc().\n" "This should be fixed, but it will work anyway (for now).\n"); warned = 1; +db_stacktrace(); +kpause("mrghax", true, hz * 10, NULL); + } broken = 1; ukbd_cnpollc(v, 1); Index: dev/usb/usb.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/usb.c,v retrieving revision 1.171 diff -p -u -r1.171 usb.c --- dev/usb/usb.c 2 Aug 2018 06:09:04 -0000 1.171 +++ dev/usb/usb.c 16 Sep 2018 02:09:58 -0000 @@ -319,9 +319,12 @@ usb_doattach(device_t self) int speed; struct usb_event *ue; + config_pending_incr(self); + USBHIST_FUNC(); USBHIST_CALLED(usbdebug); sc->sc_bus->ub_usbctl = self; + sc->sc_bus->ub_exploring = 0; sc->sc_port.up_power = USB_MAX_POWER; switch (sc->sc_bus->ub_revision) { @@ -354,6 +357,7 @@ usb_doattach(device_t self) dev = sc->sc_port.up_dev; if (dev->ud_hub == NULL) { sc->sc_dying = 1; + config_pending_decr(self); aprint_error("%s: root device is not a hub\n", device_xname(self)); return; @@ -370,13 +374,12 @@ usb_doattach(device_t self) dev->ud_hub->uh_explore(sc->sc_bus->ub_roothub); #endif } else { + config_pending_decr(self); aprint_error("%s: root hub problem, error=%s\n", device_xname(self), usbd_errstr(err)); sc->sc_dying = 1; } - config_pending_incr(self); - if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); @@ -551,6 +554,9 @@ usb_event_thread(void *arg) mutex_enter(sc->sc_bus->ub_lock); while (!sc->sc_dying) { + while (sc->sc_bus->ub_usepolling) + kpause("usbpoll", true, hz, sc->sc_bus->ub_lock); + if (usb_noexplore < 2) usb_discover(sc); @@ -997,25 +1003,30 @@ 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; + bus->ub_exploring = 1; 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); + bus->ub_exploring = 0; } } Index: dev/usb/usbdi.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/usbdi.c,v retrieving revision 1.177 diff -p -u -r1.177 usbdi.c --- dev/usb/usbdi.c 9 Aug 2018 06:26:47 -0000 1.177 +++ dev/usb/usbdi.c 16 Sep 2018 02:09:58 -0000 @@ -964,19 +964,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) { @@ -1175,7 +1175,8 @@ usbd_dopoll(struct usbd_interface *iface } /* - * XXX use this more??? ub_usepolling it touched manually all over + * This is for keybaord 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) @@ -1185,9 +1186,18 @@ usbd_set_polling(struct usbd_device *dev else dev->ud_bus->ub_usepolling--; - /* Kick the host controller when switching modes */ +printf("%s:%d: (%s) polling now %d\n", __func__, __LINE__, device_xname(dev->ud_bus->ub_usbctl), dev->ud_bus->ub_usepolling); mutex_enter(dev->ud_bus->ub_lock); + + if (dev->ud_bus->ub_exploring && dev->ud_bus->ub_usepolling) + while (dev->ud_bus->ub_exploring) +{printf("waiting for hub %s\n", device_xname(dev->ud_bus->ub_usbctl)); + kpause("usetpoll", true, hz, dev->ud_bus->ub_lock); +} + + /* Kick the host controller when switching modes */ dev->ud_bus->ub_methods->ubm_softint(dev->ud_bus); + mutex_exit(dev->ud_bus->ub_lock); } Index: dev/usb/usbdivar.h =================================================================== RCS file: /cvsroot/src/sys/dev/usb/usbdivar.h,v retrieving revision 1.117 diff -p -u -r1.117 usbdivar.h --- dev/usb/usbdivar.h 9 Aug 2018 06:26:47 -0000 1.117 +++ dev/usb/usbdivar.h 16 Sep 2018 02:09:58 -0000 @@ -171,6 +171,7 @@ struct usbd_bus { struct usbd_device *ub_devices[USB_TOTAL_DEVICES]; kcondvar_t ub_needsexplore_cv; char ub_needsexplore;/* a hub a signalled a change */ + char ub_exploring; char ub_usepolling; device_t ub_usbctl; struct usb_device_stats ub_stats; Index: dev/wscons/wsdisplay.c =================================================================== RCS file: /cvsroot/src/sys/dev/wscons/wsdisplay.c,v retrieving revision 1.145 diff -p -u -r1.145 wsdisplay.c --- dev/wscons/wsdisplay.c 18 Dec 2017 22:44:30 -0000 1.145 +++ dev/wscons/wsdisplay.c 16 Sep 2018 02:09:58 -0000 @@ -618,6 +618,8 @@ wsdisplay_emul_attach(device_t parent, d struct wsdisplay_softc *sc = device_private(self); struct wsemuldisplaydev_attach_args *ap = aux; + config_pending_incr(self); + sc->sc_dev = self; /* Don't allow more than one console to attach */ @@ -637,6 +639,8 @@ wsdisplay_emul_attach(device_t parent, d cn_tab->cn_dev = makedev(maj, WSDISPLAYMINOR(device_unit(self), 0)); } + + config_pending_decr(self); } /* Print function (for parent devices). */ @@ -693,10 +697,13 @@ wsdisplay_noemul_attach(device_t parent, struct wsdisplaydev_attach_args *ap = aux; sc->sc_dev = self; + config_pending_decr(self); wsdisplay_common_attach(sc, 0, device_cfdata(self)->cf_loc[WSDISPLAYDEVCF_KBDMUX], NULL, ap->accessops, ap->accesscookie); + + config_pending_decr(self); } static void Index: dev/wscons/wskbd.c =================================================================== RCS file: /cvsroot/src/sys/dev/wscons/wskbd.c,v retrieving revision 1.141 diff -p -u -r1.141 wskbd.c --- dev/wscons/wskbd.c 18 Dec 2017 18:57:21 -0000 1.141 +++ dev/wscons/wskbd.c 16 Sep 2018 02:09:58 -0000 @@ -414,6 +414,8 @@ wskbd_attach(device_t parent, device_t s int mux, error; #endif + config_pending_incr(self); + sc->sc_base.me_dv = self; sc->sc_isconsole = ap->console; sc->sc_hotkey = NULL; @@ -504,6 +506,8 @@ wskbd_attach(device_t parent, device_t s aprint_error_dev(self, "couldn't establish power handler\n"); else if (!pmf_class_input_register(self)) aprint_error_dev(self, "couldn't register as input device\n"); + + config_pending_decr(self); } static bool Index: kern/kern_subr.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_subr.c,v retrieving revision 1.219 diff -p -u -r1.219 kern_subr.c --- kern/kern_subr.c 14 Nov 2017 14:14:29 -0000 1.219 +++ kern/kern_subr.c 16 Sep 2018 02:09:58 -0000 @@ -261,6 +261,8 @@ setroot(device_t bootdv, int bootpartiti if (boothowto & RB_ASKNAME) { device_t defdumpdv; +printf("pausing for 10 seconds ...\n"); +kpause("askroot", true, 10 * hz, NULL); for (;;) { printf("root device"); if (bootdv != NULL) {