Re: O(/E)HCI detach support patch

From: Craig Boston <craig_at_xfoil.gank.org>
Date: Sun, 15 Jun 2003 00:51:17 -0500
Below is a preliminary patch that seems to at least keep the machine from 
panicing when detaching USB cards :)

It's still highly experimental, so use at your own risk.  It works well enough 
for me to plug in / unplug my cardbus card repeatedly (even with devices 
attached to it).  Theoretically this should also make the usb kernel module 
unloadable, however that is untested.

WARNING: There may still be edge conditions or memory leaks lurking about, and 
users of this patch are likely to be eaten by a grue.

Unplugging it while one of the devices is actively being used is probably a 
very bad idea.  I tried not to make the code too divergant from the NetBSD 
path but probably wasn't 100% successful.

If the formatting gets mangled in the mail and anyone wants to try this patch, 
mail me and I'll send it as a file.  Feedback / comments / advice are much 
appreciated.

Index: ehci_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ehci_pci.c,v
retrieving revision 1.2
diff -u -r1.2 ehci_pci.c
--- ehci_pci.c	12 Jun 2003 05:29:15 -0000	1.2
+++ ehci_pci.c	14 Jun 2003 21:48:26 -0000
_at__at_ -263,9 +263,7 _at__at_
 
 	if (err) {
 		device_printf(self, "USB init failed err=%d\n", err);
-#if 0 /* TODO */
 		ehci_pci_detach(self);
-#endif
 		return EIO;
 	}
 	return 0;
_at__at_ -317,6 +315,7 _at__at_
 	/* Device interface */
 	DEVMETHOD(device_probe, ehci_pci_probe),
 	DEVMETHOD(device_attach, ehci_pci_attach),
+	DEVMETHOD(device_detach, ehci_pci_detach),
 	DEVMETHOD(device_shutdown, bus_generic_shutdown),
 
 	/* Bus interface */
Index: ohci_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/ohci_pci.c,v
retrieving revision 1.31
diff -u -r1.31 ohci_pci.c
--- ohci_pci.c	12 Jun 2003 05:29:15 -0000	1.31
+++ ohci_pci.c	15 Jun 2003 04:25:32 -0000
_at__at_ -299,6 +299,7 _at__at_
 	/* Device interface */
 	DEVMETHOD(device_probe, ohci_pci_probe),
 	DEVMETHOD(device_attach, ohci_pci_attach),
+	DEVMETHOD(device_detach, ohci_pci_detach),
 	DEVMETHOD(device_shutdown, bus_generic_shutdown),
 
 	/* Bus interface */
Index: uhci_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/uhci_pci.c,v
retrieving revision 1.47
diff -u -r1.47 uhci_pci.c
--- uhci_pci.c	12 Jun 2003 05:29:15 -0000	1.47
+++ uhci_pci.c	15 Jun 2003 05:18:25 -0000
_at__at_ -392,6 +392,7 _at__at_
 	/* Device interface */
 	DEVMETHOD(device_probe, uhci_pci_probe),
 	DEVMETHOD(device_attach, uhci_pci_attach),
+	DEVMETHOD(device_detach, uhci_pci_detach),
 	DEVMETHOD(device_suspend, uhci_pci_suspend),
 	DEVMETHOD(device_resume, uhci_pci_resume),
 	DEVMETHOD(device_shutdown, bus_generic_shutdown),
Index: uhub.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/uhub.c,v
retrieving revision 1.47
diff -u -r1.47 uhub.c
--- uhub.c	8 Aug 2002 12:05:50 -0000	1.47
+++ uhub.c	15 Jun 2003 04:39:13 -0000
_at__at_ -87,6 +87,7 _at__at_
 
 Static usbd_status uhub_explore(usbd_device_handle hub);
 Static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
+Static int uhub_dummy_detach(device_t);
 
 #if defined(__FreeBSD__)
 Static bus_driver_added_t uhub_driver_added;
