From: Mathias Nyman Date: Mon, 16 Jan 2023 14:22:16 +0000 (+0200) Subject: xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables X-Git-Tag: v6.6.17~5713^2~20 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=74622f0a81d0c2bcfc39f9192b788124e8c7f0af;p=platform%2Fkernel%2Flinux-rpi.git xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables USB3 ports on xHC hosts may have retimers that cause too long exit latency to work with native USB3 U1/U2 link power management states. For now only use usb_acpi_port_lpm_incapable() to evaluate if port lpm should be disabled while setting up the USB3 roothub. Other ways to identify lpm incapable ports can be added here later if ACPI _DSM does not exist. Limit this to Intel hosts for now, this is to my knowledge only an Intel issue. Cc: stable@vger.kernel.org Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20230116142216.1141605-8-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b501670..fb988e4 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -355,8 +355,38 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) NULL); ACPI_FREE(obj); } + +static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct xhci_hub *rhub = &xhci->usb3_rhub; + int ret; + int i; + + /* This is not the usb3 roothub we are looking for */ + if (hcd != rhub->hcd) + return; + + if (hdev->maxchild > rhub->num_ports) { + dev_err(&hdev->dev, "USB3 roothub port number mismatch\n"); + return; + } + + for (i = 0; i < hdev->maxchild; i++) { + ret = usb_acpi_port_lpm_incapable(hdev, i); + + dev_dbg(&hdev->dev, "port-%d disable U1/U2 _DSM: %d\n", i + 1, ret); + + if (ret >= 0) { + rhub->ports[i]->lpm_incapable = ret; + continue; + } + } +} + #else static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } +static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) { } #endif /* CONFIG_ACPI */ /* called during probe() after chip reset completes */ @@ -392,6 +422,10 @@ static int xhci_pci_setup(struct usb_hcd *hcd) static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags) { + /* Check if acpi claims some USB3 roothub ports are lpm incapable */ + if (!hdev->parent) + xhci_find_lpm_incapable_ports(hcd, hdev); + return xhci_update_hub_device(hcd, hdev, tt, mem_flags); }