]> git.sur5r.net Git - u-boot/commitdiff
usb: dwc2: invalidate the dcache before starting the DMA
authorEddie Cai <eddie.cai.linux@gmail.com>
Thu, 6 Apr 2017 03:37:04 +0000 (11:37 +0800)
committerMarek Vasut <marex@denx.de>
Fri, 14 Apr 2017 14:44:16 +0000 (16:44 +0200)
We should invalidate the dcache before starting the DMA. In case there are
any dirty lines from the DMA buffer in the cache, subsequent cache-line
replacements may corrupt the buffer in memory while the DMA is still going on.
Cache-line replacement can happen if the CPU tries to bring some other memory
locations into the cache while the DMA is going on.

Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
Reviewed-by: Stefan BrĂ¼ns <stefan.bruens@rwth-aachen.de>
drivers/usb/host/dwc2.c

index ae7d8fb1da7153d4994b08f31deaa051f91a5eea..0e5df15a0de0420393a35f1f1f3236c8a1024549 100644 (file)
@@ -817,12 +817,19 @@ static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
               (*pid << DWC2_HCTSIZ_PID_OFFSET),
               &hc_regs->hctsiz);
 
-       if (!in && xfer_len) {
-               memcpy(aligned_buffer, buffer, xfer_len);
-
-               flush_dcache_range((unsigned long)aligned_buffer,
-                                  (unsigned long)aligned_buffer +
-                                  roundup(xfer_len, ARCH_DMA_MINALIGN));
+       if (xfer_len) {
+               if (in) {
+                       invalidate_dcache_range(
+                                       (uintptr_t)aligned_buffer,
+                                       (uintptr_t)aligned_buffer +
+                                       roundup(xfer_len, ARCH_DMA_MINALIGN));
+               } else {
+                       memcpy(aligned_buffer, buffer, xfer_len);
+                       flush_dcache_range(
+                                       (uintptr_t)aligned_buffer,
+                                       (uintptr_t)aligned_buffer +
+                                       roundup(xfer_len, ARCH_DMA_MINALIGN));
+               }
        }
 
        writel(phys_to_bus((unsigned long)aligned_buffer), &hc_regs->hcdma);