patch "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk" added to usb-linus
Subsystems (3)
This is a note to let you know that I've just added the patch titled
USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 5d5323a6f3625f101dbfa94ba3ef7706cce38760 Mon Sep 17 00:00:00 2001
From: Michael Grzeschik <[email protected]>
Date: Tue, 15 Dec 2020 20:31:47 +0100
Subject: USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk
set
The commit 0472bf06c6fd ("xhci: Prevent U1/U2 link pm states if exit latency is too long") was constraining the xhci code not to allow U1/U2 sleep states if the latency to wake up from the U-states reached the service interval of an periodic endpoint. This fix was not taking into account that in case the quirk XHCI_INTEL_HOST is set, the wakeup time will be calculated and configured differently.
It checks for u1_params.mel/u2_params.mel as a limit. But the code could decide to write another MEL into the hardware. This leads to broken cases where not enough bandwidth is available for other devices:
usb 1-2: can't set config #1, error -28
This patch is fixing that case by checking for timeout_ns after the wakeup time was calculated depending on the quirks.
--- drivers/usb/host/xhci.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
drivers/usb/host/xhci.c +12 -12
@@ -4770,19 +4770,19 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, {unsigned long long timeout_ns; +if (xhci->quirks &XHCI_INTEL_HOST ) + timeout_ns =xhci_calculate_intel_u1_timeout (udev, desc); +else + timeout_ns = udev->u1_params.sel; +/* Prevent U1 if service interval is shorter than U1 exit latency */ if (usb_endpoint_xfer_int (desc) ||usb_endpoint_xfer_isoc (desc)) { -if (xhci_service_interval_to_ns (desc) <= udev->u1_params.mel) { +if (xhci_service_interval_to_ns (desc) <= timeout_ns) {dev_dbg (&udev->dev,"Disable U1, ESIT shorter than exit latency\n" );return USB3_LPM_DISABLED ; } } -if (xhci->quirks &XHCI_INTEL_HOST ) - timeout_ns =xhci_calculate_intel_u1_timeout (udev, desc); -else - timeout_ns = udev->u1_params.sel; -/* The U1 timeout is encoded in 1us intervals. * Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */
@@ -4834,19 +4834,19 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, {unsigned long long timeout_ns; +if (xhci->quirks &XHCI_INTEL_HOST ) + timeout_ns =xhci_calculate_intel_u2_timeout (udev, desc); +else + timeout_ns = udev->u2_params.sel; +/* Prevent U2 if service interval is shorter than U2 exit latency */ if (usb_endpoint_xfer_int (desc) ||usb_endpoint_xfer_isoc (desc)) { -if (xhci_service_interval_to_ns (desc) <= udev->u2_params.mel) { +if (xhci_service_interval_to_ns (desc) <= timeout_ns) {dev_dbg (&udev->dev,"Disable U2, ESIT shorter than exit latency\n" );return USB3_LPM_DISABLED ; } } -if (xhci->quirks &XHCI_INTEL_HOST ) - timeout_ns =xhci_calculate_intel_u2_timeout (udev, desc); -else - timeout_ns = udev->u2_params.sel; -/* The U2 timeout is encoded in 256us intervals */ timeout_ns =DIV_ROUND_UP_ULL (timeout_ns,256 *1000 );/* If the necessary timeout value is bigger than what we can set in the
Signature · 1 line
2.29.2