autoconf(9) is your friend and it knows you more than you think. It
authormpi <mpi@openbsd.org>
Wed, 9 Jul 2014 18:15:04 +0000 (18:15 +0000)
committermpi <mpi@openbsd.org>
Wed, 9 Jul 2014 18:15:04 +0000 (18:15 +0000)
even knows your children!  So let him handle the seperation correctly.

Do not rewrite your own custom config_detach_children(9) and as a bonus
start removing the usbd_port tentacles from the stack.

ok pirofti@, yuo@, miod@, deraadt@

sys/dev/usb/uhub.c
sys/dev/usb/usb.c
sys/dev/usb/usb_subr.c
sys/dev/usb/usbdivar.h

index b597424..f842784 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uhub.c,v 1.67 2014/05/28 11:20:55 mpi Exp $ */
+/*     $OpenBSD: uhub.c,v 1.68 2014/07/09 18:15:04 mpi Exp $ */
 /*     $NetBSD: uhub.c,v 1.64 2003/02/08 03:32:51 ichiro Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $       */
 
@@ -77,23 +77,17 @@ void uhub_intr(struct usbd_xfer *, void *, usbd_status);
 int uhub_match(struct device *, void *, void *); 
 void uhub_attach(struct device *, struct device *, void *); 
 int uhub_detach(struct device *, int); 
-int uhub_activate(struct device *, int); 
 
 struct cfdriver uhub_cd = { 
        NULL, "uhub", DV_DULL 
 }; 
 
-const struct cfattach uhub_ca = { 
-       sizeof(struct uhub_softc), 
-       uhub_match, 
-       uhub_attach, 
-       uhub_detach, 
-       uhub_activate, 
+const struct cfattach uhub_ca = {
+       sizeof(struct uhub_softc), uhub_match, uhub_attach,  uhub_detach
 };
 
-struct cfattach uhub_uhub_ca = {
-       sizeof(struct uhub_softc), uhub_match, uhub_attach,
-       uhub_detach, uhub_activate
+const struct cfattach uhub_uhub_ca = {
+       sizeof(struct uhub_softc), uhub_match, uhub_attach,  uhub_detach
 };
 
 int
@@ -395,7 +389,8 @@ uhub_explore(struct usbd_device *dev)
        disco:
                if (up->device != NULL) {
                        /* Disconnected */
-                       usb_disconnect_port(up, &sc->sc_dev);
+                       usbd_detach(up->device, &sc->sc_dev);
+                       up->device = NULL;
                        usbd_clear_port_feature(dev, port,
                                                UHF_C_PORT_CONNECTION);
                }
@@ -473,31 +468,6 @@ uhub_explore(struct usbd_device *dev)
        return (0);
 }
 
-int
-uhub_activate(struct device *self, int act)
-{
-       struct uhub_softc *sc = (struct uhub_softc *)self;
-       struct usbd_hub *hub = sc->sc_hub->hub;
-       struct usbd_device *dev;
-       int nports, port, i;
-
-       switch (act) {
-       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 != NULL && dev->subdevs != NULL) {
-                               for (i = 0; dev->subdevs[i] != NULL; i++)
-                                       config_deactivate(dev->subdevs[i]);
-                       }
-               }
-               break;
-       }
-       return (0);
-}
-
 /*
  * Called from process context when the hub is gone.
  * Detach all devices on active ports.
@@ -519,8 +489,10 @@ uhub_detach(struct device *self, int flags)
        nports = hub->hubdesc.bNbrPorts;
        for(port = 0; port < nports; port++) {
                rup = &hub->ports[port];
-               if (rup->device)
-                       usb_disconnect_port(rup, self);
+               if (rup->device != NULL) {
+                       usbd_detach(rup->device, self);
+                       rup->device = NULL;
+               }
        }
 
        if (hub->ports[0].tt)
index 2397a2f..364fe7e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb.c,v 1.97 2014/05/28 11:20:55 mpi Exp $    */
+/*     $OpenBSD: usb.c,v 1.98 2014/07/09 18:15:04 mpi Exp $    */
 /*     $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */
 
 /*
@@ -849,8 +849,10 @@ usb_explore(void *v)
                sc->sc_bus->dying = 1;
 
                /* Make all devices disconnect. */
