Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'pm-domains'

* pm-domains:
PM / shmobile: Make MTU2 driver use pm_genpd_dev_always_on()
PM / shmobile: Make CMT driver use pm_genpd_dev_always_on()
PM / shmobile: Make TMU driver use pm_genpd_dev_always_on()
PM / Domains: Introduce "always on" device flag
PM / Domains: Fix hibernation restore of devices, v2
PM / Domains: Fix handling of wakeup devices during system resume

+70 -16
+2
arch/arm/mach-shmobile/setup-sh7372.c
··· 1043 1043 sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); 1044 1044 sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); 1045 1045 sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); 1046 + sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device); 1047 + sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device); 1046 1048 } 1047 1049 1048 1050 void __init sh7372_add_early_devices(void)
+53 -16
drivers/base/power/domain.c
··· 366 366 not_suspended = 0; 367 367 list_for_each_entry(pdd, &genpd->dev_list, list_node) 368 368 if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev) 369 - || pdd->dev->power.irq_safe)) 369 + || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on)) 370 370 not_suspended++; 371 371 372 372 if (not_suspended > genpd->in_progress) ··· 502 502 return -EINVAL; 503 503 504 504 might_sleep_if(!genpd->dev_irq_safe); 505 + 506 + if (dev_gpd_data(dev)->always_on) 507 + return -EBUSY; 505 508 506 509 stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; 507 510 if (stop_ok && !stop_ok(dev)) ··· 767 764 768 765 genpd_acquire_lock(genpd); 769 766 770 - if (genpd->prepared_count++ == 0) 767 + if (genpd->prepared_count++ == 0) { 768 + genpd->suspended_count = 0; 771 769 genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF; 770 + } 772 771 773 772 genpd_release_lock(genpd); 774 773 ··· 862 857 if (IS_ERR(genpd)) 863 858 return -EINVAL; 864 859 865 - if (genpd->suspend_power_off 860 + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on 866 861 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))) 867 862 return 0; 868 863 ··· 895 890 if (IS_ERR(genpd)) 896 891 return -EINVAL; 897 892 898 - if (genpd->suspend_power_off) 893 + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on 894 + || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))) 899 895 return 0; 900 896 901 897 /* ··· 1015 1009 if (IS_ERR(genpd)) 1016 1010 return -EINVAL; 1017 1011 1018 - return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev); 1012 + return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ? 1013 + 0 : genpd_stop_dev(genpd, dev); 1019 1014 } 1020 1015 1021 1016 /** ··· 1036 1029 if (IS_ERR(genpd)) 1037 1030 return -EINVAL; 1038 1031 1039 - return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev); 1032 + return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ? 1033 + 0 : genpd_start_dev(genpd, dev); 1040 1034 } 1041 1035 1042 1036 /** ··· 1104 1096 * Since all of the "noirq" callbacks are executed sequentially, it is 1105 1097 * guaranteed that this function will never run twice in parallel for 1106 1098 * the same PM domain, so it is not necessary to use locking here. 1099 + * 1100 + * At this point suspended_count == 0 means we are being run for the 1101 + * first time for the given domain in the present cycle. 1107 1102 */ 1108 - genpd->status = GPD_STATE_POWER_OFF; 1109 - if (genpd->suspend_power_off) { 1103 + if (genpd->suspended_count++ == 0) { 1110 1104 /* 1111 - * The boot kernel might put the domain into the power on state, 1112 - * so make sure it really is powered off. 1105 + * The boot kernel might put the domain into arbitrary state, 1106 + * so make it appear as powered off to pm_genpd_poweron(), so 1107 + * that it tries to power it on in case it was really off. 1113 1108 */ 1114 - if (genpd->power_off) 1115 - genpd->power_off(genpd); 1116 - return 0; 1109 + genpd->status = GPD_STATE_POWER_OFF; 1110 + if (genpd->suspend_power_off) { 1111 + /* 1112 + * If the domain was off before the hibernation, make 1113 + * sure it will be off going forward. 1114 + */ 1115 + if (genpd->power_off) 1116 + genpd->power_off(genpd); 1117 + 1118 + return 0; 1119 + } 1117 1120 } 1118 1121 1119 1122 pm_genpd_poweron(genpd); 1120 - genpd->suspended_count--; 1121 1123 1122 - return genpd_start_dev(genpd, dev); 1124 + return dev_gpd_data(dev)->always_on ? 0 : genpd_start_dev(genpd, dev); 1123 1125 } 1124 1126 1125 1127 /** ··· 1323 1305 1324 1306 return ret; 1325 1307 } 1308 + 1309 + /** 1310 + * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device. 1311 + * @dev: Device to set/unset the flag for. 1312 + * @val: The new value of the device's "always on" flag. 1313 + */ 1314 + void pm_genpd_dev_always_on(struct device *dev, bool val) 1315 + { 1316 + struct pm_subsys_data *psd; 1317 + unsigned long flags; 1318 + 1319 + spin_lock_irqsave(&dev->power.lock, flags); 1320 + 1321 + psd = dev_to_psd(dev); 1322 + if (psd && psd->domain_data) 1323 + to_gpd_data(psd->domain_data)->always_on = val; 1324 + 1325 + spin_unlock_irqrestore(&dev->power.lock, flags); 1326 + } 1327 + EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on); 1326 1328 1327 1329 /** 1328 1330 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. ··· 1686 1648 genpd->poweroff_task = NULL; 1687 1649 genpd->resume_count = 0; 1688 1650 genpd->device_count = 0; 1689 - genpd->suspended_count = 0; 1690 1651 genpd->max_off_time_ns = -1; 1691 1652 genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; 1692 1653 genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
+4
drivers/clocksource/sh_cmt.c
··· 32 32 #include <linux/sh_timer.h> 33 33 #include <linux/slab.h> 34 34 #include <linux/module.h> 35 + #include <linux/pm_domain.h> 35 36 36 37 struct sh_cmt_priv { 37 38 void __iomem *mapbase; ··· 689 688 { 690 689 struct sh_cmt_priv *p = platform_get_drvdata(pdev); 691 690 int ret; 691 + 692 + if (!is_early_platform_device(pdev)) 693 + pm_genpd_dev_always_on(&pdev->dev, true); 692 694 693 695 if (p) { 694 696 dev_info(&pdev->dev, "kept as earlytimer\n");
+4
drivers/clocksource/sh_mtu2.c
··· 31 31 #include <linux/sh_timer.h> 32 32 #include <linux/slab.h> 33 33 #include <linux/module.h> 34 + #include <linux/pm_domain.h> 34 35 35 36 struct sh_mtu2_priv { 36 37 void __iomem *mapbase; ··· 306 305 { 307 306 struct sh_mtu2_priv *p = platform_get_drvdata(pdev); 308 307 int ret; 308 + 309 + if (!is_early_platform_device(pdev)) 310 + pm_genpd_dev_always_on(&pdev->dev, true); 309 311 310 312 if (p) { 311 313 dev_info(&pdev->dev, "kept as earlytimer\n");
+4
drivers/clocksource/sh_tmu.c
··· 32 32 #include <linux/sh_timer.h> 33 33 #include <linux/slab.h> 34 34 #include <linux/module.h> 35 + #include <linux/pm_domain.h> 35 36 36 37 struct sh_tmu_priv { 37 38 void __iomem *mapbase; ··· 410 409 { 411 410 struct sh_tmu_priv *p = platform_get_drvdata(pdev); 412 411 int ret; 412 + 413 + if (!is_early_platform_device(pdev)) 414 + pm_genpd_dev_always_on(&pdev->dev, true); 413 415 414 416 if (p) { 415 417 dev_info(&pdev->dev, "kept as earlytimer\n");
+3
include/linux/pm_domain.h
··· 99 99 struct gpd_dev_ops ops; 100 100 struct gpd_timing_data td; 101 101 bool need_restore; 102 + bool always_on; 102 103 }; 103 104 104 105 #ifdef CONFIG_PM_GENERIC_DOMAINS ··· 138 137 139 138 extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, 140 139 struct device *dev); 140 + extern void pm_genpd_dev_always_on(struct device *dev, bool val); 141 141 extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 142 142 struct generic_pm_domain *new_subdomain); 143 143 extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, ··· 181 179 { 182 180 return -ENOSYS; 183 181 } 182 + static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {} 184 183 static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 185 184 struct generic_pm_domain *new_sd) 186 185 {