]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.38.8/xhci-fix-bug-in-control-transfer-cancellation.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.38.8 / xhci-fix-bug-in-control-transfer-cancellation.patch
1 From 3abeca998a44205cfd837fa0bf1f7c24f8294acb Mon Sep 17 00:00:00 2001
2 From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
3 Date: Thu, 5 May 2011 19:08:09 -0700
4 Subject: xhci: Fix bug in control transfer cancellation.
5
6 From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
7
8 commit 3abeca998a44205cfd837fa0bf1f7c24f8294acb upstream.
9
10 When the xHCI driver attempts to cancel a transfer, it issues a Stop
11 Endpoint command and waits for the host controller to indicate which TRB
12 it was in the middle of processing. The host will put an event TRB with
13 completion code COMP_STOP on the event ring if it stops on a control
14 transfer TRB (or other types of transfer TRBs). The ring handling code
15 is supposed to set ep->stopped_trb to the TRB that the host stopped on
16 when this happens.
17
18 Unfortunately, there is a long-standing bug in the control transfer
19 completion code. It doesn't actually check to see if COMP_STOP is set
20 before attempting to process the transfer based on which part of the
21 control TD completed. So when we get an event on the data phase of the
22 control TRB with COMP_STOP set, it thinks it's a normal completion of
23 the transfer and doesn't set ep->stopped_td or ep->stopped_trb.
24
25 When the ring handling code goes on to process the completion of the Stop
26 Endpoint command, it sees that ep->stopped_trb is not a part of the TD
27 it's trying to cancel. It thinks the hardware has its enqueue pointer
28 somewhere further up in the ring, and thinks it's safe to turn the control
29 TRBs into no-op TRBs. Since the hardware was in the middle of the control
30 TRBs to be cancelled, the proper software behavior is to issue a Set TR
31 dequeue pointer command.
32
33 It turns out that the NEC host controllers can handle active TRBs being
34 set to no-op TRBs after a stop endpoint command, but other host
35 controllers have issues with this out-of-spec software behavior. Fix this
36 behavior.
37
38 This patch should be backported to kernels as far back as 2.6.31, but it
39 may be a bit challenging, since process_ctrl_td() was introduced in some
40 refactoring done in 2.6.36, and some endian-safe patches added in 2.6.40
41 that touch the same lines.
42
43 Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
44 Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
45 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
46
47 ---
48 drivers/usb/host/xhci-ring.c | 18 +++++++++---------
49 1 file changed, 9 insertions(+), 9 deletions(-)
50
51 --- a/drivers/usb/host/xhci-ring.c
52 +++ b/drivers/usb/host/xhci-ring.c
53 @@ -1532,6 +1532,9 @@ static int process_ctrl_td(struct xhci_h
54 else
55 *status = 0;
56 break;
57 + case COMP_STOP_INVAL:
58 + case COMP_STOP:
59 + return finish_td(xhci, td, event_trb, event, ep, status, false);
60 default:
61 if (!xhci_requires_manual_halt_cleanup(xhci,
62 ep_ctx, trb_comp_code))
63 @@ -1576,15 +1579,12 @@ static int process_ctrl_td(struct xhci_h
64 }
65 } else {
66 /* Maybe the event was for the data stage? */
67 - if (trb_comp_code != COMP_STOP_INVAL) {
68 - /* We didn't stop on a link TRB in the middle */
69 - td->urb->actual_length =
70 - td->urb->transfer_buffer_length -
71 - TRB_LEN(event->transfer_len);
72 - xhci_dbg(xhci, "Waiting for status "
73 - "stage event\n");
74 - return 0;
75 - }
76 + td->urb->actual_length =
77 + td->urb->transfer_buffer_length -
78 + TRB_LEN(le32_to_cpu(event->transfer_len));
79 + xhci_dbg(xhci, "Waiting for status "
80 + "stage event\n");
81 + return 0;
82 }
83 }
84