diff options
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
| -rw-r--r-- | drivers/pci/pcie/aspm.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 8474b6a4fc9..e1e7026b838 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -548,7 +548,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) /* * pcie_aspm_init_link_state: Initiate PCI express link state. - * It is called after the pcie and its children devices are scaned. + * It is called after the pcie and its children devices are scanned. * @pdev: the root port or switch downstream port */ void pcie_aspm_init_link_state(struct pci_dev *pdev) @@ -556,6 +556,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) struct pcie_link_state *link; int blacklist = !!pcie_aspm_sanity_check(pdev); + if (!aspm_support_enabled) + return; + if (!pci_is_pcie(pdev) || pdev->link_state) return; if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && @@ -634,10 +637,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link, *root, *parent_link; - if (!pci_is_pcie(pdev) || !parent || !parent->link_state) - return; - if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) && - (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)) + if (!parent || !parent->link_state) return; down_read(&pci_bus_sem); @@ -714,19 +714,12 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) up_read(&pci_bus_sem); } -/* - * pci_disable_link_state - disable pci device's link state, so the link will - * never enter specific states - */ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, bool force) { struct pci_dev *parent = pdev->bus->self; struct pcie_link_state *link; - if (aspm_disabled && !force) - return; - if (!pci_is_pcie(pdev)) return; @@ -736,6 +729,19 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, if (!parent || !parent->link_state) return; + /* + * A driver requested that ASPM be disabled on this device, but + * if we don't 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. + */ + if (aspm_disabled && !force) { + dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n"); + return; + } + if (sem) down_read(&pci_bus_sem); mutex_lock(&aspm_lock); @@ -761,6 +767,15 @@ void 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. + * + * @pdev: PCI device + * @state: ASPM link state to disable + */ void pci_disable_link_state(struct pci_dev *pdev, int state) { __pci_disable_link_state(pdev, state, true, false); @@ -969,18 +984,6 @@ void pcie_no_aspm(void) } } -/** - * pcie_aspm_enabled - is PCIe ASPM enabled? - * - * Returns true if ASPM has not been disabled by the command-line option - * pcie_aspm=off. - **/ -int pcie_aspm_enabled(void) -{ - return !aspm_disabled; -} -EXPORT_SYMBOL(pcie_aspm_enabled); - bool pcie_aspm_support_enabled(void) { return aspm_support_enabled; |
