NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-amd64/59180: System reboots instead of shutting down



> Date: Mon, 17 Mar 2025 18:13:31 -0400
> From: swagg boi <swaggboi@gangstalking.agency>
> 
> Hello, sorry for the delay but I have my little 'build environment' 
> setup with the handy build.sh so I can build kernels nice and easy now.
> 
> I gave the patch a try and still get the reboot but when I set 
> ddb.onpanic=1 the output looks different: [...]

Thanks, can you revert the patch I gave you before and try this one
instead?
diff -r 63a5958e843d -r e419e0cd0295 sys/arch/arm/xscale/pxa2x0_ohci.c
--- a/sys/arch/arm/xscale/pxa2x0_ohci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/arch/arm/xscale/pxa2x0_ohci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -123,11 +123,7 @@ pxaohci_attach(device_t parent, device_t
 	}
 
 #if 0
-	sc->sc.sc_powerhook = powerhook_establish(device_xname(sc->sc.sc_bus.bdev),
-	    pxaohci_power, sc);
-	if (sc->sc.sc_powerhook == NULL) {
-		aprint_error_dev(sc->sc.sc_dev->sc_bus.bdev, "cannot establish powerhook\n");
-	}
+	pmf_device_register1(self, ohci_suspend, ohci_resume, ohci_shutdown);
 #endif
 
 	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint,
@@ -151,27 +147,57 @@ pxaohci_detach(device_t self, int flags)
 	struct pxaohci_softc *sc = device_private(self);
 	int error;
 
-	error = ohci_detach(&sc->sc, flags);
+	/*
+	 * Detach the USB child first.  Disconnects all USB devices and
+	 * prevents connecting new ones.
+	 */
+	error = config_detach_children(self, flags);
 	if (error)
 		return error;
 
+	/*
+	 * Shut down the controller and block interrupts at the device
+	 * level.  Once we have shut down the controller, the shutdown
+	 * handler no longer needed -- deregister it from PMF.
+	 * (Harmless to call ohci_shutdown more than once, so no
+	 * synchronization needed.)
+	 */
+	ohci_shutdown(self, 0);
 #if 0
-	if (sc->sc.sc_powerhook) {
-		powerhook_disestablish(sc->sc.sc_powerhook);
-		sc->sc.sc_powerhook = NULL;
-	}
+	pmf_device_deregister(self);
 #endif
 
+	/*
+	 * Interrupts are blocked at the device level by ohci_shutdown.
+	 * Disestablish the interrupt handler.  This waits for it to
+	 * complete on all CPUs.
+	 */
 	if (sc->sc_ih) {
 		pxa2x0_intr_disestablish(sc->sc_ih);
 		sc->sc_ih = NULL;
 	}
 
+	/*
+	 * Free the bus-independent ohci(4) state now that the
+	 * interrupt handler has ceased to run on all CPUs.
+	 */
+	ohci_detach(&sc->sc);
+
+	/*
+	 * Issue a Full Host Reset to disable the host controller
+	 * interface.
+	 *
+	 * XXX Is this necessary or is it redundant with ohci_shutdown?
+	 * Should it be done in ohci_shutdown as well?
+	 */
 	pxaohci_disable(sc);
 
 	/* stop clock */
 	pxa2x0_clkman_config(CKEN_USBHC, 0);
 
