summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2023-09-18 16:10:53 +0300
committerBjorn Helgaas <bhelgaas@google.com>2026-10-15 17:55:09 -0500
commit2cbfd6c8dcfc9c5539d0ffca22b5609593f93c03 (patch)
tree8a2f09d944711b51b410232926874d4fefb869f0
parentcee9395acd8043be0644b25c34bfa86623f2b935 (diff)
downloadlinux-2cbfd6c8dcfc9c5539d0ffca22b5609593f93c03.tar.gz
linux-2cbfd6c8dcfc9c5539d0ffca22b5609593f93c03.zip
PCI/ASPM: Disable ASPM when driver requests it
PCI core/ASPM service driver allows controlling ASPM state through pci_disable_link_state() and pci_enable_link_state() API. It was decided earlier (see the Link below), to not allow ASPM changes when OS does not have control over it but only log a warning about the problem (commit 2add0ec14c25 ("PCI/ASPM: Warn when driver asks to disable ASPM, but we can't do it")). Similarly, if ASPM is not enabled through config, ASPM cannot be disabled. A number of drivers have added workarounds to force ASPM off with own writes into the Link Control Register (some even with comments explaining why PCI core does not disable it under some circumstances). According to the comments, some drivers require ASPM to be off for reliable operation. Having custom ASPM handling in drivers is problematic because the state kept in the ASPM service driver is not updated by the changes made outside the link state management API. As the first step to address this issue, make pci_disable_link_state() unconditionally disable ASPM so the motivation for drivers to come up with custom ASPM handling code is eliminated. Make pci_disable_link_state() function comment to comply kerneldoc formatting while changing the description. [bhelgaas: To take advantage of the PCI core ASPM handling, drivers that need to quirk ASPM should depend on CONFIG_PCIEASPM and have their custom ASPM code removed.] Link: https://lore.kernel.org/all/CANUX_P3F5YhbZX3WGU-j1AGpbXb_T9Bis2ErhvKkFMtDvzatVQ@mail.gmail.com/ Link: https://lore.kernel.org/all/20230511131441.45704-1-ilpo.jarvinen@linux.intel.com/ Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> [bhelgaas: extract just the aspm.c change and update commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20230918131103.24119-4-ilpo.jarvinen@linux.intel.com
-rw-r--r--drivers/pci/pcie/aspm.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 95ac34a34bd5..b039b57f8466 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1504,16 +1504,23 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked
return -EINVAL;
/*
* A driver requested that ASPM be disabled on this device, but
- * if we don't have permission to manage ASPM (e.g., on ACPI
+ * if we might not have permission to manage ASPM (e.g., on ACPI
* systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
- * the _OSC method), we can't honor that request. Windows has
- * a similar mechanism using "PciASPMOptOut", which is also
- * ignored in this situation.
+ * the _OSC method), previously we chose to not honor disable
+ * request in that case. Windows has a similar mechanism using
+ * "PciASPMOptOut", which is also ignored in this situation.
+ *
+ * Not honoring the requests to disable ASPM, however, led to
+ * drivers forcing ASPM off on their own. As such changes of ASPM
+ * state are not tracked by this service driver, the state kept here
+ * became out of sync.
+ *
+ * Therefore, honor ASPM disable requests even when OS does not have
+ * ASPM control. Plain disable for ASPM is assumed to be slightly
+ * safer than fully managing it.
*/
- if (aspm_disabled) {
- pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n");
- return -EPERM;
- }
+ if (aspm_disabled)
+ pci_warn(pdev, "OS doesn't have ASPM control, disabling ASPM anyway\n");
if (!locked)
down_read(&pci_bus_sem);
@@ -1540,13 +1547,13 @@ int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
EXPORT_SYMBOL(pci_disable_link_state_locked);
/**
- * pci_disable_link_state - Disable device's link state, so the link will
- * never enter specific states. Note that if the BIOS didn't grant ASPM
- * control to the OS, this does nothing because we can't touch the LNKCTL
- * register. Returns 0 or a negative errno.
- *
+ * pci_disable_link_state - Disable device's link state
* @pdev: PCI device
* @state: ASPM link state to disable
+ *
+ * Disable device's link state so the link will never enter specific states.
+ *
+ * Return: 0 or a negative errno
*/
int pci_disable_link_state(struct pci_dev *pdev, int state)
{