From 417fa84913a7d3d29037b7230af1720cfce6a6df Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Thu, 5 Nov 2020 10:08:16 +0100 Subject: [PATCH] device/pciexp: Allow ASPM on bridge devices The device acceptable latency field is only valid for 'endpoints', but not for bridge devices. Set the maximum acceptable latency on such devices to allow ASPM being enabled if supported on both sides. Allows the PCIe link on bridge devices to go into L0s/L1. This allows the package to enter a deeper sleep state when all links are idle. WARNING: This might cause issues on PCIe bridge devices that doesn't properly support ASPM. In addition it might decrease performance. Change-Id: I277efe0bd1448ee8bff633428aa729aeedf04e28 Signed-off-by: Patrick Rudolph --- src/device/pciexp_device.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/device/pciexp_device.c b/src/device/pciexp_device.c index 8f721071c9..1894e7d6ce 100644 --- a/src/device/pciexp_device.c +++ b/src/device/pciexp_device.c @@ -368,8 +368,20 @@ static void pciexp_enable_aspm(struct device *root, unsigned int root_cap, if (endp->disable_pcie_aspm) return; - /* Get endpoint device capabilities for acceptable limits */ - devcap = pci_read_config32(endp, endp_cap + PCI_EXP_DEVCAP); + const uint16_t xcap = pci_read_config16(endp, endp_cap + PCI_EXP_FLAGS); + const uint8_t type = (xcap & PCI_EXP_FLAGS_TYPE) >> 4; + + /* + * PCI_EXP_DEVCAP_L0S and PCI_EXP_DEVCAP_L1 are only valid for PCIe endpoints. + * Refer to "PCI Express Base Specification Revision 2.0" Chapter 7.8.3 + */ + if (type != PCI_EXP_TYPE_ENDPOINT && type != PCI_EXP_TYPE_LEG_END) { + /* Set no limit in acceptable latency */ + devcap = (0x7 << 6) | (0x7 << 9); + } else { + /* Get endpoint device capabilities for acceptable limits */ + devcap = pci_read_config32(endp, endp_cap + PCI_EXP_DEVCAP); + } /* Enable L0s if it is within endpoint acceptable limit */ ok_latency = (devcap & PCI_EXP_DEVCAP_L0S) >> 6;