diff options
author | Eddie Cai <eddie.cai.linux@gmail.com> | 2017-04-06 11:37:04 +0800 |
---|---|---|
committer | Marek Vasut <marex@denx.de> | 2017-04-14 16:44:16 +0200 |
commit | 57ca63b86e5987029cd4970890aa28602ba50856 (patch) | |
tree | 3156baad07499a98e8568005bb99306d4f7efb56 | |
parent | 889239d6b5c15c82d507498ded5e3b8fea2d44cf (diff) |
usb: dwc2: invalidate the dcache before starting the DMA
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>
-rw-r--r-- | drivers/usb/host/dwc2.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index ae7d8fb1da..0e5df15a0d 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -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); |