]> git.ipfire.org Git - people/arne_f/kernel.git/blobdiff - drivers/usb/host/xhci.c
xhci: Prevent U1/U2 link pm states if exit latency is too long
[people/arne_f/kernel.git] / drivers / usb / host / xhci.c
index 155b36265f7ac258d53f340f993ff4ada87f55d5..930eecd864299f032b103832358d81d439db566b 100644 (file)
@@ -4381,6 +4381,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
 {
        unsigned long long timeout_ns;
 
+       /* 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) {
+                       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
@@ -4437,6 +4445,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
 {
        unsigned long long timeout_ns;
 
+       /* 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) {
+                       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