Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Re-order operations in usb_detach() so that if a...



details:   https://anonhg.NetBSD.org/src/rev/e1d910248c77
branches:  trunk
changeset: 749001:e1d910248c77
user:      dyoung <dyoung%NetBSD.org@localhost>
date:      Thu Nov 12 20:11:35 2009 +0000

description:
Re-order operations in usb_detach() so that if a usb(4) instance's
children will not detach, the instance is not left in an inconsistent
state.

If uhub(4) port is disconnected, forcefully detach the children on
that port.

Simplify detachment hooks.  (sc_dying must die!)

Pass along and respect detachment flags, esp. DETACH_FORCE,
throughout.

diffstat:

 sys/dev/usb/uhub.c     |  58 ++++++++++++-------------------------------------
 sys/dev/usb/usb.c      |  32 ++++++++++-----------------
 sys/dev/usb/usb_subr.c |  29 ++++++++++++++----------
 sys/dev/usb/usbdivar.h |   4 +-
 4 files changed, 46 insertions(+), 77 deletions(-)

diffs (281 lines):

diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/uhub.c
--- a/sys/dev/usb/uhub.c        Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/uhub.c        Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $        */
+/*     $NetBSD: uhub.c,v 1.108 2009/11/12 20:11:35 dyoung Exp $        */
 /*     $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $       */
 
 /*
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.108 2009/11/12 20:11:35 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -98,13 +98,12 @@
 int uhub_rescan(device_t, const char *, const int *);
 void uhub_childdet(device_t, device_t);
 int uhub_detach(device_t, int);
-int uhub_activate(device_t, enum devact);
 extern struct cfdriver uhub_cd;
 CFATTACH_DECL3_NEW(uhub, sizeof(struct uhub_softc), uhub_match,
-    uhub_attach, uhub_detach, uhub_activate, uhub_rescan, uhub_childdet,
+    uhub_attach, uhub_detach, NULL, uhub_rescan, uhub_childdet,
     DVF_DETACH_SHUTDOWN);
 CFATTACH_DECL2_NEW(uroothub, sizeof(struct uhub_softc), uhub_match,
-    uhub_attach, uhub_detach, uhub_activate, uhub_rescan, uhub_childdet);
+    uhub_attach, uhub_detach, NULL, uhub_rescan, uhub_childdet);
 
 int
 uhub_match(device_t parent, cfdata_t match, void *aux)
@@ -470,7 +469,7 @@
                        /* Disconnected */
                        DPRINTF(("uhub_explore: device addr=%d disappeared "
                                 "on port %d\n", up->device->address, port));
-                       usb_disconnect_port(up, sc->sc_dev);
+                       usb_disconnect_port(up, sc->sc_dev, DETACH_FORCE);
                        usbd_clear_port_feature(dev, port,
                                                UHF_C_PORT_CONNECTION);
                }
@@ -554,35 +553,6 @@
        return (USBD_NORMAL_COMPLETION);
 }
 
-int
-uhub_activate(device_t self, enum devact act)
-{
-       struct uhub_softc *sc = device_private(self);
-       struct usbd_hub *hub = sc->sc_hub->hub;
-       usbd_device_handle dev;
-       int nports, port, i;
-
-       switch (act) {
-       case DVACT_ACTIVATE:
-               return (EOPNOTSUPP);
-
-       case DVACT_DEACTIVATE:
-               if (hub == NULL) /* malfunctioning hub */
-                       break;
-               nports = hub->hubdesc.bNbrPorts;
-               for(port = 0; port < nports; port++) {
-                       dev = hub->ports[port].device;
-                       if (!dev)
-                               continue;
-                       for (i = 0; i < dev->subdevlen; i++)
-                               if (dev->subdevs[i])
-                                       config_deactivate(dev->subdevs[i]);
-               }
-               break;
-       }
-       return (0);
-}
-
 /*
  * Called from process context when the hub is gone.
  * Detach all devices on active ports.
@@ -593,24 +563,26 @@
        struct uhub_softc *sc = device_private(self);
        struct usbd_hub *hub = sc->sc_hub->hub;
        struct usbd_port *rup;
-       int port, nports;
+       int nports, port, rc;
 
        DPRINTF(("uhub_detach: sc=%p flags=%d\n", sc, flags));
 
        if (hub == NULL)                /* Must be partially working */
                return (0);
 
+       nports = hub->hubdesc.bNbrPorts;
+       for(port = 0; port < nports; port++) {
+               rup = &hub->ports[port];
+               if (rup->device == NULL)
+                       continue;
+               if ((rc = usb_disconnect_port(rup, self, flags)) != 0)
+                       return rc;
+       }
+
        pmf_device_deregister(self);
        usbd_abort_pipe(sc->sc_ipipe);
        usbd_close_pipe(sc->sc_ipipe);
 
