diff options
| -rw-r--r-- | drivers/cpuidle/cpuidle-big_little.c | 4 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 17 | ||||
| -rw-r--r-- | drivers/pci/pci-driver.c | 11 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 26 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 6 |
5 files changed, 59 insertions, 5 deletions
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c index e3e225fe6b45..40c34faffe59 100644 --- a/drivers/cpuidle/cpuidle-big_little.c +++ b/drivers/cpuidle/cpuidle-big_little.c | |||
| @@ -182,6 +182,10 @@ static int __init bl_idle_init(void) | |||
| 182 | */ | 182 | */ |
| 183 | if (!of_match_node(compatible_machine_match, root)) | 183 | if (!of_match_node(compatible_machine_match, root)) |
| 184 | return -ENODEV; | 184 | return -ENODEV; |
| 185 | |||
| 186 | if (!mcpm_is_available()) | ||
| 187 | return -EUNATCH; | ||
| 188 | |||
| 185 | /* | 189 | /* |
| 186 | * For now the differentiation between little and big cores | 190 | * For now the differentiation between little and big cores |
| 187 | * is based on the part number. A7 cores are considered little | 191 | * is based on the part number. A7 cores are considered little |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 3542150fc8a3..489063987325 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -501,12 +501,29 @@ static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | |||
| 501 | return 0; | 501 | return 0; |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | static bool acpi_pci_need_resume(struct pci_dev *dev) | ||
| 505 | { | ||
| 506 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | ||
| 507 | |||
| 508 | if (!adev || !acpi_device_power_manageable(adev)) | ||
| 509 | return false; | ||
| 510 | |||
| 511 | if (device_may_wakeup(&dev->dev) != !!adev->wakeup.prepare_count) | ||
| 512 | return true; | ||
| 513 | |||
| 514 | if (acpi_target_system_state() == ACPI_STATE_S0) | ||
| 515 | return false; | ||
| 516 | |||
| 517 | return !!adev->power.flags.dsw_present; | ||
| 518 | } | ||
| 519 | |||
| 504 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { | 520 | static struct pci_platform_pm_ops acpi_pci_platform_pm = { |
| 505 | .is_manageable = acpi_pci_power_manageable, | 521 | .is_manageable = acpi_pci_power_manageable, |
| 506 | .set_state = acpi_pci_set_power_state, | 522 | .set_state = acpi_pci_set_power_state, |
| 507 | .choose_state = acpi_pci_choose_state, | 523 | .choose_state = acpi_pci_choose_state, |
| 508 | .sleep_wake = acpi_pci_sleep_wake, | 524 | .sleep_wake = acpi_pci_sleep_wake, |
| 509 | .run_wake = acpi_pci_run_wake, | 525 | .run_wake = acpi_pci_run_wake, |
| 526 | .need_resume = acpi_pci_need_resume, | ||
| 510 | }; | 527 | }; |
| 511 | 528 | ||
| 512 | void acpi_pci_add_bus(struct pci_bus *bus) | 529 | void acpi_pci_add_bus(struct pci_bus *bus) |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 887e6bd95af7..741023e94008 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
| @@ -653,7 +653,6 @@ static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) | |||
| 653 | static int pci_pm_prepare(struct device *dev) | 653 | static int pci_pm_prepare(struct device *dev) |
| 654 | { | 654 | { |
| 655 | struct device_driver *drv = dev->driver; | 655 | struct device_driver *drv = dev->driver; |
| 656 | int error = 0; | ||
| 657 | 656 | ||
| 658 | /* | 657 | /* |
| 659 | * Devices having power.ignore_children set may still be necessary for | 658 | * Devices having power.ignore_children set may still be necessary for |
| @@ -662,10 +661,12 @@ static int pci_pm_prepare(struct device *dev) | |||
| 662 | if (dev->power.ignore_children) | 661 | if (dev->power.ignore_children) |
| 663 | pm_runtime_resume(dev); | 662 | pm_runtime_resume(dev); |
| 664 | 663 | ||
| 665 | if (drv && drv->pm && drv->pm->prepare) | 664 | if (drv && drv->pm && drv->pm->prepare) { |
| 666 | error = drv->pm->prepare(dev); | 665 | int error = drv->pm->prepare(dev); |
| 667 | 666 | if (error) | |
| 668 | return error; | 667 | return error; |
| 668 | } | ||
| 669 | return pci_dev_keep_suspended(to_pci_dev(dev)); | ||
| 669 | } | 670 | } |
| 670 | 671 | ||
| 671 | 672 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e9d4fd861ba1..8cf6b85968ec 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -521,6 +521,11 @@ static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) | |||
| 521 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; | 521 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | static inline bool platform_pci_need_resume(struct pci_dev *dev) | ||
| 525 | { | ||
| 526 | return pci_platform_pm ? pci_platform_pm->need_resume(dev) : false; | ||
| 527 | } | ||
| 528 | |||
| 524 | /** | 529 | /** |
| 525 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of | 530 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of |
| 526 | * given PCI device | 531 | * given PCI device |
| @@ -1999,6 +2004,27 @@ bool pci_dev_run_wake(struct pci_dev *dev) | |||
| 1999 | } | 2004 | } |
| 2000 | EXPORT_SYMBOL_GPL(pci_dev_run_wake); | 2005 | EXPORT_SYMBOL_GPL(pci_dev_run_wake); |
| 2001 | 2006 | ||
| 2007 | /** | ||
| 2008 | * pci_dev_keep_suspended - Check if the device can stay in the suspended state. | ||
| 2009 | * @pci_dev: Device to check. | ||
| 2010 | * | ||
| 2011 | * Return 'true' if the device is runtime-suspended, it doesn't have to be | ||
| 2012 | * reconfigured due to wakeup settings difference between system and runtime | ||
| 2013 | * suspend and the current power state of it is suitable for the upcoming | ||
| 2014 | * (system) transition. | ||
| 2015 | */ | ||
| 2016 | bool pci_dev_keep_suspended(struct pci_dev *pci_dev) | ||
| 2017 | { | ||
| 2018 | struct device *dev = &pci_dev->dev; | ||
| 2019 | |||
| 2020 | if (!pm_runtime_suspended(dev) | ||
| 2021 | || (device_can_wakeup(dev) && !device_may_wakeup(dev)) | ||
| 2022 | || platform_pci_need_resume(pci_dev)) | ||
| 2023 | return false; | ||
| 2024 | |||
| 2025 | return pci_target_state(pci_dev) == pci_dev->current_state; | ||
| 2026 | } | ||
| 2027 | |||
| 2002 | void pci_config_pm_runtime_get(struct pci_dev *pdev) | 2028 | void pci_config_pm_runtime_get(struct pci_dev *pdev) |
| 2003 | { | 2029 | { |
| 2004 | struct device *dev = &pdev->dev; | 2030 | struct device *dev = &pdev->dev; |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d54632a1db43..4091f82239cd 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -50,6 +50,10 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
| 50 | * for given device (the device's wake-up capability has to be | 50 | * for given device (the device's wake-up capability has to be |
| 51 | * enabled by @sleep_wake for this feature to work) | 51 | * enabled by @sleep_wake for this feature to work) |
| 52 | * | 52 | * |
| 53 | * @need_resume: returns 'true' if the given device (which is currently | ||
| 54 | * suspended) needs to be resumed to be configured for system | ||
| 55 | * wakeup. | ||
| 56 | * | ||
| 53 | * If given platform is generally capable of power managing PCI devices, all of | 57 | * If given platform is generally capable of power managing PCI devices, all of |
| 54 | * these callbacks are mandatory. | 58 | * these callbacks are mandatory. |
| 55 | */ | 59 | */ |
| @@ -59,6 +63,7 @@ struct pci_platform_pm_ops { | |||
| 59 | pci_power_t (*choose_state)(struct pci_dev *dev); | 63 | pci_power_t (*choose_state)(struct pci_dev *dev); |
| 60 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | 64 | int (*sleep_wake)(struct pci_dev *dev, bool enable); |
| 61 | int (*run_wake)(struct pci_dev *dev, bool enable); | 65 | int (*run_wake)(struct pci_dev *dev, bool enable); |
| 66 | bool (*need_resume)(struct pci_dev *dev); | ||
| 62 | }; | 67 | }; |
| 63 | 68 | ||
| 64 | int pci_set_platform_pm(struct pci_platform_pm_ops *ops); | 69 | int pci_set_platform_pm(struct pci_platform_pm_ops *ops); |
| @@ -67,6 +72,7 @@ void pci_power_up(struct pci_dev *dev); | |||
| 67 | void pci_disable_enabled_device(struct pci_dev *dev); | 72 | void pci_disable_enabled_device(struct pci_dev *dev); |
| 68 | int pci_finish_runtime_suspend(struct pci_dev *dev); | 73 | int pci_finish_runtime_suspend(struct pci_dev *dev); |
| 69 | int __pci_pme_wakeup(struct pci_dev *dev, void *ign); | 74 | int __pci_pme_wakeup(struct pci_dev *dev, void *ign); |
| 75 | bool pci_dev_keep_suspended(struct pci_dev *dev); | ||
| 70 | void pci_config_pm_runtime_get(struct pci_dev *dev); | 76 | void pci_config_pm_runtime_get(struct pci_dev *dev); |
| 71 | void pci_config_pm_runtime_put(struct pci_dev *dev); | 77 | void pci_config_pm_runtime_put(struct pci_dev *dev); |
| 72 | void pci_pm_init(struct pci_dev *dev); | 78 | void pci_pm_init(struct pci_dev *dev); |
