aboutsummaryrefslogtreecommitdiffstats
path: root/usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch
diff options
Diffstat (limited to 'usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch')
-rw-r--r--usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch57
1 files changed, 57 insertions, 0 deletions
diff --git a/usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch b/usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch
new file mode 100644
index 00000000000000..b655843c2ff33d
--- /dev/null
+++ b/usb.current/usb-xhci-fix-another-bug-in-link-trb-activation-change.patch
@@ -0,0 +1,57 @@
+From sarah.a.sharp@linux.intel.com Fri Jul 9 14:32:26 2010
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 9 Jul 2010 17:08:38 +0200
+Subject: USB: xHCI: Fix another bug in link TRB activation change.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Fajun Chen <fajun.chen@seagate.com>
+Message-ID: <20100709150837.GA2987@xanatos>
+Content-Disposition: inline
+
+
+Commit 6c12db90f19727c76990e7f4801c67a148b30111 also seems to have
+introduced a bug that is triggered when the command ring is about to wrap.
+The inc_enq() function will not have moved the enqueue pointer past the
+link TRB. It is supposed to be moved past the link TRB in prepare_ring(),
+which should be called before a TD is enqueued. However, the
+queue_command() function never calls the prepare_ring() function because
+prepare_ring() is only supposed to be used for endpoint rings. That means
+the enqueue pointer will not be moved past the link TRB, and will get
+overwritten.
+
+The fix is to make queue_command() call prepare_ring() with a fake
+endpoint status (set to running). Then the enqueue pointer will get moved
+past the link TRB.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2380,16 +2380,19 @@ static int queue_command(struct xhci_hcd
+ u32 field3, u32 field4, bool command_must_succeed)
+ {
+ int reserved_trbs = xhci->cmd_ring_reserved_trbs;
++ int ret;
++
+ if (!command_must_succeed)
+ reserved_trbs++;
+
+- if (!room_on_ring(xhci, xhci->cmd_ring, reserved_trbs)) {
+- if (!in_interrupt())
+- xhci_err(xhci, "ERR: No room for command on command ring\n");
++ ret = prepare_ring(xhci, xhci->cmd_ring, EP_STATE_RUNNING,
++ reserved_trbs, GFP_ATOMIC);
++ if (ret < 0) {
++ xhci_err(xhci, "ERR: No room for command on command ring\n");
+ if (command_must_succeed)
+ xhci_err(xhci, "ERR: Reserved TRB counting for "
+ "unfailable commands failed.\n");
+- return -ENOMEM;
++ return ret;
+ }
+ queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
+ field4 | xhci->cmd_ring->cycle_state);