From: Greg Kroah-Hartman Date: Wed, 20 Mar 2013 20:43:28 +0000 (-0700) Subject: 3.8-stable patches X-Git-Tag: v3.0.71~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5f71c6e4a2f29033030b91d57416374038ea6142;p=thirdparty%2Fkernel%2Fstable-queue.git 3.8-stable patches added patches: usb-ehci-work-around-silicon-bug-in-intel-s-ehci-controllers.patch --- diff --git a/queue-3.8/series b/queue-3.8/series new file mode 100644 index 00000000000..533e19574b2 --- /dev/null +++ b/queue-3.8/series @@ -0,0 +1 @@ +usb-ehci-work-around-silicon-bug-in-intel-s-ehci-controllers.patch diff --git a/queue-3.8/usb-ehci-work-around-silicon-bug-in-intel-s-ehci-controllers.patch b/queue-3.8/usb-ehci-work-around-silicon-bug-in-intel-s-ehci-controllers.patch new file mode 100644 index 00000000000..d61bc393891 --- /dev/null +++ b/queue-3.8/usb-ehci-work-around-silicon-bug-in-intel-s-ehci-controllers.patch @@ -0,0 +1,95 @@ +From 6402c796d3b4205d3d7296157956c5100a05d7d6 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 1 Mar 2013 10:50:08 -0500 +Subject: USB: EHCI: work around silicon bug in Intel's EHCI controllers + +From: Alan Stern + +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 +Tested-by: Stephen Thirlwall +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -1178,7 +1178,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 +@@ -1221,9 +1221,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();