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) {

Reply via email to