+++ /dev/null
-From 6402c796d3b4205d3d7296157956c5100a05d7d6 Mon Sep 17 00:00:00 2001
-From: Alan Stern <stern@rowland.harvard.edu>
-Date: Fri, 1 Mar 2013 10:50:08 -0500
-Subject: USB: EHCI: work around silicon bug in Intel's EHCI controllers
-
-From: Alan Stern <stern@rowland.harvard.edu>
-
-commit 6402c796d3b4205d3d7296157956c5100a05d7d6 upstream.
-
-This patch (as1660) works around a hardware problem present in some
-(if not all) Intel EHCI controllers. After a QH has been unlinked
-from the async schedule and the corresponding IAA interrupt has
-occurred, the controller is not supposed access the QH and its qTDs.
-There certainly shouldn't be any more DMA writes to those structures.
-Nevertheless, Intel's controllers have been observed to perform a
-final writeback to the QH's overlay region and to the most recent qTD.
-For more information and a test program to determine whether this
-problem is present in a particular controller, see
-
- http://marc.info/?l=linux-usb&m=135492071812265&w=2
- http://marc.info/?l=linux-usb&m=136182570800963&w=2
-
-This patch works around the problem by always waiting for two IAA
-cycles when unlinking an async QH. The extra IAA delay gives the
-controller time to perform its final writeback.
-
-Surprisingly enough, the effects of this silicon bug have gone
-undetected until quite recently. More through luck than anything
-else, it hasn't caused any apparent problems. However, it does
-interact badly with the path that follows this one, so it needs to be
-addressed.
-
-This is the first part of a fix for the regression reported at:
-
- https://bugs.launchpad.net/bugs/1088733
-
-Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
-Tested-by: Stephen Thirlwall <sdt@dr.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
----
- drivers/usb/host/ehci-hcd.c | 6 ++----
- drivers/usb/host/ehci-q.c | 18 ++++++++++++++----
- 2 files changed, 16 insertions(+), 8 deletions(-)
-
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -748,11 +748,9 @@ static irqreturn_t ehci_irq (struct usb_
- /* guard against (alleged) silicon errata */
- if (cmd & CMD_IAAD)
- ehci_dbg(ehci, "IAA with IAAD still set?\n");
-- if (ehci->async_iaa) {
-+ if (ehci->async_iaa)
- COUNT(ehci->stats.iaa);
-- end_unlink_async(ehci);
-- } else
-- ehci_dbg(ehci, "IAA with nothing unlinked?\n");
-+ end_unlink_async(ehci);
- }
-
- /* remote wakeup [4.3.1] */
---- a/drivers/usb/host/ehci-q.c
-+++ b/drivers/usb/host/ehci-q.c
-@@ -1170,7 +1170,7 @@ static void single_unlink_async(struct e
- struct ehci_qh *prev;
-
- /* Add to the end of the list of QHs waiting for the next IAAD */
-- qh->qh_state = QH_STATE_UNLINK;
-+ qh->qh_state = QH_STATE_UNLINK_WAIT;
- if (ehci->async_unlink)
- ehci->async_unlink_last->unlink_next = qh;
- else
-@@ -1213,9 +1213,19 @@ static void start_iaa_cycle(struct ehci_
-
- /* Do only the first waiting QH (nVidia bug?) */
- qh = ehci->async_unlink;
-- ehci->async_iaa = qh;
-- ehci->async_unlink = qh->unlink_next;
-- qh->unlink_next = NULL;
-+
-+ /*
-+ * Intel (?) bug: The HC can write back the overlay region
-+ * even after the IAA interrupt occurs. In self-defense,
-+ * always go through two IAA cycles for each QH.
-+ */
-+ if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
-+ qh->qh_state = QH_STATE_UNLINK;
-+ } else {
-+ ehci->async_iaa = qh;
-+ ehci->async_unlink = qh->unlink_next;
-+ qh->unlink_next = NULL;
-+ }
-
- /* Make sure the unlinks are all visible to the hardware */
- wmb();