diff options
-rw-r--r-- | drivers/base/power/domain.c | 57 | ||||
-rw-r--r-- | include/linux/pm_domain.h | 16 | ||||
-rw-r--r-- | kernel/power/Kconfig | 4 |
3 files changed, 71 insertions, 6 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 55c39f5b7a59..515c8ecf01ce 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -697,6 +697,24 @@ static inline void genpd_power_off_work_fn(struct work_struct *work) {} | |||
697 | 697 | ||
698 | #ifdef CONFIG_PM_SLEEP | 698 | #ifdef CONFIG_PM_SLEEP |
699 | 699 | ||
700 | /** | ||
701 | * pm_genpd_present - Check if the given PM domain has been initialized. | ||
702 | * @genpd: PM domain to check. | ||
703 | */ | ||
704 | static bool pm_genpd_present(struct generic_pm_domain *genpd) | ||
705 | { | ||
706 | struct generic_pm_domain *gpd; | ||
707 | |||
708 | if (IS_ERR_OR_NULL(genpd)) | ||
709 | return false; | ||
710 | |||
711 | list_for_each_entry(gpd, &gpd_list, gpd_list_node) | ||
712 | if (gpd == genpd) | ||
713 | return true; | ||
714 | |||
715 | return false; | ||
716 | } | ||
717 | |||
700 | static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd, | 718 | static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd, |
701 | struct device *dev) | 719 | struct device *dev) |
702 | { | 720 | { |
@@ -750,9 +768,10 @@ static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev) | |||
750 | * Check if the given PM domain can be powered off (during system suspend or | 768 | * Check if the given PM domain can be powered off (during system suspend or |
751 | * hibernation) and do that if so. Also, in that case propagate to its masters. | 769 | * hibernation) and do that if so. Also, in that case propagate to its masters. |
752 | * | 770 | * |
753 | * This function is only called in "noirq" stages of system power transitions, | 771 | * This function is only called in "noirq" and "syscore" stages of system power |
754 | * so it need not acquire locks (all of the "noirq" callbacks are executed | 772 | * transitions, so it need not acquire locks (all of the "noirq" callbacks are |
755 | * sequentially, so it is guaranteed that it will never run twice in parallel). | 773 | * executed sequentially, so it is guaranteed that it will never run twice in |
774 | * parallel). | ||
756 | */ | 775 | */ |
757 | static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) | 776 | static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) |
758 | { | 777 | { |
@@ -780,9 +799,10 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) | |||
780 | * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters. | 799 | * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters. |
781 | * @genpd: PM domain to power on. | 800 | * @genpd: PM domain to power on. |
782 | * | 801 | * |
783 | * This function is only called in "noirq" stage of system power transitions, so | 802 | * This function is only called in "noirq" and "syscore" stages of system power |
784 | * it need not acquire locks (all of the "noirq" callbacks are executed | 803 | * transitions, so it need not acquire locks (all of the "noirq" callbacks are |
785 | * sequentially, so it is guaranteed that it will never run twice in parallel). | 804 | * executed sequentially, so it is guaranteed that it will never run twice in |
805 | * parallel). | ||
786 | */ | 806 | */ |
787 | static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) | 807 | static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) |
788 | { | 808 | { |
@@ -1272,6 +1292,31 @@ static void pm_genpd_complete(struct device *dev) | |||
1272 | } | 1292 | } |
1273 | } | 1293 | } |
1274 | 1294 | ||
1295 | /** | ||
1296 | * pm_genpd_syscore_switch - Switch power during system core suspend or resume. | ||
1297 | * @dev: Device that normally is marked as "always on" to switch power for. | ||
1298 | * | ||
1299 | * This routine may only be called during the system core (syscore) suspend or | ||
1300 | * resume phase for devices whose "always on" flags are set. | ||
1301 | */ | ||
1302 | void pm_genpd_syscore_switch(struct device *dev, bool suspend) | ||
1303 | { | ||
1304 | struct generic_pm_domain *genpd; | ||
1305 | |||
1306 | genpd = dev_to_genpd(dev); | ||
1307 | if (!pm_genpd_present(genpd)) | ||
1308 | return; | ||
1309 | |||
1310 | if (suspend) { | ||
1311 | genpd->suspended_count++; | ||
1312 | pm_genpd_sync_poweroff(genpd); | ||
1313 | } else { | ||
1314 | pm_genpd_sync_poweron(genpd); | ||
1315 | genpd->suspended_count--; | ||
1316 | } | ||
1317 | } | ||
1318 | EXPORT_SYMBOL_GPL(pm_genpd_syscore_switch); | ||
1319 | |||
1275 | #else | 1320 | #else |
1276 | 1321 | ||
1277 | #define pm_genpd_prepare NULL | 1322 | #define pm_genpd_prepare NULL |
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index a7d6172922d4..ab83cf3dfaac 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h | |||
@@ -258,4 +258,20 @@ static inline void genpd_queue_power_off_work(struct generic_pm_domain *gpd) {} | |||
258 | static inline void pm_genpd_poweroff_unused(void) {} | 258 | static inline void pm_genpd_poweroff_unused(void) {} |
259 | #endif | 259 | #endif |
260 | 260 | ||
261 | #ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP | ||
262 | extern void pm_genpd_syscore_switch(struct device *dev, bool suspend); | ||
263 | #else | ||
264 | static inline void pm_genpd_syscore_switch(struct device *dev, bool suspend) {} | ||
265 | #endif | ||
266 | |||
267 | static inline void pm_genpd_syscore_poweroff(struct device *dev) | ||
268 | { | ||
269 | pm_genpd_syscore_switch(dev, true); | ||
270 | } | ||
271 | |||
272 | static inline void pm_genpd_syscore_poweron(struct device *dev) | ||
273 | { | ||
274 | pm_genpd_syscore_switch(dev, false); | ||
275 | } | ||
276 | |||
261 | #endif /* _LINUX_PM_DOMAIN_H */ | 277 | #endif /* _LINUX_PM_DOMAIN_H */ |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index a70518c9d82f..5dfdc9ea180b 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -263,6 +263,10 @@ config PM_GENERIC_DOMAINS | |||
263 | bool | 263 | bool |
264 | depends on PM | 264 | depends on PM |
265 | 265 | ||
266 | config PM_GENERIC_DOMAINS_SLEEP | ||
267 | def_bool y | ||
268 | depends on PM_SLEEP && PM_GENERIC_DOMAINS | ||
269 | |||
266 | config PM_GENERIC_DOMAINS_RUNTIME | 270 | config PM_GENERIC_DOMAINS_RUNTIME |
267 | def_bool y | 271 | def_bool y |
268 | depends on PM_RUNTIME && PM_GENERIC_DOMAINS | 272 | depends on PM_RUNTIME && PM_GENERIC_DOMAINS |