diff options
Diffstat (limited to 'sys/dev/usb/usb_hub.c')
-rw-r--r-- | sys/dev/usb/usb_hub.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 2c81d97..07a0970 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -316,12 +316,13 @@ repeat: if (err) { goto error; } - /* detach any existing devices */ + /* check if there is a child */ - if (child) { - usb_free_device(child, - USB_UNCFG_FLAG_FREE_SUBDEV | - USB_UNCFG_FLAG_FREE_EP0); + if (child != NULL) { + /* + * Free USB device and all subdevices, if any. + */ + usb_free_device(child, 0); child = NULL; } /* get fresh status */ @@ -438,10 +439,11 @@ repeat: return (0); /* success */ error: - if (child) { - usb_free_device(child, - USB_UNCFG_FLAG_FREE_SUBDEV | - USB_UNCFG_FLAG_FREE_EP0); + if (child != NULL) { + /* + * Free USB device and all subdevices, if any. + */ + usb_free_device(child, 0); child = NULL; } if (err == 0) { @@ -888,12 +890,14 @@ uhub_detach(device_t dev) struct usb_device *child; uint8_t x; - /* detach all children first */ - bus_generic_detach(dev); - if (hub == NULL) { /* must be partially working */ return (0); } + + /* Make sure interrupt transfer is gone. */ + usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER); + + /* Detach all ports */ for (x = 0; x != hub->nports; x++) { child = usb_bus_port_get_device(sc->sc_udev->bus, hub->ports + x); @@ -901,16 +905,13 @@ uhub_detach(device_t dev) if (child == NULL) { continue; } + /* - * Subdevices are not freed, because the caller of - * uhub_detach() will do that. + * Free USB device and all subdevices, if any. */ - usb_free_device(child, - USB_UNCFG_FLAG_FREE_EP0); + usb_free_device(child, 0); } - usbd_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER); - free(hub, M_USBDEV); sc->sc_udev->hub = NULL; @@ -984,10 +985,19 @@ static int uhub_child_location_string(device_t parent, device_t child, char *buf, size_t buflen) { - struct uhub_softc *sc = device_get_softc(parent); - struct usb_hub *hub = sc->sc_udev->hub; + struct uhub_softc *sc; + struct usb_hub *hub; struct hub_result res; + if (!device_is_attached(parent)) { + if (buflen) + buf[0] = 0; + return (0); + } + + sc = device_get_softc(parent); + hub = sc->sc_udev->hub; + mtx_lock(&Giant); uhub_find_iface_index(hub, child, &res); if (!res.udev) { @@ -1009,11 +1019,20 @@ static int uhub_child_pnpinfo_string(device_t parent, device_t child, char *buf, size_t buflen) { - struct uhub_softc *sc = device_get_softc(parent); - struct usb_hub *hub = sc->sc_udev->hub; + struct uhub_softc *sc; + struct usb_hub *hub; struct usb_interface *iface; struct hub_result res; + if (!device_is_attached(parent)) { + if (buflen) + buf[0] = 0; + return (0); + } + + sc = device_get_softc(parent); + hub = sc->sc_udev->hub; + mtx_lock(&Giant); uhub_find_iface_index(hub, child, &res); if (!res.udev) { |