
CONFIG_USB_EHCI_DATA_ALIGN sets the required alignment of data for USB packets (e.g. 4 means word-aligned). This is required for Tegra to operate.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v2: - Tidy code style in USB buffer alignment code - Display prominent warning when alignment code is triggered
README | 6 ++++++ drivers/usb/host/ehci-hcd.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/README b/README index fda0190..3194846 100644 --- a/README +++ b/README @@ -1096,6 +1096,12 @@ The following options need to be configured: May be defined to allow interrupt polling instead of using asynchronous interrupts
+ CONFIG_USB_EHCI_DATA_ALIGN sets the required alignment of + data for USB packets (e.g. 4 means word-aligned). This is + required for Tegra to operate. Since we want all callers to + align data for us, we display a warning when the alignment + code is triggered. + - USB Device: Define the below if you wish to use the USB console. Once firmware is rebuilt from a serial console issue the diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 2197119..23458b6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -322,6 +322,24 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int timeout; int ret = 0;
+#ifdef CONFIG_USB_EHCI_DATA_ALIGN + /* In case ehci host requires alignment for buffers */ + void *align_buf = NULL; + void *orig_buf = buffer; + int unaligned = (int)buffer & (CONFIG_USB_EHCI_DATA_ALIGN - 1); + + if (unaligned) { + printf("EHCI: Unaligned buffer: performance will suffer\n"); + align_buf = malloc(length + CONFIG_USB_EHCI_DATA_ALIGN); + if (!align_buf) + return -1; + buffer = (void *)(((ulong)align_buf + + CONFIG_USB_EHCI_DATA_ALIGN - 1) & + ~(CONFIG_USB_EHCI_DATA_ALIGN - 1)); + if (usb_pipeout(pipe)) + memcpy(buffer, orig_buf, length); + } +#endif debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, buffer, length, req); if (req != NULL) @@ -513,9 +531,20 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci_readl(&hcor->or_portsc[1])); }
+#ifdef CONFIG_USB_EHCI_DATA_ALIGN + if (unaligned) { + if (usb_pipein(pipe) && dev->act_len) + memcpy(orig_buf, buffer, length); + free(align_buf); + } +#endif return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
fail: +#ifdef CONFIG_USB_EHCI_DATA_ALIGN + if (unaligned) + free(align_buf); +#endif td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); while (td != (void *)QT_NEXT_TERMINATE) { qh->qh_overlay.qt_next = td->qt_next;