[RFC PATCH] usb: hcd: warn about URB buffers that are not DMA aligned and are about to be DMA mapped

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux