]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch
4.19-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.19 / usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch
1 From b8c3b718087bf7c3c8e388eb1f72ac1108a4926e Mon Sep 17 00:00:00 2001
2 From: Mathias Nyman <mathias.nyman@linux.intel.com>
3 Date: Tue, 18 Jun 2019 17:27:47 +0300
4 Subject: usb: xhci: Don't try to recover an endpoint if port is in error state.
5
6 From: Mathias Nyman <mathias.nyman@linux.intel.com>
7
8 commit b8c3b718087bf7c3c8e388eb1f72ac1108a4926e upstream.
9
10 A USB3 device needs to be reset and re-enumarated if the port it
11 connects to goes to a error state, with link state inactive.
12
13 There is no use in trying to recover failed transactions by resetting
14 endpoints at this stage. Tests show that in rare cases, after multiple
15 endpoint resets of a roothub port the whole host controller might stop
16 completely.
17
18 Several retries to recover from transaction error can happen as
19 it can take a long time before the hub thread discovers the USB3
20 port error and inactive link.
21
22 We can't reliably detect the port error from slot or endpoint context
23 due to a limitation in xhci, see xhci specs section 4.8.3:
24 "There are several cases where the EP State field in the Output
25 Endpoint Context may not reflect the current state of an endpoint"
26 and
27 "Software should maintain an accurate value for EP State, by tracking it
28 with an internal variable that is driven by Events and Doorbell accesses"
29
30 Same appears to be true for slot state.
31
32 set a flag to the corresponding slot if a USB3 roothub port link goes
33 inactive to prevent both queueing new URBs and resetting endpoints.
34
35 Reported-by: Rapolu Chiranjeevi <chiranjeevi.rapolu@intel.com>
36 Tested-by: Rapolu Chiranjeevi <chiranjeevi.rapolu@intel.com>
37 Cc: <stable@vger.kernel.org>
38 Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41
42 ---
43 drivers/usb/host/xhci-ring.c | 15 ++++++++++++++-
44 drivers/usb/host/xhci.c | 5 +++++
45 drivers/usb/host/xhci.h | 9 +++++++++
46 3 files changed, 28 insertions(+), 1 deletion(-)
47
48 --- a/drivers/usb/host/xhci-ring.c
49 +++ b/drivers/usb/host/xhci-ring.c
50 @@ -1604,8 +1604,13 @@ static void handle_port_status(struct xh
51 usb_hcd_resume_root_hub(hcd);
52 }
53
54 - if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE)
55 + if (hcd->speed >= HCD_USB3 &&
56 + (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
57 + slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
58 + if (slot_id && xhci->devs[slot_id])
59 + xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
60 bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
61 + }
62
63 if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
64 xhci_dbg(xhci, "port resume event for port %d\n", port_id);
65 @@ -1793,6 +1798,14 @@ static void xhci_cleanup_halted_endpoint
66 {
67 struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
68 struct xhci_command *command;
69 +
70 + /*
71 + * Avoid resetting endpoint if link is inactive. Can cause host hang.
72 + * Device will be reset soon to recover the link so don't do anything
73 + */
74 + if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR)
75 + return;
76 +
77 command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
78 if (!command)
79 return;
80 --- a/drivers/usb/host/xhci.c
81 +++ b/drivers/usb/host/xhci.c
82 @@ -1441,6 +1441,10 @@ static int xhci_urb_enqueue(struct usb_h
83 xhci_dbg(xhci, "urb submitted during PCI suspend\n");
84 return -ESHUTDOWN;
85 }
86 + if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) {
87 + xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n");
88 + return -ENODEV;
89 + }
90
91 if (usb_endpoint_xfer_isoc(&urb->ep->desc))
92 num_tds = urb->number_of_packets;
93 @@ -3724,6 +3728,7 @@ static int xhci_discover_or_reset_device
94 }
95 /* If necessary, update the number of active TTs on this root port */
96 xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps);
97 + virt_dev->flags = 0;
98 ret = 0;
99
100 command_cleanup:
101 --- a/drivers/usb/host/xhci.h
102 +++ b/drivers/usb/host/xhci.h
103 @@ -1010,6 +1010,15 @@ struct xhci_virt_device {
104 u8 real_port;
105 struct xhci_interval_bw_table *bw_table;
106 struct xhci_tt_bw_info *tt_info;
107 + /*
108 + * flags for state tracking based on events and issued commands.
109 + * Software can not rely on states from output contexts because of
110 + * latency between events and xHC updating output context values.
111 + * See xhci 1.1 section 4.8.3 for more details
112 + */
113 + unsigned long flags;
114 +#define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */
115 +
116 /* The current max exit latency for the enabled USB3 link states. */
117 u16 current_mel;
118 /* Used for the debugfs interfaces. */