On Thu, 20 Jan 2011, Robert Morell wrote: > The Tegra2 USB controller doesn't properly deal with misaligned DMA > buffers, causing corruption. This is especially prevalent with USB > network adapters, where skbuff alignment is often in the middle of a > 4-byte dword. > > To avoid this, allocate a temporary buffer for the DMA if the provided > buffer isn't sufficiently aligned. > > Signed-off-by: Robert Morell <rmorell@xxxxxxxxxx> > --- > drivers/usb/host/ehci-tegra.c | 92 +++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 92 insertions(+), 0 deletions(-) > > diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c > index 2341904..7cdfc65 100644 > --- a/drivers/usb/host/ehci-tegra.c > +++ b/drivers/usb/host/ehci-tegra.c > @@ -32,6 +32,8 @@ > #define TEGRA_USB_USBMODE_HOST (3 << 0) > #define TEGRA_USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) > > +#define TEGRA_USB_DMA_ALIGN 32 > + > struct tegra_ehci_context { > bool valid; > u32 command; > @@ -461,6 +463,94 @@ static int tegra_ehci_bus_resume(struct usb_hcd *hcd) > } > #endif > > +struct temp_buffer { > + void *kmalloc_ptr; > + void *old_xfer_buffer; > + u8 data[0]; > +}; > + > +static void free_temp_buffer(struct urb *urb, int status) > +{ > + enum dma_data_direction dir; > + struct temp_buffer *temp; > + > + if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) > + return; > + > + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; > + > + temp = container_of(urb->transfer_buffer, struct temp_buffer, > + data); > + > + if (dir == DMA_FROM_DEVICE && !status) > + memcpy(temp->old_xfer_buffer, temp->data, > + urb->transfer_buffer_length); Even if status is nonzero, there may be valid data in the buffer. You should skip that test. No other problems that I can see. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html