Module Name: src Committed By: mrg Date: Sun Mar 24 03:29:03 UTC 2024
Modified Files: src/sys/dev/pci: ehci_pci.c Log Message: ehci(4): properly handle failed attach thinkpad a475 fails to attach an ehci instance: ehci0: pre-2.0 USB rev, device ignored which ends up stopping suspend/resume working as the device has no pmf handlers installed. put most of the teardown code into a new common function that is called from failed attach and detach. if attach fails, register NULL pmf handlers. don't check the return value of pmf_device_register*(). re-order several parts of detach to match the reverse attach order. tested on rockpro64, thinkpad a475, and xps 1645, the a475 can now suspend/resume almost fully successfully. To generate a diff of this commit: cvs rdiff -u -r1.76 -r1.77 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.76 src/sys/dev/pci/ehci_pci.c:1.77 --- src/sys/dev/pci/ehci_pci.c:1.76 Tue Jan 24 08:40:46 2023 +++ src/sys/dev/pci/ehci_pci.c Sun Mar 24 03:29:02 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci_pci.c,v 1.76 2023/01/24 08:40:46 mlelstv Exp $ */ +/* $NetBSD: ehci_pci.c,v 1.77 2024/03/24 03:29:02 mrg 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.76 2023/01/24 08:40:46 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci_pci.c,v 1.77 2024/03/24 03:29:02 mrg Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -85,10 +85,12 @@ struct ehci_pci_softc { void *sc_ih; /* interrupt vectoring */ enum { EHCI_INIT_NONE, + EHCI_INIT_OWNER, EHCI_INIT_INITED } sc_init_state; }; +static void ehci_pci_release_resources(struct ehci_pci_softc *); static int ehci_sb700_match(const struct pci_attach_args *); static int ehci_apply_amd_quirks(struct ehci_pci_softc *); static enum ehci_pci_quirk_flags ehci_pci_lookup_quirkdata(pci_vendor_id_t, @@ -200,9 +202,6 @@ ehci_pci_attach(device_t parent, device_ sc->sc_ih = pci_intr_establish_xname(pc, sc->sc_pihp[0], IPL_USB, ehci_intr, sc, device_xname(self)); if (sc->sc_ih == NULL) { - pci_intr_release(sc->sc_pc, sc->sc_pihp, 1); - sc->sc_pihp = NULL; - aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); @@ -258,6 +257,7 @@ ehci_pci_attach(device_t parent, device_ sc->sc.sc_ncomp = ncomp; ehci_get_ownership(&sc->sc, pc, tag); + sc->sc_init_state = EHCI_INIT_OWNER; int err = ehci_init(&sc->sc); if (err) { @@ -266,9 +266,8 @@ ehci_pci_attach(device_t parent, device_ } sc->sc_init_state = EHCI_INIT_INITED; - if (!pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume, - ehci_shutdown)) - aprint_error_dev(self, "couldn't establish power handler\n"); + pmf_device_register1(self, ehci_pci_suspend, ehci_pci_resume, + ehci_shutdown); /* Attach usb device. */ sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint, @@ -276,15 +275,31 @@ ehci_pci_attach(device_t parent, device_ return; fail: + ehci_pci_release_resources(sc); + pmf_device_register(self, NULL, NULL); +} + +static void +ehci_pci_release_resources(struct ehci_pci_softc *sc) +{ + if (sc->sc_init_state >= EHCI_INIT_OWNER) + ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); + if (sc->sc_ih) { pci_intr_disestablish(sc->sc_pc, sc->sc_ih); sc->sc_ih = NULL; } + if (sc->sc_pihp != NULL) { + pci_intr_release(sc->sc_pc, sc->sc_pihp, 1); + sc->sc_pihp = NULL; + } + if (sc->sc.sc_size) { - ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); sc->sc.sc_size = 0; } + + sc->sc_init_state = EHCI_INIT_NONE; } static int @@ -302,26 +317,14 @@ ehci_pci_detach(device_t self, int flags pmf_device_deregister(self); ehci_shutdown(self, flags); - /* disable interrupts */ - EOWRITE4(&sc->sc, EHCI_USBINTR, 0); - /* XXX grotty hack to flush the write */ - (void)EOREAD4(&sc->sc, EHCI_USBINTR); - - if (sc->sc_ih != NULL) { - pci_intr_disestablish(sc->sc_pc, sc->sc_ih); - sc->sc_ih = NULL; - } - - if (sc->sc_pihp != NULL) { - pci_intr_release(sc->sc_pc, sc->sc_pihp, 1); - sc->sc_pihp = NULL; + if (sc->sc_init_state >= EHCI_INIT_INITED) { + /* disable interrupts */ + EOWRITE4(&sc->sc, EHCI_USBINTR, 0); + /* XXX grotty hack to flush the write */ + (void)EOREAD4(&sc->sc, EHCI_USBINTR); } - if (sc->sc.sc_size) { - ehci_release_ownership(&sc->sc, sc->sc_pc, sc->sc_tag); - bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); - sc->sc.sc_size = 0; - } + ehci_pci_release_resources(sc); #if 1 /* XXX created in ehci.c */