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;