summaryrefslogtreecommitdiff
path: root/payloads/libpayload/drivers
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2013-01-11 16:25:52 -0800
committerRonald G. Minnich <rminnich@gmail.com>2013-03-13 23:08:11 +0100
commit69eea7c01af0ce095aa7618eadae72e86f6eebbe (patch)
treeaa8da537c37121dc0817462e5a78417ede0d6728 /payloads/libpayload/drivers
parent716375dd3ee8ec695c38b2ab25e714a0cc116fb0 (diff)
libpayload: Split EHCI bulk transfers on packet boundaries over qTDs
EHCI controllers see transfers as a queue of transfer descriptors (qTDs), each of which can represent an aligned area of up to 20KB. Each qTD is processed separately, which means that a single USB packet cannot span multiple qTDs. While this should not be a problem according to the specification, some USB storage devices seem to get confused when a packet in the middle of a transfer is smaller than the maximum packet size (512 bytes) due to falling on a qTD boundary. This patch aligns the total transfer length per qTD to 512 bytes to avoid that problem (any excess bytes will simply roll over to the next qTD). Change-Id: I0b5db07507699a3861b30c1a5ee774c45dda7fdd Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: http://review.coreboot.org/2651 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'payloads/libpayload/drivers')
-rw-r--r--payloads/libpayload/drivers/usb/ehci.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/payloads/libpayload/drivers/usb/ehci.c b/payloads/libpayload/drivers/usb/ehci.c
index d33fec57b6..972962cf51 100644
--- a/payloads/libpayload/drivers/usb/ehci.c
+++ b/payloads/libpayload/drivers/usb/ehci.c
@@ -241,6 +241,10 @@ static int fill_td(qtd_t *td, void* data, int datalen)
}
datalen -= 4096;
total_len += 4096;
+
+ /* end TD at a packet boundary if transfer not complete */
+ if (page_no == 5)
+ total_len &= ~511;
}
}
td->token |= total_len << QTD_TOTAL_LEN_SHIFT;