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 */