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>
This commit is contained in:
Julius Werner 2013-01-11 16:25:52 -08:00 committed by Ronald G. Minnich
parent 716375dd3e
commit 69eea7c01a
1 changed files with 4 additions and 0 deletions

View File

@ -241,6 +241,10 @@ static int fill_td(qtd_t *td, void* data, int datalen)
} }
datalen -= 4096; datalen -= 4096;
total_len += 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; td->token |= total_len << QTD_TOTAL_LEN_SHIFT;