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 <patrick.rudolph@9elements.com>
This commit is contained in:
Patrick Rudolph
2020-11-05 10:08:16 +01:00
committed by Jeremy Soller
parent d13acd817d
commit 417fa84913

View File

@@ -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;