xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables

commit 74622f0a81 upstream.

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 <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20230116142216.1141605-8-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Mathias Nyman 2023-01-16 16:22:16 +02:00 коммит произвёл Greg Kroah-Hartman
Родитель 10cb7d53be
Коммит 418e2c756d
1 изменённых файлов: 34 добавлений и 0 удалений

Просмотреть файл

@ -356,8 +356,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 */
@ -393,6 +423,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);
}