-       nports = hub->hubdesc.bNbrPorts;
-       for(port = 0; port < nports; port++) {
-               rup = &hub->ports[port];
-               if (rup->device != NULL)
-                       usb_disconnect_port(rup, self);
-       }
-
        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, sc->sc_dev);
 
 #if 0
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usb.c
--- a/sys/dev/usb/usb.c Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usb.c Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb.c,v 1.118 2009/06/16 19:42:44 dyoung Exp $ */
+/*     $NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $ */
 
 /*
  * Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.118 2009/06/16 19:42:44 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $");
 
 #include "opt_compat_netbsd.h"
 
@@ -937,25 +937,14 @@
 usb_activate(device_t self, enum devact act)
 {
        struct usb_softc *sc = device_private(self);
-       usbd_device_handle dev = sc->sc_port.device;
-       int i, rv = 0;
 
        switch (act) {
-       case DVACT_ACTIVATE:
-               return (EOPNOTSUPP);
-
        case DVACT_DEACTIVATE:
                sc->sc_dying = 1;
-               if (dev != NULL && dev->cdesc != NULL && dev->subdevlen > 0) {
-                       for (i = 0; i < dev->subdevlen; i++) {
-                               if (!dev->subdevs[i])
-                                       continue;
-                               rv |= config_deactivate(dev->subdevs[i]);
-                       }
-               }
-               break;
+               return 0;
+       default:
+               return EOPNOTSUPP;
        }
-       return (rv);
 }
 
 void
@@ -978,21 +967,24 @@
 {
        struct usb_softc *sc = device_private(self);
        struct usb_event *ue;
+       int rc;
 
        DPRINTF(("usb_detach: start\n"));
 
+       /* Make all devices disconnect. */
+       if (sc->sc_port.device != NULL &&
+           (rc = usb_disconnect_port(&sc->sc_port, self, flags)) != 0)
+               return rc;
+
        pmf_device_deregister(self);
        /* Kill off event thread. */
+       sc->sc_dying = 1;
        while (sc->sc_event_thread != NULL) {
                wakeup(&sc->sc_bus->needs_explore);
                tsleep(sc, PWAIT, "usbdet", hz * 60);
        }
        DPRINTF(("usb_detach: event thread dead\n"));
 
-       /* Make all devices disconnect. */
-       if (sc->sc_port.device != NULL)
-               usb_disconnect_port(&sc->sc_port, self);
-
 #ifdef USB_USE_SOFTINTR
        if (sc->sc_bus->soft != NULL) {
                softint_disestablish(sc->sc_bus->soft);
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usb_subr.c
--- a/sys/dev/usb/usb_subr.c    Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usb_subr.c    Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb_subr.c,v 1.166 2009/11/12 08:41:49 uebayasi Exp $  */
+/*     $NetBSD: usb_subr.c,v 1.167 2009/11/12 20:11:35 dyoung Exp $    */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.166 2009/11/12 08:41:49 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.167 2009/11/12 20:11:35 dyoung Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_usbverbose.h"
@@ -1480,34 +1480,38 @@
  * Called from process context when we discover that a port has
  * been disconnected.
  */
-void
-usb_disconnect_port(struct usbd_port *up, device_t parent)
+int
+usb_disconnect_port(struct usbd_port *up, device_t parent, int flags)
 {
        usbd_device_handle dev = up->device;
+       device_t subdev;
+       char subdevname[16];
        const char *hubname = device_xname(parent);
-       int i;
+       int i, rc;
 
        DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
                    up, dev, up->portno));
 
+       if (dev == NULL) {
 #ifdef DIAGNOSTIC
-       if (dev == NULL) {
                printf("usb_disconnect_port: no device\n");
-               return;
+#endif
+               return 0;
        }
-#endif
 
        if (dev->subdevlen > 0) {
                DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
                for (i = 0; i < dev->subdevlen; i++) {
-                       if (!dev->subdevs[i])
+                       if ((subdev = dev->subdevs[i]) == NULL)
                                continue;
-                       printf("%s: at %s", device_xname(dev->subdevs[i]),
-                              hubname);
+                       strlcpy(subdevname, device_xname(subdev),
+                           sizeof(subdevname));
+                       if ((rc = config_detach(subdev, flags)) != 0)
+                               return rc;
+                       printf("%s: at %s", subdevname, hubname);
                        if (up->portno != 0)
                                printf(" port %d", up->portno);
                        printf(" (addr %d) disconnected\n", dev->address);
-                       config_detach(dev->subdevs[i], DETACH_FORCE);
                }
                KASSERT(!dev->nifaces_claimed);
        }
@@ -1516,4 +1520,5 @@
        dev->bus->devices[dev->address] = NULL;
        up->device = NULL;
        usb_free_device(dev);
+       return 0;
 }
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usbdivar.h
--- a/sys/dev/usb/usbdivar.h    Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usbdivar.h    Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdivar.h,v 1.90 2009/11/12 08:16:50 uebayasi Exp $   */
+/*     $NetBSD: usbdivar.h,v 1.91 2009/11/12 20:11:35 dyoung Exp $     */
 /*     $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $   */
 
 /*
@@ -251,7 +251,7 @@
 
 usbd_status    usb_insert_transfer(usbd_xfer_handle);
 void           usb_transfer_complete(usbd_xfer_handle);
-void           usb_disconnect_port(struct usbd_port *, device_t);
+int            usb_disconnect_port(struct usbd_port *, device_t, int);
 
 /* Routines from usb.c */
 void           usb_needs_explore(usbd_device_handle);



Home | Main Index | Thread Index | Old Index