Loading drivers/pci/pci-driver.c +2 −0 Original line number Diff line number Diff line Loading @@ -511,6 +511,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) } pci_restore_state(pci_dev); pci_pme_restore(pci_dev); return 0; } Loading @@ -522,6 +523,7 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev) { pci_power_up(pci_dev); pci_restore_state(pci_dev); pci_pme_restore(pci_dev); pci_fixup_device(pci_fixup_resume_early, pci_dev); } Loading drivers/pci/pci.c +8 −8 Original line number Diff line number Diff line Loading @@ -1801,7 +1801,11 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); } static void pci_pme_restore(struct pci_dev *dev) /** * pci_pme_restore - Restore PME configuration after config space restore. * @dev: PCI device to update. */ void pci_pme_restore(struct pci_dev *dev) { u16 pmcsr; Loading @@ -1811,6 +1815,7 @@ static void pci_pme_restore(struct pci_dev *dev) pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); if (dev->wakeup_prepared) { pmcsr |= PCI_PM_CTRL_PME_ENABLE; pmcsr &= ~PCI_PM_CTRL_PME_STATUS; } else { pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; pmcsr |= PCI_PM_CTRL_PME_STATUS; Loading Loading @@ -1907,14 +1912,9 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) { int ret = 0; /* * Don't do the same thing twice in a row for one device, but restore * PME Enable in case it has been updated by config space restoration. */ if (!!enable == !!dev->wakeup_prepared) { pci_pme_restore(dev); /* Don't do the same thing twice in a row for one device. */ if (!!enable == !!dev->wakeup_prepared) return 0; } /* * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don Loading drivers/pci/pci.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ void pci_power_up(struct pci_dev *dev); void pci_disable_enabled_device(struct pci_dev *dev); int pci_finish_runtime_suspend(struct pci_dev *dev); int __pci_pme_wakeup(struct pci_dev *dev, void *ign); void pci_pme_restore(struct pci_dev *dev); bool pci_dev_keep_suspended(struct pci_dev *dev); void pci_dev_complete_resume(struct pci_dev *pci_dev); void pci_config_pm_runtime_get(struct pci_dev *dev); Loading drivers/pci/pcie/pme.c +13 −22 Original line number Diff line number Diff line Loading @@ -40,17 +40,11 @@ static int __init pcie_pme_setup(char *str) } __setup("pcie_pme=", pcie_pme_setup); enum pme_suspend_level { PME_SUSPEND_NONE = 0, PME_SUSPEND_WAKEUP, PME_SUSPEND_NOIRQ, }; struct pcie_pme_service_data { spinlock_t lock; struct pcie_device *srv; struct work_struct work; enum pme_suspend_level suspend_level; bool noirq; /* If set, keep the PME interrupt disabled. */ }; /** Loading Loading @@ -228,7 +222,7 @@ static void pcie_pme_work_fn(struct work_struct *work) spin_lock_irq(&data->lock); for (;;) { if (data->suspend_level != PME_SUSPEND_NONE) if (data->noirq) break; pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); Loading @@ -255,7 +249,7 @@ static void pcie_pme_work_fn(struct work_struct *work) spin_lock_irq(&data->lock); } if (data->suspend_level == PME_SUSPEND_NONE) if (!data->noirq) pcie_pme_interrupt_enable(port, true); spin_unlock_irq(&data->lock); Loading Loading @@ -378,7 +372,7 @@ static int pcie_pme_suspend(struct pcie_device *srv) { struct pcie_pme_service_data *data = get_service_data(srv); struct pci_dev *port = srv->port; bool wakeup, wake_irq_enabled = false; bool wakeup; int ret; if (device_may_wakeup(&port->dev)) { Loading @@ -388,19 +382,16 @@ static int pcie_pme_suspend(struct pcie_device *srv) wakeup = pcie_pme_check_wakeup(port->subordinate); up_read(&pci_bus_sem); } spin_lock_irq(&data->lock); if (wakeup) { ret = enable_irq_wake(srv->irq); if (ret == 0) { data->suspend_level = PME_SUSPEND_WAKEUP; wake_irq_enabled = true; } if (!ret) return 0; } if (!wake_irq_enabled) { spin_lock_irq(&data->lock); pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; } data->noirq = true; spin_unlock_irq(&data->lock); synchronize_irq(srv->irq); Loading @@ -417,15 +408,15 @@ static int pcie_pme_resume(struct pcie_device *srv) struct pcie_pme_service_data *data = get_service_data(srv); spin_lock_irq(&data->lock); if (data->suspend_level == PME_SUSPEND_NOIRQ) { if (data->noirq) { struct pci_dev *port = srv->port; pcie_clear_root_pme_status(port); pcie_pme_interrupt_enable(port, true); data->noirq = false; } else { disable_irq_wake(srv->irq); } data->suspend_level = PME_SUSPEND_NONE; spin_unlock_irq(&data->lock); return 0; Loading Loading
drivers/pci/pci-driver.c +2 −0 Original line number Diff line number Diff line Loading @@ -511,6 +511,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev) } pci_restore_state(pci_dev); pci_pme_restore(pci_dev); return 0; } Loading @@ -522,6 +523,7 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev) { pci_power_up(pci_dev); pci_restore_state(pci_dev); pci_pme_restore(pci_dev); pci_fixup_device(pci_fixup_resume_early, pci_dev); } Loading
drivers/pci/pci.c +8 −8 Original line number Diff line number Diff line Loading @@ -1801,7 +1801,11 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); } static void pci_pme_restore(struct pci_dev *dev) /** * pci_pme_restore - Restore PME configuration after config space restore. * @dev: PCI device to update. */ void pci_pme_restore(struct pci_dev *dev) { u16 pmcsr; Loading @@ -1811,6 +1815,7 @@ static void pci_pme_restore(struct pci_dev *dev) pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); if (dev->wakeup_prepared) { pmcsr |= PCI_PM_CTRL_PME_ENABLE; pmcsr &= ~PCI_PM_CTRL_PME_STATUS; } else { pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; pmcsr |= PCI_PM_CTRL_PME_STATUS; Loading Loading @@ -1907,14 +1912,9 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) { int ret = 0; /* * Don't do the same thing twice in a row for one device, but restore * PME Enable in case it has been updated by config space restoration. */ if (!!enable == !!dev->wakeup_prepared) { pci_pme_restore(dev); /* Don't do the same thing twice in a row for one device. */ if (!!enable == !!dev->wakeup_prepared) return 0; } /* * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don Loading
drivers/pci/pci.h +1 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ void pci_power_up(struct pci_dev *dev); void pci_disable_enabled_device(struct pci_dev *dev); int pci_finish_runtime_suspend(struct pci_dev *dev); int __pci_pme_wakeup(struct pci_dev *dev, void *ign); void pci_pme_restore(struct pci_dev *dev); bool pci_dev_keep_suspended(struct pci_dev *dev); void pci_dev_complete_resume(struct pci_dev *pci_dev); void pci_config_pm_runtime_get(struct pci_dev *dev); Loading
drivers/pci/pcie/pme.c +13 −22 Original line number Diff line number Diff line Loading @@ -40,17 +40,11 @@ static int __init pcie_pme_setup(char *str) } __setup("pcie_pme=", pcie_pme_setup); enum pme_suspend_level { PME_SUSPEND_NONE = 0, PME_SUSPEND_WAKEUP, PME_SUSPEND_NOIRQ, }; struct pcie_pme_service_data { spinlock_t lock; struct pcie_device *srv; struct work_struct work; enum pme_suspend_level suspend_level; bool noirq; /* If set, keep the PME interrupt disabled. */ }; /** Loading Loading @@ -228,7 +222,7 @@ static void pcie_pme_work_fn(struct work_struct *work) spin_lock_irq(&data->lock); for (;;) { if (data->suspend_level != PME_SUSPEND_NONE) if (data->noirq) break; pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); Loading @@ -255,7 +249,7 @@ static void pcie_pme_work_fn(struct work_struct *work) spin_lock_irq(&data->lock); } if (data->suspend_level == PME_SUSPEND_NONE) if (!data->noirq) pcie_pme_interrupt_enable(port, true); spin_unlock_irq(&data->lock); Loading Loading @@ -378,7 +372,7 @@ static int pcie_pme_suspend(struct pcie_device *srv) { struct pcie_pme_service_data *data = get_service_data(srv); struct pci_dev *port = srv->port; bool wakeup, wake_irq_enabled = false; bool wakeup; int ret; if (device_may_wakeup(&port->dev)) { Loading @@ -388,19 +382,16 @@ static int pcie_pme_suspend(struct pcie_device *srv) wakeup = pcie_pme_check_wakeup(port->subordinate); up_read(&pci_bus_sem); } spin_lock_irq(&data->lock); if (wakeup) { ret = enable_irq_wake(srv->irq); if (ret == 0) { data->suspend_level = PME_SUSPEND_WAKEUP; wake_irq_enabled = true; } if (!ret) return 0; } if (!wake_irq_enabled) { spin_lock_irq(&data->lock); pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; } data->noirq = true; spin_unlock_irq(&data->lock); synchronize_irq(srv->irq); Loading @@ -417,15 +408,15 @@ static int pcie_pme_resume(struct pcie_device *srv) struct pcie_pme_service_data *data = get_service_data(srv); spin_lock_irq(&data->lock); if (data->suspend_level == PME_SUSPEND_NOIRQ) { if (data->noirq) { struct pci_dev *port = srv->port; pcie_clear_root_pme_status(port); pcie_pme_interrupt_enable(port, true); data->noirq = false; } else { disable_irq_wake(srv->irq); } data->suspend_level = PME_SUSPEND_NONE; spin_unlock_irq(&data->lock); return 0; Loading