diff options
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/Kconfig | 20 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 17 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 16 | ||||
-rw-r--r-- | drivers/pci/pcie/pme/pcie_pme.c | 5 |
4 files changed, 41 insertions, 17 deletions
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index b8b494b3e0d..dda70981b7a 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -31,14 +31,22 @@ source "drivers/pci/pcie/aer/Kconfig" # PCI Express ASPM # config PCIEASPM - bool "PCI Express ASPM support(Experimental)" - depends on PCI && EXPERIMENTAL && PCIEPORTBUS - default n + bool "PCI Express ASPM control" if EMBEDDED + depends on PCI && PCIEPORTBUS + default y help - This enables PCI Express ASPM (Active State Power Management) and - Clock Power Management. ASPM supports state L0/L0s/L1. + This enables OS control over PCI Express ASPM (Active State + Power Management) and Clock Power Management. ASPM supports + state L0/L0s/L1. - When in doubt, say N. + ASPM is initially set up the the firmware. With this option enabled, + Linux can modify this state in order to disable ASPM on known-bad + hardware or configurations and enable it when known-safe. + + ASPM can be disabled or enabled at runtime via + /sys/module/pcie_aspm/parameters/policy + + When in doubt, say Y. config PCIEASPM_DEBUG bool "Debug PCI Express ASPM" depends on PCIEASPM diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 8af4f619bba..fc0b5a93e1d 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -727,20 +727,21 @@ static void aer_isr_one_error(struct pcie_device *p_device, static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) { unsigned long flags; - int ret = 0; /* Lock access to Root error producer/consumer index */ spin_lock_irqsave(&rpc->e_lock, flags); - if (rpc->prod_idx != rpc->cons_idx) { - *e_src = rpc->e_sources[rpc->cons_idx]; - rpc->cons_idx++; - if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) - rpc->cons_idx = 0; - ret = 1; + if (rpc->prod_idx == rpc->cons_idx) { + spin_unlock_irqrestore(&rpc->e_lock, flags); + return 0; } + + *e_src = rpc->e_sources[rpc->cons_idx]; + rpc->cons_idx++; + if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) + rpc->cons_idx = 0; spin_unlock_irqrestore(&rpc->e_lock, flags); - return ret; + return 1; } /** diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index be53d98fa38..71222814c1e 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -588,11 +588,23 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) * update through pcie_aspm_cap_init(). */ pcie_aspm_cap_init(link, blacklist); - pcie_config_aspm_path(link); /* Setup initial Clock PM state */ pcie_clkpm_cap_init(link, blacklist); - pcie_set_clkpm(link, policy_to_clkpm_state(link)); + + /* + * At this stage drivers haven't had an opportunity to change the + * link policy setting. Enabling ASPM on broken hardware can cripple + * it even before the driver has had a chance to disable ASPM, so + * default to a safe level right now. If we're enabling ASPM beyond + * the BIOS's expectation, we'll do so once pci_enable_device() is + * called. + */ + if (aspm_policy != POLICY_POWERSAVE) { + pcie_config_aspm_path(link); + pcie_set_clkpm(link, policy_to_clkpm_state(link)); + } + unlock: mutex_unlock(&aspm_lock); out: diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c index d672a0a6381..bbdea18693d 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme/pcie_pme.c @@ -154,6 +154,7 @@ static bool pcie_pme_walk_bus(struct pci_bus *bus) /* Skip PCIe devices in case we started from a root port. */ if (!pci_is_pcie(dev) && pci_check_pme_status(dev)) { pm_request_resume(&dev->dev); + pci_wakeup_event(dev); ret = true; } @@ -254,8 +255,10 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id) if (found) { /* The device is there, but we have to check its PME status. */ found = pci_check_pme_status(dev); - if (found) + if (found) { pm_request_resume(&dev->dev); + pci_wakeup_event(dev); + } pci_dev_put(dev); } else if (devfn) { /* |