summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller/ehci.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2012-04-29 17:12:33 +0000
committerhselasky <hselasky@FreeBSD.org>2012-04-29 17:12:33 +0000
commit5827c4e6ace287e7d537ca4e7b19b17680693d6a (patch)
tree75a758f6263175281d04ea31332521e60c1a4fc7 /sys/dev/usb/controller/ehci.c
parent99428404bed28d421872e61f367292954ab61dc2 (diff)
downloadFreeBSD-src-5827c4e6ace287e7d537ca4e7b19b17680693d6a.zip
FreeBSD-src-5827c4e6ace287e7d537ca4e7b19b17680693d6a.tar.gz
Add support for Multi-TT mode of modern USB HUBs.
This will give you more bandwidth for isochronous FULL speed applications connected through a High Speed HUB. This patch has been tested with XHCI and EHCI. MFC after: 1 week
Diffstat (limited to 'sys/dev/usb/controller/ehci.c')
-rw-r--r--sys/dev/usb/controller/ehci.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c
index da37954..a822077 100644
--- a/sys/dev/usb/controller/ehci.c
+++ b/sys/dev/usb/controller/ehci.c
@@ -2398,9 +2398,9 @@ ehci_device_isoc_fs_open(struct usb_xfer *xfer)
EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
- if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN) {
+ if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN)
sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
- }
+
sitd_portaddr = htohc32(sc, sitd_portaddr);
/* initialize all TD's */
@@ -2436,9 +2436,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
{
struct usb_page_search buf_res;
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
- struct usb_fs_isoc_schedule *fss_start;
- struct usb_fs_isoc_schedule *fss_end;
- struct usb_fs_isoc_schedule *fss;
ehci_sitd_t *td;
ehci_sitd_t *td_last = NULL;
ehci_sitd_t **pp_last;
@@ -2450,7 +2447,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
uint16_t tlen;
uint8_t sa;
uint8_t sb;
- uint8_t error;
#ifdef USB_DEBUG
uint8_t once = 1;
@@ -2495,9 +2491,8 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
* pre-compute when the isochronous transfer will be finished:
*/
xfer->isoc_time_complete =
- usbd_fs_isoc_schedule_isoc_time_expand
- (xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
- xfer->nframes;
+ usb_isoc_time_expand(&sc->sc_bus, nframes) +
+ buf_offset + xfer->nframes;
/* get the real number of frames */
@@ -2520,19 +2515,14 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
xfer->qh_pos = xfer->endpoint->isoc_next;
- fss = fss_start + (xfer->qh_pos % USB_ISOC_TIME_MAX);
-
while (nframes--) {
if (td == NULL) {
panic("%s:%d: out of TD's\n",
__FUNCTION__, __LINE__);
}
- if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
+ if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
pp_last = &sc->sc_isoc_fs_p_last[0];
- }
- if (fss >= fss_end) {
- fss = fss_start;
- }
+
/* reuse sitd_portaddr and sitd_back from last transfer */
if (*plen > xfer->max_frame_size) {
@@ -2547,17 +2537,19 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
#endif
*plen = xfer->max_frame_size;
}
- /*
- * We currently don't care if the ISOCHRONOUS schedule is
- * full!
- */
- error = usbd_fs_isoc_schedule_alloc(fss, &sa, *plen);
- if (error) {
+
+ /* allocate a slot */
+
+ sa = usbd_fs_isoc_schedule_alloc_slot(xfer,
+ xfer->isoc_time_complete - nframes - 1);
+
+ if (sa == 255) {
/*
- * The FULL speed schedule is FULL! Set length
- * to zero.
+ * Schedule is FULL, set length to zero:
*/
+
*plen = 0;
+ sa = USB_FS_ISOC_UFRAME_MAX - 1;
}
if (*plen) {
/*
@@ -2637,7 +2629,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
pp_last++;
plen++;
- fss++;
td_last = td;
td = td->obj_next;
}
OpenPOWER on IntegriCloud