summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2019-06-18 17:27:47 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-06-25 06:35:53 +0300
commit17027034a47bda8a8fc96f2875ff19062c90e18c (patch)
treec63e604bb4b9d71b71de3a402b1791eeb6378049 /drivers/usb/host/xhci.c
parentd606a82ccc0a7c7244b26698bef35b47cce9666c (diff)
downloadlinux-17027034a47bda8a8fc96f2875ff19062c90e18c.tar.xz
usb: xhci: Don't try to recover an endpoint if port is in error state.
commit b8c3b718087bf7c3c8e388eb1f72ac1108a4926e upstream. A USB3 device needs to be reset and re-enumarated if the port it connects to goes to a error state, with link state inactive. There is no use in trying to recover failed transactions by resetting endpoints at this stage. Tests show that in rare cases, after multiple endpoint resets of a roothub port the whole host controller might stop completely. Several retries to recover from transaction error can happen as it can take a long time before the hub thread discovers the USB3 port error and inactive link. We can't reliably detect the port error from slot or endpoint context due to a limitation in xhci, see xhci specs section 4.8.3: "There are several cases where the EP State field in the Output Endpoint Context may not reflect the current state of an endpoint" and "Software should maintain an accurate value for EP State, by tracking it with an internal variable that is driven by Events and Doorbell accesses" Same appears to be true for slot state. set a flag to the corresponding slot if a USB3 roothub port link goes inactive to prevent both queueing new URBs and resetting endpoints. Reported-by: Rapolu Chiranjeevi <chiranjeevi.rapolu@intel.com> Tested-by: Rapolu Chiranjeevi <chiranjeevi.rapolu@intel.com> Cc: <stable@vger.kernel.org> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 71cf35eeb186..4ffadca2c71a 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1441,6 +1441,10 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
xhci_dbg(xhci, "urb submitted during PCI suspend\n");
return -ESHUTDOWN;
}
+ if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) {
+ xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n");
+ return -ENODEV;
+ }
if (usb_endpoint_xfer_isoc(&urb->ep->desc))
num_tds = urb->number_of_packets;
@@ -3724,6 +3728,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
}
/* If necessary, update the number of active TTs on this root port */
xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps);
+ virt_dev->flags = 0;
ret = 0;
command_cleanup: