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); |