Module Name:    src
Committed By:   maxv
Date:           Thu Jun 13 17:33:34 UTC 2019

Modified Files:
        src/sys/dev/pci: ehci_pci.c

Log Message:
Fix the error handling in ehci_pci_attach(): if we got a USB<2 device we
won't call ehci_init(), so don't call ehci_detach() in ehci_pci_detach().

Fixes a panic seen on a recent Lenovo machine, which has an USB 1.1
controller; ehci_detach() was getting called while 'sc' had not been
completely initialized.


To generate a diff of this commit:
cvs rdiff -u -r1.69 -r1.70 src/sys/dev/pci/ehci_pci.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/ehci_pci.c
diff -u src/sys/dev/pci/ehci_pci.c:1.69 src/sys/dev/pci/ehci_pci.c:1.70
--- src/sys/dev/pci/ehci_pci.c:1.69	Thu Jun 13 17:20:25 2019
+++ src/sys/dev/pci/ehci_pci.c	Thu Jun 13 17:33:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci_pci.c,v 1.69 2019/06/13 17:20:25 maxv Exp $	*/
+/*	$NetBSD: ehci_pci.c,v 1.70 2019/06/13 17:33:34 maxv Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.69 2019/06/13 17:20:25 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.70 2019/06/13 17:33:34 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -83,6 +83,10 @@ struct ehci_pci_softc {
 	pcitag_t		sc_tag;
 	pci_intr_handle_t	*sc_pihp;
 	void 			*sc_ih;		/* interrupt vectoring */
+	enum {
+		EHCI_INIT_NONE,
+		EHCI_INIT_INITED
+	} sc_init_state;
 };
 
 static int ehci_sb700_match(const struct pci_attach_args *);
@@ -120,6 +124,7 @@ ehci_pci_attach(device_t parent, device_
 	int ncomp, quirk;
 	pcireg_t csr;
 
+	sc->sc_init_state = EHCI_INIT_NONE;
 	sc->sc.sc_dev = self;
 	sc->sc.sc_bus.ub_hcpriv = sc;
 
@@ -243,6 +248,7 @@ ehci_pci_attach(device_t parent, device_
 		aprint_error_dev(self, "init failed, error=%d\n", err);
 		goto fail;
 	}
+	sc->sc_init_state = EHCI_INIT_INITED;
 
 	if (!pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume,
 	    ehci_shutdown))
@@ -270,9 +276,11 @@ ehci_pci_detach(device_t self, int flags
 	struct ehci_pci_softc *sc = device_private(self);
 	int rv;
 
-	rv = ehci_detach(&sc->sc, flags);
-	if (rv)
-		return rv;
+	if (sc->sc_init_state >= EHCI_INIT_INITED) {
+		rv = ehci_detach(&sc->sc, flags);
+		if (rv)
+			return rv;
+	}
 
 	pmf_device_deregister(self);
 	ehci_shutdown(self, flags);
@@ -300,10 +308,12 @@ ehci_pci_detach(device_t self, int flags
 
 #if 1
 	/* XXX created in ehci.c */
-	mutex_destroy(&sc->sc.sc_lock);
-	mutex_destroy(&sc->sc.sc_intr_lock);
-	softint_disestablish(sc->sc.sc_doorbell_si);
-	softint_disestablish(sc->sc.sc_pcd_si);
+	if (sc->sc_init_state >= EHCI_INIT_INITED) {
+		mutex_destroy(&sc->sc.sc_lock);
+		mutex_destroy(&sc->sc.sc_intr_lock);
+		softint_disestablish(sc->sc.sc_doorbell_si);
+		softint_disestablish(sc->sc.sc_pcd_si);
+	}
 #endif
 
 	return 0;

Reply via email to