diff options
-rw-r--r-- | drivers/usb/host/ehci-q.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 22 |
2 files changed, 24 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5c25783a7643..0eb20989d67e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -334,6 +334,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_COMPLETING; stopped = (state == QH_STATE_IDLE); + ehci_sync_qh(ehci, qh); rescan: last = NULL; last_status = -EINPROGRESS; @@ -367,6 +368,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) if (qtd == end) break; + ehci_sync_qtd(ehci, qtd); /* hardware copies qtd out of qh overlay */ rmb (); token = hc32_to_cpu(ehci, qtd->hw_token); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index cfbdf32ec0b2..569cdf5a4c03 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -767,10 +767,32 @@ static inline void ehci_sync_mem(void) { mb(); } + +/* + * DMA coherent memory on ARM which features speculative prefetcher doesn't + * guarantee coherency, so introduce the helpers which can invalidate QH and + * QTD in L1/L2 cache. It enforces CPU reads from memory directly. + */ +static inline void ehci_sync_qh(struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + dma_sync_single_for_cpu(ehci_to_hcd(ehci)->self.controller, qh->qh_dma, + sizeof(struct ehci_qh_hw), DMA_FROM_DEVICE); +} +static inline void ehci_sync_qtd(struct ehci_hcd *ehci, struct ehci_qtd *qtd) +{ + dma_sync_single_for_cpu(ehci_to_hcd(ehci)->self.controller, + qtd->qtd_dma, sizeof(struct ehci_qtd), DMA_FROM_DEVICE); +} #else static inline void ehci_sync_mem() { } +static inline void ehci_sync_qh(struct ehci_hcd *ehci, struct ehci_qh *qh) +{ +} +static inline void ehci_sync_qtd(struct ehci_hcd *ehci, struct ehci_qtd *qtd) +{ +} #endif /*-------------------------------------------------------------------------*/ |