aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndrey Konovalov <andrey.konovalov@linaro.org>2012-07-16 20:24:10 +0400
committerAndrey Konovalov <andrey.konovalov@linaro.org>2012-07-16 20:24:10 +0400
commitb3768db6f4d8407882c02d560389543c972d4748 (patch)
treef1a1632e87232ae67e2c0e59197a26c62e1d6b26 /drivers
parentc98c5ee0ecac183b83b12ea12c760640cf50cfee (diff)
parent6af8da9c55bf34b0089db8296c0e55470b8a7b27 (diff)
Merge branch 'tracking-unsorted' into merge-linux-linaro
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/platform.c7
-rw-r--r--drivers/usb/host/ehci-q.c18
-rw-r--r--drivers/usb/host/ehci.h17
3 files changed, 42 insertions, 0 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index e44f8c2d239d..4150b9427047 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -348,6 +348,7 @@ static int of_platform_bus_create(struct device_node *bus,
struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
+ int id = -1;
int rc = 0;
/* Make sure it has a compatible property */
@@ -360,6 +361,7 @@ static int of_platform_bus_create(struct device_node *bus,
auxdata = of_dev_lookup(lookup, bus);
if (auxdata) {
bus_id = auxdata->name;
+ id = auxdata->id;
platform_data = auxdata->platform_data;
}
@@ -369,6 +371,11 @@ static int of_platform_bus_create(struct device_node *bus,
}
dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
+
+ /* override the id if auxdata gives an id */
+ if (id != -1)
+ dev->id = id;
+
if (!dev || !of_match_node(matches, bus))
return 0;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4378bf72bbac..a878ab1f6b99 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1003,6 +1003,12 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head->qh_next.qh = qh;
head->hw->hw_next = dma;
+ /*
+ * flush qh descriptor into memory immediately,
+ * see comments in qh_append_tds.
+ */
+ ehci_sync_mem();
+
qh_get(qh);
qh->xacterrs = 0;
qh->qh_state = QH_STATE_LINKED;
@@ -1090,6 +1096,18 @@ static struct ehci_qh *qh_append_tds (
wmb ();
dummy->hw_token = token;
+ /*
+ * Writing to dma coherent buffer on ARM may
+ * be delayed to reach memory, so HC may not see
+ * hw_token of dummy qtd in time, which can cause
+ * the qtd transaction to be executed very late,
+ * and degrade performance a lot. ehci_sync_mem
+ * is added to flush 'token' immediatelly into
+ * memory, so that ehci can execute the transaction
+ * ASAP.
+ */
+ ehci_sync_mem();
+
urb->hcpriv = qh_get (qh);
}
}
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2694ed6558d2..b44c37d59ef0 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -748,6 +748,23 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
#endif
+/*
+ * Writing to dma coherent memory on ARM may be delayed via L2
+ * writing buffer, so introduce the helper which can flush L2 writing
+ * buffer into memory immediately, especially used to flush ehci
+ * descriptor to memory.
+ */
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+static inline void ehci_sync_mem()
+{
+ mb();
+}
+#else
+static inline void ehci_sync_mem()
+{
+}
+#endif
+
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PCI