summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorJC Kuo <jckuo@nvidia.com>2012-07-17 17:57:44 +0800
committerSimone Willett <swillett@nvidia.com>2012-07-27 17:17:18 -0700
commitafee560766283360ee64f7b8f9a92c561be2847a (patch)
treef2793669ee45a2ff70b9c53fc86965c3a8ed88d8 /drivers/usb
parent1dfcfbc1b81a9579ce781005cb423a26d1e7096e (diff)
usb: ehci: DMA buffer sync for qh/qtd descriptors
When EHCI host controller driver examines qh/qtd descriptors, driver might see stale data in cache on some ARM CPU. This patch introduces two helper functions, ehci_sync_qh() and ehci_sync_qtd(), to invalidate cached descriptors so that driver can always read up-to-date descriptors from memory. Bug 1005403 Change-Id: I2345bda7dfe29c5fe7f9550066b518cd6624d263 Signed-off-by: JC Kuo <jckuo@nvidia.com> Reviewed-on: http://git-master/r/116406 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: WK Tsai <wtsai@nvidia.com> Reviewed-by: ChihMin Cheng <ccheng@nvidia.com> Reviewed-by: Joy Wang <joyw@nvidia.com> Reviewed-by: Vinayak Pane <vpane@nvidia.com> Reviewed-by: Michael Hsu <mhsu@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-q.c2
-rw-r--r--drivers/usb/host/ehci.h22
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
/*-------------------------------------------------------------------------*/