aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorEddie Cai2017-04-06 11:37:04 +0800
committerMarek Vasut2017-04-14 16:44:16 +0200
commit57ca63b86e5987029cd4970890aa28602ba50856 (patch)
tree3156baad07499a98e8568005bb99306d4f7efb56 /drivers/usb
parent889239d6b5c15c82d507498ded5e3b8fea2d44cf (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>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/dwc2.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index ae7d8fb1da7..0e5df15a0de 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);