diff options
Diffstat (limited to 'sys/dev/usb/usb_hub.c')
-rw-r--r-- | sys/dev/usb/usb_hub.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 0defc97..2c81d97 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -96,6 +96,7 @@ struct uhub_current_state { struct uhub_softc { struct uhub_current_state sc_st;/* current state */ device_t sc_dev; /* base device */ + struct mtx sc_mtx; /* our mutex */ struct usb_device *sc_udev; /* USB device */ struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ uint8_t sc_flags; @@ -428,7 +429,6 @@ repeat: mode = USB_MODE_HOST; /* need to create a new child */ - child = usb_alloc_device(sc->sc_dev, udev->bus, udev, udev->depth + 1, portno - 1, portno, speed, mode); if (child == NULL) { @@ -691,6 +691,8 @@ uhub_attach(device_t dev) sc->sc_udev = udev; sc->sc_dev = dev; + mtx_init(&sc->sc_mtx, "USB HUB mutex", NULL, MTX_DEF); + snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -774,7 +776,7 @@ uhub_attach(device_t dev) } else { /* normal HUB */ err = usbd_transfer_setup(udev, &iface_index, sc->sc_xfer, - uhub_config, UHUB_N_TRANSFER, sc, &Giant); + uhub_config, UHUB_N_TRANSFER, sc, &sc->sc_mtx); } if (err) { DPRINTFN(0, "cannot setup interrupt transfer, " @@ -850,9 +852,9 @@ uhub_attach(device_t dev) /* Start the interrupt endpoint, if any */ if (sc->sc_xfer[0] != NULL) { - USB_XFER_LOCK(sc->sc_xfer[0]); + mtx_lock(&sc->sc_mtx); usbd_transfer_start(sc->sc_xfer[0]); - USB_XFER_UNLOCK(sc->sc_xfer[0]); + mtx_unlock(&sc->sc_mtx); } /* Enable automatic power save on all USB HUBs */ @@ -868,6 +870,9 @@ error: free(udev->hub, M_USBDEV); udev->hub = NULL; } + + mtx_destroy(&sc->sc_mtx); + return (ENXIO); } @@ -908,6 +913,9 @@ uhub_detach(device_t dev) free(hub, M_USBDEV); sc->sc_udev->hub = NULL; + + mtx_destroy(&sc->sc_mtx); + return (0); } @@ -1775,10 +1783,13 @@ usb_dev_resume_peer(struct usb_device *udev) /* always update hardware power! */ (bus->methods->set_hw_power) (bus); } - sx_xlock(udev->default_sx + 1); + + usbd_enum_lock(udev); + /* notify all sub-devices about resume */ err = usb_suspend_resume(udev, 0); - sx_unlock(udev->default_sx + 1); + + usbd_enum_unlock(udev); /* check if peer has wakeup capability */ if (usb_peer_can_wakeup(udev)) { @@ -1844,10 +1855,12 @@ repeat: } } - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); + /* notify all sub-devices about suspend */ err = usb_suspend_resume(udev, 1); - sx_unlock(udev->default_sx + 1); + + usbd_enum_unlock(udev); if (usb_peer_can_wakeup(udev)) { /* allow device to do remote wakeup */ |