diff options
author | hselasky <hselasky@FreeBSD.org> | 2016-01-05 09:18:43 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-05 10:23:15 +0100 |
commit | c04e7c2657fc630ac6a2abc0945aadf37056d339 (patch) | |
tree | ed7a07e4c08daeccc5ccb5dcc762deb8f5c69962 /freebsd/sys/dev/usb | |
parent | NETSTAT(1): Avoid use of uninitialized memory (diff) | |
download | rtems-libbsd-c04e7c2657fc630ac6a2abc0945aadf37056d339.tar.bz2 |
Fix for directly connected FULL or LOW speed USB devices.
Found by: Sebastian Huber <sebastian.huber@embedded-brains.de>
MFC after: 1 week
Diffstat (limited to 'freebsd/sys/dev/usb')
-rw-r--r-- | freebsd/sys/dev/usb/controller/dwc_otg.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c index 2110b94d..7d55c800 100644 --- a/freebsd/sys/dev/usb/controller/dwc_otg.c +++ b/freebsd/sys/dev/usb/controller/dwc_otg.c @@ -458,6 +458,18 @@ dwc_otg_init_fifo(struct dwc_otg_softc *sc, uint8_t mode) return (0); } +static uint8_t +dwc_otg_uses_split(struct usb_device *udev) +{ + /* + * When a LOW or FULL speed device is connected directly to + * the USB port we don't use split transactions: + */ + return (udev->speed != USB_SPEED_HIGH && + udev->parent_hs_hub != NULL && + udev->parent_hs_hub->parent_hub != NULL); +} + static void dwc_otg_update_host_frame_interval(struct dwc_otg_softc *sc) { @@ -3331,16 +3343,16 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer) else hcchar |= (td->ep_type << HCCHAR_EPTYPE_SHIFT); - if (usbd_get_speed(xfer->xroot->udev) == USB_SPEED_LOW) - hcchar |= HCCHAR_LSPDDEV; if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN) hcchar |= HCCHAR_EPDIR_IN; switch (xfer->xroot->udev->speed) { - case USB_SPEED_FULL: case USB_SPEED_LOW: + hcchar |= HCCHAR_LSPDDEV; + /* FALLTHROUGH */ + case USB_SPEED_FULL: /* check if root HUB port is running High Speed */ - if (xfer->xroot->udev->parent_hs_hub != NULL) { + if (dwc_otg_uses_split(xfer->xroot->udev)) { hcsplt = HCSPLT_SPLTENA | (xfer->xroot->udev->hs_port_no << HCSPLT_PRTADDR_SHIFT) | @@ -4162,7 +4174,10 @@ dwc_otg_device_isoc_start(struct usb_xfer *xfer) framenum = DSTS_SOFFN_GET(temp); } - if (xfer->xroot->udev->parent_hs_hub != NULL) + /* + * Check if port is doing 8000 or 1000 frames per second: + */ + if (sc->sc_flags.status_high_speed) framenum /= 8; framenum &= DWC_OTG_FRAME_MASK; @@ -4839,7 +4854,7 @@ dwc_otg_xfer_setup(struct usb_setup_params *parm) td = USB_ADD_BYTES(parm->buf, parm->size[0]); /* compute shared bandwidth resource index for TT */ - if (parm->udev->parent_hs_hub != NULL && parm->udev->speed != USB_SPEED_HIGH) { + if (dwc_otg_uses_split(parm->udev)) { if (parm->udev->parent_hs_hub->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) td->tt_index = parm->udev->device_index; else |