_at__at_ -123,8 +124,7 _at__at_
 Static device_method_t uhubroot_methods[] = {
 	DEVMETHOD(device_probe, uhub_match),
 	DEVMETHOD(device_attach, uhub_attach),
-
-	/* detach is not allowed for a root hub */
+	DEVMETHOD(device_detach, uhub_dummy_detach),
 	DEVMETHOD(device_suspend, bus_generic_suspend),
 	DEVMETHOD(device_resume, bus_generic_resume),
 	DEVMETHOD(device_shutdown, bus_generic_shutdown),
_at__at_ -535,6 +535,16 _at__at_
 	return (0);
 }
 #endif
+
+/*
+ * Dummy detach for root hub when devices are being torn down
+ * Don't need to detach child devices since they're already gone
+ */
+Static int
+uhub_dummy_detach(device_t dev)
+{
+	return 0;
+}
 
 /*
  * Called from process context when the hub is gone.
Index: usb.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/usb/usb.c,v
retrieving revision 1.87
diff -u -r1.87 usb.c
--- usb.c	14 Apr 2003 14:04:07 -0000	1.87
+++ usb.c	15 Jun 2003 05:20:58 -0000
_at__at_ -121,6 +121,10 _at__at_
 
 	struct proc	*sc_event_thread;
 
+#if defined(__FreeBSD__)
+	dev_t		dev;
+#endif
+	
 	char		sc_dying;
 };
 
_at__at_ -175,7 +179,8 _at__at_
 USB_DECLARE_DRIVER_INIT(usb,
 			DEVMETHOD(device_suspend, bus_generic_suspend),
 			DEVMETHOD(device_resume, bus_generic_resume),
-			DEVMETHOD(device_shutdown, bus_generic_shutdown)
+			DEVMETHOD(device_shutdown, bus_generic_shutdown),
+			DEVMETHOD(device_detach, usb_detach)
 			);
 
 #if defined(__FreeBSD__)
_at__at_ -295,8 +300,8 _at__at_
 	usb_create_event_thread(sc);
 	/* The per controller devices (used for usb_discover) */
 	/* XXX This is redundant now, but old usbd's will want it */
-	make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR,
-		0660, "usb%d", device_get_unit(self));
+	sc->dev = make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT,
+		GID_OPERATOR, 0660, "usb%d", device_get_unit(self));
 	if (!global_init_done) {
 		/* The device spitting out events */
 		make_dev(&usb_cdevsw, USB_DEV_MINOR, UID_ROOT, GID_OPERATOR,
_at__at_ -850,20 +855,26 _at__at_
 	}
 	return (rv);
 }
+#endif
 
-int
-usb_detach(device_ptr_t self, int flags)
+USB_DETACH(usb)
 {
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 	struct usb_softc *sc = (struct usb_softc *)self;
+#elif defined(__FreeBSD__)
+	struct usb_softc *sc = device_get_softc(self);
+#endif
 	struct usb_event ue;
 
 	DPRINTF(("usb_detach: start\n"));
 
 	sc->sc_dying = 1;
 
+#if !defined(__FreeBSD__)
 	/* Make all devices disconnect. */
 	if (sc->sc_port.device != NULL)
 		usb_disconnect_port(&sc->sc_port, self);
+#endif
 
 	/* Kill off event thread. */
 	if (sc->sc_event_thread != NULL) {
_at__at_ -890,17 +901,12 _at__at_
 	ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
 	usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
 
-	return (0);
-}
-#elif defined(__FreeBSD__)
-int
-usb_detach(device_t self)
-{
-	DPRINTF(("%s: unload, prevented\n", USBDEVNAME(self)));
+#if defined(__FreeBSD__)
+	destroy_dev(sc->dev);
+#endif
 
-	return (EINVAL);
+	return (0);
 }
-#endif
 
 
 #if defined(__FreeBSD__)
Received on Sat Jun 14 2003 - 20:51:19 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:11 UTC