+	/*
+	 * Unmap the registers now that we're all done with them.
+	 */
 	if (sc->sc.sc_size) {
 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
 		sc->sc.sc_size = 0;
diff -r 63a5958e843d -r e419e0cd0295 sys/arch/mips/ralink/ralink_ehci.c
--- a/sys/arch/mips/ralink/ralink_ehci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/arch/mips/ralink/ralink_ehci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -57,15 +57,11 @@ static void ralink_ehci_attach(device_t,
 static int  ralink_ehci_detach(device_t, int);
 
 CFATTACH_DECL2_NEW(ralink_ehci, sizeof(struct ralink_ehci_softc),
-	ralink_ehci_match, ralink_ehci_attach, ralink_ehci_detach,
-	ehci_activate, NULL, ehci_childdet);
+    ralink_ehci_match, ralink_ehci_attach, ralink_ehci_detach,
+    ehci_activate, NULL, ehci_childdet);
 
 static TAILQ_HEAD(, ralink_usb_hc) ralink_usb_alldevs =
-	TAILQ_HEAD_INITIALIZER(ralink_usb_alldevs);
-
-#if 0
-struct usb_hc_alldevs ralink_usb_alldevs = TAILQ_HEAD_INITIALIZER(ralink_usb_alldevs);
-#endif
+    TAILQ_HEAD_INITIALIZER(ralink_usb_alldevs);
 
 /*
  * ralink_ehci_match
@@ -144,6 +140,7 @@ ralink_ehci_attach(device_t parent, devi
 	 * have lower function numbers so they should be enumerated already.
 	 */
 	int ncomp = 0;
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ralink_usb_alldevs */
 	TAILQ_FOREACH(ruh, &ralink_usb_alldevs, next) {
 		aprint_normal_dev(self, "companion %s\n",
 			device_xname(ruh->usb));
@@ -207,6 +204,9 @@ ralink_ehci_detach(device_t self, int fl
 void
 ralink_usb_hc_add(struct ralink_usb_hc *ruh, device_t usbp)
 {
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ralink_usb_alldevs */
+
 	TAILQ_INSERT_TAIL(&ralink_usb_alldevs, ruh, next);
 	ruh->usb = usbp;
 }
@@ -214,5 +214,9 @@ ralink_usb_hc_add(struct ralink_usb_hc *
 void
 ralink_usb_hc_rem(struct ralink_usb_hc *ruh)
 {
-	TAILQ_REMOVE(&ralink_usb_alldevs, ruh, next);
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ralink_usb_alldevs */
+
+	if (ruh->usb)
+		TAILQ_REMOVE(&ralink_usb_alldevs, ruh, next);
 }
diff -r 63a5958e843d -r e419e0cd0295 sys/arch/mips/ralink/ralink_ohci.c
--- a/sys/arch/mips/ralink/ralink_ohci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/arch/mips/ralink/ralink_ohci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -162,28 +162,58 @@ static int
 ralink_ohci_detach(device_t self, int flags)
 {
 	struct ralink_ohci_softc *sc = device_private(self);
-	int rv;
+	int error;
+
+	/*
+	 * Detach the USB child first.  Disconnects all USB devices and
+	 * prevents connecting new ones.
+	 */
+	error = config_detach_children(self, flags);
+	if (error)
+		return error;
 
+	/*
+	 * Stop listing this as a possible companion controller for
+	 * ehci(4).
+	 */
+#if NEHCI > 0
+	ralink_usb_hc_rem(&sc->sc_hc);
+#endif
+
+	/*
+	 * Shut down the controller and block interrupts at the device
+	 * level.  Once we have shut down the controller, the shutdown
+	 * handler no longer needed -- deregister it from PMF.
+	 * (Harmless to call ohci_shutdown more than once, so no
+	 * synchronization needed.)
+	 */
+	ohci_shutdown(self, 0);
 	pmf_device_deregister(self);
 
-	rv = ohci_detach(&sc->sc_ohci, flags);
-	if (rv != 0)
-		return rv;
-
+	/*
+	 * Interrupts are blocked at the device level by ohci_shutdown.
+	 * Disestablish the interrupt handler.  This waits for it to
+	 * complete on all CPUs.
+	 */
 	if (sc->sc_ih != NULL) {
 		ra_intr_disestablish(sc->sc_ih);
 		sc->sc_ih = NULL;
 	}
 
-	if (sc->sc_ohci.sc_size == 0) {
+	/*
+	 * Free the bus-independent ohci(4) state now that the
+	 * interrupt handler has ceased to run on all CPUs.
+	 */
+	ohci_detach(&sc->sc_ohci);
+
+	/*
+	 * Unmap the registers now that we're all done with them.
+	 */
+	if (sc->sc_ohci.sc_size) {
 		bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh,
-			sc->sc_ohci.sc_size);
+		    sc->sc_ohci.sc_size);
 		sc->sc_ohci.sc_size = 0;
 	}
 
-#if NEHCI > 0
-	ralink_usb_hc_rem(&sc->sc_hc);
-#endif
-
 	return 0;
 }
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/cardbus/ehci_cardbus.c
--- a/sys/dev/cardbus/ehci_cardbus.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/cardbus/ehci_cardbus.c	Sun Mar 30 20:18:14 2025 +0000
@@ -82,7 +82,7 @@ CFATTACH_DECL_NEW(ehci_cardbus, sizeof(s
     ehci_activate);
 
 static TAILQ_HEAD(, usb_cardbus) ehci_cardbus_alldevs =
-	TAILQ_HEAD_INITIALIZER(ehci_cardbus_alldevs);
+    TAILQ_HEAD_INITIALIZER(ehci_cardbus_alldevs);
 
 int
 ehci_cardbus_match(device_t parent, cfdata_t match, void *aux)
@@ -175,6 +175,7 @@ ehci_cardbus_attach(device_t parent, dev
 	 * have lower function numbers so they should be enumerated already.
 	 */
 	ncomp = 0;
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_cardbus_alldevs */
 	TAILQ_FOREACH(up, &ehci_cardbus_alldevs, next) {
 		if (up->bus == ca->ca_bus) {
 			DPRINTF(("ehci_cardbus_attach: companion %s\n",
@@ -232,6 +233,9 @@ void
 usb_cardbus_add(struct usb_cardbus *up, struct cardbus_attach_args *ca,
     device_t bu)
 {
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_cardbus_alldevs */
+
 	TAILQ_INSERT_TAIL(&ehci_cardbus_alldevs, up, next);
 	up->bus = ca->ca_bus;
 	up->function = ca->ca_function;
@@ -241,5 +245,9 @@ usb_cardbus_add(struct usb_cardbus *up, 
 void
 usb_cardbus_rem(struct usb_cardbus *up)
 {
-	TAILQ_REMOVE(&ehci_cardbus_alldevs, up, next);
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_cardbus_alldevs */
+
+	if (up->usb)
+		TAILQ_REMOVE(&ehci_cardbus_alldevs, up, next);
 }
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/cardbus/ohci_cardbus.c
--- a/sys/dev/cardbus/ohci_cardbus.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/cardbus/ohci_cardbus.c	Sun Mar 30 20:18:14 2025 +0000
@@ -175,22 +175,58 @@ ohci_cardbus_detach(device_t self, int f
 {
 	struct ohci_cardbus_softc *sc = device_private(self);
 	struct cardbus_devfunc *ct = sc->sc_ct;
-	int rv;
+	int error;
+
+	/*
+	 * Detach the USB child first.  Disconnects all USB devices and
+	 * prevents connecting new ones.
+	 */
+	error = config_detach_children(self, flags);
+	if (error)
+		return error;
 
-	rv = ohci_detach(&sc->sc, flags);
-	if (rv)
-		return rv;
+	/*
+	 * Stop listing this as a possible companion controller for
+	 * ehci(4).
+	 */
+#if NEHCI_CARDBUS > 0
+	usb_cardbus_rem(&sc->sc_cardbus);
+#endif
+
+	/*
+	 * Shut down the controller and block interrupts at the device
+	 * level.  Once we have shut down the controller, the shutdown
+	 * handler no longer needed -- deregister it from PMF.
+	 * (Harmless to call ohci_shutdown more than once, so no
+	 * synchronization needed.)
+	 */
+	ohci_shutdown(self, 0);
+	pmf_device_deregister(self);
+
+	/*
+	 * Interrupts are blocked at the device level by ohci_shutdown.
+	 * Disestablish the interrupt handler.  This waits for it to
+	 * complete on all CPUs.
+	 */
 	if (sc->sc_ih != NULL) {
 		Cardbus_intr_disestablish(ct, sc->sc_ih);
 		sc->sc_ih = NULL;
 	}
+
+	/*
+	 * Free the bus-independent ohci(4) state now that the
+	 * interrupt handler has ceased to run on all CPUs.
+	 */
+	ohci_detach(&sc->sc);
+
+	/*
+	 * Unmap the registers now that we're all done with them.
+	 */
 	if (sc->sc.sc_size) {
 		Cardbus_mapreg_unmap(ct, PCI_CBMEM, sc->sc.iot,
 		    sc->sc.ioh, sc->sc.sc_size);
 		sc->sc.sc_size = 0;
 	}
-#if NEHCI_CARDBUS > 0
-	usb_cardbus_rem(&sc->sc_cardbus);
-#endif
+
 	return 0;
 }
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/pci/ehci_pci.c
--- a/sys/dev/pci/ehci_pci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/pci/ehci_pci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -243,6 +243,7 @@ ehci_pci_attach(device_t parent, device_
 	const u_int maxncomp = EHCI_HCS_N_CC(EREAD4(&sc->sc, EHCI_HCSPARAMS));
 	KASSERT(maxncomp <= EHCI_COMPANION_MAX);
 	ncomp = 0;
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_pci_alldevs */
 	TAILQ_FOREACH(up, &ehci_pci_alldevs, next) {
 		if (up->bus == pa->pa_bus && up->device == pa->pa_device &&
 		    !up->claimed) {
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/pci/ohci_pci.c
--- a/sys/dev/pci/ohci_pci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/pci/ohci_pci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -187,33 +187,58 @@ static int
 ohci_pci_detach(device_t self, int flags)
 {
 	struct ohci_pci_softc *sc = device_private(self);
-	int rv;
+	int error;
+
+	/*
+	 * Detach the USB child first.  Disconnects all USB devices and
+	 * prevents connecting new ones.
+	 */
+	error = config_detach_children(self, flags);
+	if (error)
+		return error;
 
-	rv = ohci_detach(&sc->sc, flags);
-	if (rv)
-		return rv;
+	/*
+	 * Stop listing this as a possible companion controller for
+	 * ehci(4).
+	 */
+#if NEHCI > 0
+	usb_pci_rem(&sc->sc_pci);
+#endif
 
+	/*
+	 * Shut down the controller and block interrupts at the device
+	 * level.  Once we have shut down the controller, the shutdown
+	 * handler no longer needed -- deregister it from PMF.
+	 * (Harmless to call ohci_shutdown more than once, so no
+	 * synchronization needed.)
+	 */
+	ohci_shutdown(self, 0);
 	pmf_device_deregister(self);
 
-	ohci_shutdown(self, flags);
-
-	if (sc->sc.sc_size) {
-		/* Disable interrupts, so we don't get any spurious ones. */
-		bus_space_write_4(sc->sc.iot, sc->sc.ioh,
-				  OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
-	}
-
+	/*
+	 * Interrupts are blocked at the device level by ohci_shutdown.
+	 * Disestablish the interrupt handler.  This waits for it to
+	 * complete on all CPUs.
+	 */
 	if (sc->sc_ih != NULL) {
 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
 		sc->sc_ih = NULL;
 	}
+
+	/*
+	 * Free the bus-independent ohci(4) state now that the
+	 * interrupt handler has ceased to run on all CPUs.
+	 */
+	ohci_detach(&sc->sc);
+
+	/*
+	 * Unmap the registers now that we're all done with them.
+	 */
 	if (sc->sc.sc_size) {
 		bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
 		sc->sc.sc_size = 0;
 	}
-#if NEHCI > 0
-	usb_pci_rem(&sc->sc_pci);
-#endif
+
 	return 0;
 }
 
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/pci/usb_pci.c
--- a/sys/dev/pci/usb_pci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/pci/usb_pci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -33,28 +33,31 @@
 __KERNEL_RCSID(0, "$NetBSD: usb_pci.c,v 1.7 2008/04/28 20:23:55 martin Exp $");
 
 #include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/queue.h>
-#include <sys/proc.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/usb_pci.h>
 
 #include <dev/usb/usb.h>
+#include <dev/usb/usb_mem.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdivar.h>
-#include <dev/usb/usb_mem.h>
 
 #include <dev/usb/ehcireg.h>
 #include <dev/usb/ehcivar.h>
 
 struct usb_pci_alldevs ehci_pci_alldevs =
-	TAILQ_HEAD_INITIALIZER(ehci_pci_alldevs);
+    TAILQ_HEAD_INITIALIZER(ehci_pci_alldevs);
 
 void
 usb_pci_add(struct usb_pci *up, struct pci_attach_args *pa, device_t bu)
 {
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_pci_alldevs */
+
 	TAILQ_INSERT_TAIL(&ehci_pci_alldevs, up, next);
 	up->bus = pa->pa_bus;
 	up->device = pa->pa_device;
@@ -65,5 +68,9 @@ usb_pci_add(struct usb_pci *up, struct p
 void
 usb_pci_rem(struct usb_pci *up)
 {
-	TAILQ_REMOVE(&ehci_pci_alldevs, up, next);
+
+	KASSERT(KERNEL_LOCKED_P()); /* XXXSMP ehci_pci_alldevs */
+
+	if (up->usb)
+		TAILQ_REMOVE(&ehci_pci_alldevs, up, next);
 }
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/usb/ohci.c
--- a/sys/dev/usb/ohci.c	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/usb/ohci.c	Sun Mar 30 20:18:14 2025 +0000
@@ -368,16 +368,14 @@ ohci_childdet(device_t self, device_t ch
 	sc->sc_child = NULL;
 }
 
-int
-ohci_detach(struct ohci_softc *sc, int flags)
+void
+ohci_detach(struct ohci_softc *sc)
 {
-	int rv = 0;
-
-	if (sc->sc_child != NULL)
-		rv = config_detach(sc->sc_child, flags);
-
-	if (rv != 0)
-		return rv;
+
+	KASSERT(sc->sc_child == NULL);
+
+	if (!sc->sc_attached)
+		return;
 
 	softint_disestablish(sc->sc_rhsc_si);
 
@@ -391,8 +389,6 @@ ohci_detach(struct ohci_softc *sc, int f
 		usb_freemem(&sc->sc_hccadma);
 	pool_cache_destroy(sc->sc_xferpool);
 	cv_destroy(&sc->sc_abort_cv);
-
-	return rv;
 }
 
 ohci_soft_ed_t *
@@ -1092,6 +1088,7 @@ ohci_init(ohci_softc_t *sc)
 	DPRINTF("enabling %#jx", sc->sc_eintrs | OHCI_MIE, 0, 0, 0);
 	OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
 
+	sc->sc_attached = true;
 	return 0;
 
  bad5:
@@ -1166,6 +1163,9 @@ ohci_shutdown(device_t self, int flags)
 
 	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 
+	if (!sc->sc_attached)
+		return true;
+
 	DPRINTF("stopping the HC", 0, 0, 0, 0);
 	OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
 	OWRITE4(sc, OHCI_CONTROL, OHCI_SET_HCFS(OHCI_HCFS_RESET));
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/usb/ohcivar.h
--- a/sys/dev/usb/ohcivar.h	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/usb/ohcivar.h	Sun Mar 30 20:18:14 2025 +0000
@@ -90,6 +90,7 @@ typedef struct ohci_softc {
 	bus_space_tag_t iot;
 	bus_space_handle_t ioh;
 	bus_size_t sc_size;
+	bool sc_attached;
 
 	kmutex_t sc_lock;
 	kmutex_t sc_intr_lock;
@@ -172,7 +173,7 @@ struct ohci_xfer {
 
 int		ohci_init(ohci_softc_t *);
 int		ohci_intr(void *);
-int		ohci_detach(ohci_softc_t *, int);
+void		ohci_detach(ohci_softc_t *);
 bool		ohci_shutdown(device_t, int);
 void		ohci_childdet(device_t, device_t);
 int		ohci_activate(device_t, enum devact);
diff -r 63a5958e843d -r e419e0cd0295 sys/dev/usb/usbdivar.h
--- a/sys/dev/usb/usbdivar.h	Sun Mar 30 16:22:37 2025 +0000
+++ b/sys/dev/usb/usbdivar.h	Sun Mar 30 20:18:14 2025 +0000
@@ -74,9 +74,11 @@
  *
  */
 
+#include <sys/bus.h>
 #include <sys/callout.h>
 #include <sys/mutex.h>
-#include <sys/bus.h>
+
+#include <dev/usb/usbdi.h>
 
 /* From usb_mem.h */
 struct usb_dma_block;


Home | Main Index | Thread Index | Old Index