Appearently some out-of-tree USB host drivers do not handle DMA alignment for URB buffers and let core/hcd.c to do the mapping on architectures that have minimum DMA alignment requirements. This leads to random memory corruptions and crashes when using USB device drivers that use unaligned URB buffers. Instead of fixing host drivers, users end up posting bug reports against those USB device drivers that use unaligned buffers for URB; such as with rtl8192cu (http://thread.gmane.org/gmane.linux.kernel.wireless.general/105631). Patch makes this issue more visible at core level, and hopefully gives hint for future hcd driver implementors about this problem. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@xxxxxx> --- drivers/usb/core/hcd.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d53547d..7ad13e6 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1405,6 +1405,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { enum dma_data_direction dir; + unsigned int dma_align = dma_get_cache_alignment(); int ret = 0; /* Map the URB's buffers for DMA access. @@ -1417,6 +1418,14 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (hcd->self.uses_pio_for_control) return ret; if (hcd->self.uses_dma) { + if (PTR_ALIGN(urb->setup_packet, dma_align) != + urb->setup_packet) { + /* USB host driver does not appear to handle + * buffer alignment for DMA; warn once. + */ + WARN_ONCE(1, "urb->setup_packet not DMA aligned.\n"); + } + urb->setup_dma = dma_map_single( hcd->self.controller, urb->setup_packet, @@ -1479,6 +1488,15 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, else urb->transfer_flags |= URB_DMA_MAP_PAGE; } else { + if (PTR_ALIGN(urb->transfer_buffer, dma_align) + != urb->transfer_buffer) { + /* USB host driver does not appear to + * handle buffer alignment for DMA; warn + * once. + */ + WARN_ONCE(1, "urb->transfer_buffer not DMA aligned.\n"); + } + urb->transfer_dma = dma_map_single( hcd->self.controller, urb->transfer_buffer, -- 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