Module Name: src Committed By: mrg Date: Tue Sep 18 05:24:10 UTC 2018
Modified Files: src/sys/dev/pci: xhci_pci.c src/sys/dev/usb: usb.c Log Message: 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 To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/dev/pci/xhci_pci.c cvs rdiff -u -r1.172 -r1.173 src/sys/dev/usb/usb.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/xhci_pci.c diff -u src/sys/dev/pci/xhci_pci.c:1.13 src/sys/dev/pci/xhci_pci.c:1.14 --- src/sys/dev/pci/xhci_pci.c:1.13 Fri Jun 29 17:48:24 2018 +++ src/sys/dev/pci/xhci_pci.c Tue Sep 18 05:24:10 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: xhci_pci.c,v 1.13 2018/06/29 17:48:24 msaitoh Exp $ */ +/* $NetBSD: xhci_pci.c,v 1.14 2018/09/18 05:24:10 mrg 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.13 2018/06/29 17:48:24 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v 1.14 2018/09/18 05:24:10 mrg Exp $"); #ifdef _KERNEL_OPT #include "opt_xhci_pci.h" @@ -143,6 +143,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; } @@ -160,6 +161,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/usb.c diff -u src/sys/dev/usb/usb.c:1.172 src/sys/dev/usb/usb.c:1.173 --- src/sys/dev/usb/usb.c:1.172 Sun Sep 16 20:21:56 2018 +++ src/sys/dev/usb/usb.c Tue Sep 18 05:24:10 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.172 2018/09/16 20:21:56 mrg Exp $ */ +/* $NetBSD: usb.c,v 1.173 2018/09/18 05:24:10 mrg 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.172 2018/09/16 20:21:56 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.173 2018/09/18 05:24:10 mrg 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) { @@ -307,6 +312,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; } @@ -342,8 +352,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); @@ -383,9 +391,8 @@ usb_doattach(device_t 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; } @@ -1179,6 +1186,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 { @@ -1231,7 +1242,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) {