]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.4.65/xhci-ensure-a-command-structure-points-to-the-correct-trb-on-the-command-ring.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.65 / xhci-ensure-a-command-structure-points-to-the-correct-trb-on-the-command-ring.patch
CommitLineData
b2758999
GKH
1From ec7e43e2d98173483866fe2e4e690143626b659c Mon Sep 17 00:00:00 2001
2From: Mathias Nyman <mathias.nyman@linux.intel.com>
3Date: Fri, 30 Aug 2013 18:25:49 +0300
4Subject: xhci: Ensure a command structure points to the correct trb on the command ring
5
6From: Mathias Nyman <mathias.nyman@linux.intel.com>
7
8commit ec7e43e2d98173483866fe2e4e690143626b659c upstream.
9
10If a command on the command ring needs to be cancelled before it is handled
11it can be turned to a no-op operation when the ring is stopped.
12We want to store the command ring enqueue pointer in the command structure
13when the command in enqueued for the cancellation case.
14
15Some commands used to store the command ring dequeue pointers instead of enqueue
16(these often worked because enqueue happends to equal dequeue quite often)
17
18Other commands correctly used the enqueue pointer but did not check if it pointed
19to a valid trb or a link trb, this caused for example stop endpoint command to timeout in
20xhci_stop_device() in about 2% of suspend/resume cases.
21
22This should also solve some weird behavior happening in command cancellation cases.
23
24This patch is based on a patch submitted by Sarah Sharp to linux-usb, but
25then forgotten:
26 http://marc.info/?l=linux-usb&m=136269803207465&w=2
27
28This patch should be backported to kernels as old as 3.7, that contain
29the commit b92cc66c047ff7cf587b318fe377061a353c120f "xHCI: add aborting
30command ring function"
31
32Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
33Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
34Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35
36---
37 drivers/usb/host/xhci-hub.c | 2 +-
38 drivers/usb/host/xhci-ring.c | 10 ++++++++++
39 drivers/usb/host/xhci.c | 25 +++++--------------------
40 drivers/usb/host/xhci.h | 1 +
41 4 files changed, 17 insertions(+), 21 deletions(-)
42
43--- a/drivers/usb/host/xhci-hub.c
44+++ b/drivers/usb/host/xhci-hub.c
45@@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_
46 if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
47 xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
48 }
49- cmd->command_trb = xhci->cmd_ring->enqueue;
50+ cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
51 list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
52 xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
53 xhci_ring_cmd_db(xhci);
54--- a/drivers/usb/host/xhci-ring.c
55+++ b/drivers/usb/host/xhci-ring.c
56@@ -122,6 +122,16 @@ static int enqueue_is_link_trb(struct xh
57 return TRB_TYPE_LINK_LE32(link->control);
58 }
59
60+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
61+{
62+ /* Enqueue pointer can be left pointing to the link TRB,
63+ * we must handle that
64+ */
65+ if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
66+ return ring->enq_seg->next->trbs;
67+ return ring->enqueue;
68+}
69+
70 /* Updates trb to point to the next TRB in the ring, and updates seg if the next
71 * TRB is in a new segment. This does not skip over link TRBs, and it does not
72 * effect the ring dequeue or enqueue pointers.
73--- a/drivers/usb/host/xhci.c
74+++ b/drivers/usb/host/xhci.c
75@@ -2582,15 +2582,7 @@ static int xhci_configure_endpoint(struc
76 if (command) {
77 cmd_completion = command->completion;
78 cmd_status = &command->status;
79- command->command_trb = xhci->cmd_ring->enqueue;
80-
81- /* Enqueue pointer can be left pointing to the link TRB,
82- * we must handle that
83- */
84- if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
85- command->command_trb =
86- xhci->cmd_ring->enq_seg->next->trbs;
87-
88+ command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
89 list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
90 } else {
91 cmd_completion = &virt_dev->cmd_completion;
92@@ -2598,7 +2590,7 @@ static int xhci_configure_endpoint(struc
93 }
94 init_completion(cmd_completion);
95
96- cmd_trb = xhci->cmd_ring->dequeue;
97+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
98 if (!ctx_change)
99 ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
100 udev->slot_id, must_succeed);
101@@ -3383,14 +3375,7 @@ int xhci_discover_or_reset_device(struct
102
103 /* Attempt to submit the Reset Device command to the command ring */
104 spin_lock_irqsave(&xhci->lock, flags);
105- reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
106-
107- /* Enqueue pointer can be left pointing to the link TRB,
108- * we must handle that
109- */
110- if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
111- reset_device_cmd->command_trb =
112- xhci->cmd_ring->enq_seg->next->trbs;
113+ reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
114
115 list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
116 ret = xhci_queue_reset_device(xhci, slot_id);
117@@ -3594,7 +3579,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd,
118 union xhci_trb *cmd_trb;
119
120 spin_lock_irqsave(&xhci->lock, flags);
121- cmd_trb = xhci->cmd_ring->dequeue;
122+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
123 ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
124 if (ret) {
125 spin_unlock_irqrestore(&xhci->lock, flags);
126@@ -3721,7 +3706,7 @@ int xhci_address_device(struct usb_hcd *
127 xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
128
129 spin_lock_irqsave(&xhci->lock, flags);
130- cmd_trb = xhci->cmd_ring->dequeue;
131+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
132 ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
133 udev->slot_id);
134 if (ret) {
135--- a/drivers/usb/host/xhci.h
136+++ b/drivers/usb/host/xhci.h
137@@ -1811,6 +1811,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhc
138 union xhci_trb *cmd_trb);
139 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
140 unsigned int ep_index, unsigned int stream_id);
141+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
142
143 /* xHCI roothub code */
144 void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,