-               if (sc->sc_port.device != NULL)
-                       usb_disconnect_port(&sc->sc_port, (struct device *)sc);
+               if (sc->sc_port.device != NULL) {
+                       usbd_detach(sc->sc_port.device, (struct device *)sc);
+                       sc->sc_port.device = NULL;
+               }
 
                sc->sc_bus->flags &= ~USB_BUS_DISCONNECTING;
        } else {
index eadf5b4..2bdeaeb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb_subr.c,v 1.101 2014/07/09 15:47:54 mpi Exp $ */
+/*     $OpenBSD: usb_subr.c,v 1.102 2014/07/09 18:15:04 mpi Exp $ */
 /*     $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
@@ -72,7 +72,7 @@ usbd_status   usbd_probe_and_attach(struct device *,
                    struct usbd_device *, int, int);
 
 int            usbd_printBCD(char *cp, size_t len, int bcd);
-void           usb_free_device(struct usbd_device *, struct usbd_port *);
+void           usb_free_device(struct usbd_device *);
 
 #ifdef USBVERBOSE
 #include <dev/usb/usbdevs_data.h>
@@ -1092,7 +1092,8 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
            &dev->default_pipe);
        if (err) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
@@ -1137,11 +1138,9 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
                        USB_MAX_IPACKET, dd);
        }
 
-       /* fail to get device descriptor, give up */
        if (err) {
-               DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
-                   "failed\n", addr));
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
@@ -1163,16 +1162,14 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
                 dev->speed));
 
        if (dd->bDescriptorType != UDESC_DEVICE) {
-               /* Illegal device descriptor */
-               DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
-                   dd->bDescriptorType));
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (USBD_INVAL);
        }
 
        if (dd->bLength < USB_DEVICE_DESCRIPTOR_SIZE) {
-               DPRINTFN(-1,("usbd_new_device: bad length %d\n", dd->bLength));
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (USBD_INVAL);
        }
 
@@ -1183,20 +1180,23 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
            &dev->default_pipe);
        if (err) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
        err = usbd_reload_device_desc(dev);
        if (err) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
        /* Set the address if the HC didn't do it already. */
        if (bus->methods->dev_setaddr != NULL &&
            bus->methods->dev_setaddr(dev, addr)) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (USBD_SET_ADDR_FAILED);
        }
 
@@ -1205,7 +1205,8 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
        err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
            &dev->default_pipe);
        if (err) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
@@ -1231,7 +1232,8 @@ usbd_new_device(struct device *parent, struct usbd_bus *bus, int depth,
 
        err = usbd_probe_and_attach(parent, dev, port, addr);
        if (err) {
-               usb_free_device(dev, up);
+               usb_free_device(dev);
+               up->device = NULL;
                return (err);
        }
 
@@ -1424,7 +1426,7 @@ usbd_get_cdesc(struct usbd_device *dev, int index, int *lenp)
 }
 
 void
-usb_free_device(struct usbd_device *dev, struct usbd_port *up)
+usb_free_device(struct usbd_device *dev)
 {
        int ifcidx, nifc;
 
@@ -1444,7 +1446,6 @@ usb_free_device(struct usbd_device *dev, struct usbd_port *up)
                free(dev->cdesc, M_USB);
        if (dev->subdevs != NULL)
                free(dev->subdevs, M_USB);
-       up->device = NULL;
        dev->bus->devices[dev->address] = NULL;
 
        free(dev, M_USB);
@@ -1467,38 +1468,14 @@ usb_free_device(struct usbd_device *dev, struct usbd_port *up)
  * Called from process context when we discover that a port has
  * been disconnected.
  */
-void
-usb_disconnect_port(struct usbd_port *up, struct device *parent)
+int
+usbd_detach(struct usbd_device *dev, struct device *parent)
 {
-       struct usbd_device *dev = up->device;
-       int i;
-
-       DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
-                   up, dev, up->portno));
-
-#ifdef DIAGNOSTIC
-       if (dev == NULL) {
-               printf("usb_disconnect_port: no device\n");
-               return;
-       }
-#endif
+       int rv;
 
-       if (dev->subdevs != NULL) {
-               DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
-               for (i = 0; dev->subdevs[i]; i++) {
-                       DPRINTF(("%s: at %s", dev->subdevs[i]->dv_xname,
-                           parent->dv_xname));
-                       if (up->portno != 0)
-                               DPRINTF((" port %d", up->portno));
-                       DPRINTF((" (addr %d) deactivated\n", dev->address));
-                       config_deactivate(dev->subdevs[i]);
-               }
-               for (i = 0; dev->subdevs[i]; i++) {
-                       DPRINTF((" (addr %d) disconnected\n", dev->address));
-                       config_detach(dev->subdevs[i], DETACH_FORCE);
-                       dev->subdevs[i] = 0;
-               }
-       }
+       rv = config_detach_children(parent, DETACH_FORCE);
+       if (rv == 0)
+               usb_free_device(dev);
 
-       usb_free_device(dev, up);
+       return (rv);
 }
index 18ae506..c8b860a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdivar.h,v 1.60 2014/07/09 15:47:54 mpi Exp $ */
+/*     $OpenBSD: usbdivar.h,v 1.61 2014/07/09 18:15:04 mpi Exp $ */
 /*     $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $   */
 /*     $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $   */
 
@@ -245,7 +245,7 @@ usbd_status usbd_fill_iface_data(struct usbd_device *, int, int);
 
 usbd_status    usb_insert_transfer(struct usbd_xfer *);
 void           usb_transfer_complete(struct usbd_xfer *);
-void           usb_disconnect_port(struct usbd_port *, struct device *);
+int            usbd_detach(struct usbd_device *, struct device *);
 
 /* Routines from usb.c */
 void           usb_needs_explore(struct usbd_device *, int);