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

Merge branches 'pm-domains', 'pm-kconfig', 'pm-cpuidle' and 'powercap'

* pm-domains:
PM / genpd: Stop/start devices without pm_runtime_force_suspend/resume()
PM / domains: Don't skip driver's ->suspend|resume_noirq() callbacks
PM / Domains: Remove obsolete "samsung,power-domain" check

* pm-kconfig:
bus: simple-pm-bus: convert bool SIMPLE_PM_BUS to tristate
PM: Provide a config snippet for disabling PM

* pm-cpuidle:
cpuidle: Avoid NULL argument in cpuidle_switch_governor()

* powercap:
powercap: intel_rapl: Fix trailing semicolon
powercap: add suspend and resume mechanism for SOC power limit
powercap: Simplify powercap_init()

+153 -44
+1
MAINTAINERS
··· 10890 10890 F: include/linux/pm_* 10891 10891 F: include/linux/powercap.h 10892 10892 F: drivers/powercap/ 10893 + F: kernel/configs/nopm.config 10893 10894 10894 10895 POWER STATE COORDINATION INTERFACE (PSCI) 10895 10896 M: Mark Rutland <mark.rutland@arm.com>
+33 -36
drivers/base/power/domain.c
··· 1032 1032 static int genpd_finish_suspend(struct device *dev, bool poweroff) 1033 1033 { 1034 1034 struct generic_pm_domain *genpd; 1035 - int ret; 1035 + int ret = 0; 1036 1036 1037 1037 genpd = dev_to_genpd(dev); 1038 1038 if (IS_ERR(genpd)) 1039 1039 return -EINVAL; 1040 - 1041 - if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) 1042 - return 0; 1043 1040 1044 1041 if (poweroff) 1045 1042 ret = pm_generic_poweroff_noirq(dev); ··· 1045 1048 if (ret) 1046 1049 return ret; 1047 1050 1048 - if (genpd->dev_ops.stop && genpd->dev_ops.start) { 1049 - ret = pm_runtime_force_suspend(dev); 1050 - if (ret) 1051 + if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) 1052 + return 0; 1053 + 1054 + if (genpd->dev_ops.stop && genpd->dev_ops.start && 1055 + !pm_runtime_status_suspended(dev)) { 1056 + ret = genpd_stop_dev(genpd, dev); 1057 + if (ret) { 1058 + if (poweroff) 1059 + pm_generic_restore_noirq(dev); 1060 + else 1061 + pm_generic_resume_noirq(dev); 1051 1062 return ret; 1063 + } 1052 1064 } 1053 1065 1054 1066 genpd_lock(genpd); ··· 1091 1085 static int genpd_resume_noirq(struct device *dev) 1092 1086 { 1093 1087 struct generic_pm_domain *genpd; 1094 - int ret = 0; 1088 + int ret; 1095 1089 1096 1090 dev_dbg(dev, "%s()\n", __func__); 1097 1091 ··· 1100 1094 return -EINVAL; 1101 1095 1102 1096 if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) 1103 - return 0; 1097 + return pm_generic_resume_noirq(dev); 1104 1098 1105 1099 genpd_lock(genpd); 1106 1100 genpd_sync_power_on(genpd, true, 0); 1107 1101 genpd->suspended_count--; 1108 1102 genpd_unlock(genpd); 1109 1103 1110 - if (genpd->dev_ops.stop && genpd->dev_ops.start) 1111 - ret = pm_runtime_force_resume(dev); 1104 + if (genpd->dev_ops.stop && genpd->dev_ops.start && 1105 + !pm_runtime_status_suspended(dev)) { 1106 + ret = genpd_start_dev(genpd, dev); 1107 + if (ret) 1108 + return ret; 1109 + } 1112 1110 1113 - ret = pm_generic_resume_noirq(dev); 1114 - if (ret) 1115 - return ret; 1116 - 1117 - return ret; 1111 + return pm_generic_resume_noirq(dev); 1118 1112 } 1119 1113 1120 1114 /** ··· 1141 1135 if (ret) 1142 1136 return ret; 1143 1137 1144 - if (genpd->dev_ops.stop && genpd->dev_ops.start) 1145 - ret = pm_runtime_force_suspend(dev); 1138 + if (genpd->dev_ops.stop && genpd->dev_ops.start && 1139 + !pm_runtime_status_suspended(dev)) 1140 + ret = genpd_stop_dev(genpd, dev); 1146 1141 1147 1142 return ret; 1148 1143 } ··· 1166 1159 if (IS_ERR(genpd)) 1167 1160 return -EINVAL; 1168 1161 1169 - if (genpd->dev_ops.stop && genpd->dev_ops.start) { 1170 - ret = pm_runtime_force_resume(dev); 1162 + if (genpd->dev_ops.stop && genpd->dev_ops.start && 1163 + !pm_runtime_status_suspended(dev)) { 1164 + ret = genpd_start_dev(genpd, dev); 1171 1165 if (ret) 1172 1166 return ret; 1173 1167 } ··· 1225 1217 genpd_sync_power_on(genpd, true, 0); 1226 1218 genpd_unlock(genpd); 1227 1219 1228 - if (genpd->dev_ops.stop && genpd->dev_ops.start) { 1229 - ret = pm_runtime_force_resume(dev); 1220 + if (genpd->dev_ops.stop && genpd->dev_ops.start && 1221 + !pm_runtime_status_suspended(dev)) { 1222 + ret = genpd_start_dev(genpd, dev); 1230 1223 if (ret) 1231 1224 return ret; 1232 1225 } ··· 2208 2199 2209 2200 ret = of_parse_phandle_with_args(dev->of_node, "power-domains", 2210 2201 "#power-domain-cells", 0, &pd_args); 2211 - if (ret < 0) { 2212 - if (ret != -ENOENT) 2213 - return ret; 2214 - 2215 - /* 2216 - * Try legacy Samsung-specific bindings 2217 - * (for backwards compatibility of DT ABI) 2218 - */ 2219 - pd_args.args_count = 0; 2220 - pd_args.np = of_parse_phandle(dev->of_node, 2221 - "samsung,power-domain", 0); 2222 - if (!pd_args.np) 2223 - return -ENOENT; 2224 - } 2202 + if (ret < 0) 2203 + return ret; 2225 2204 2226 2205 mutex_lock(&gpd_list_lock); 2227 2206 pd = genpd_get_from_provider(&pd_args);
+1 -1
drivers/bus/Kconfig
··· 120 120 SRAM, ethernet adapters, FPGAs and LCD displays. 121 121 122 122 config SIMPLE_PM_BUS 123 - bool "Simple Power-Managed Bus Driver" 123 + tristate "Simple Power-Managed Bus Driver" 124 124 depends on OF && PM 125 125 help 126 126 Driver for transparent busses that don't need a real driver, but
+3 -2
drivers/cpuidle/governor.c
··· 36 36 /** 37 37 * cpuidle_switch_governor - changes the governor 38 38 * @gov: the new target governor 39 - * 40 - * NOTE: "gov" can be NULL to specify disabled 41 39 * Must be called with cpuidle_lock acquired. 42 40 */ 43 41 int cpuidle_switch_governor(struct cpuidle_governor *gov) 44 42 { 45 43 struct cpuidle_device *dev; 44 + 45 + if (!gov) 46 + return -EINVAL; 46 47 47 48 if (gov == cpuidle_curr_governor) 48 49 return 0;
+98 -1
drivers/powercap/intel_rapl.c
··· 29 29 #include <linux/sysfs.h> 30 30 #include <linux/cpu.h> 31 31 #include <linux/powercap.h> 32 + #include <linux/suspend.h> 32 33 #include <asm/iosf_mbi.h> 33 34 34 35 #include <asm/processor.h> ··· 156 155 int prim_id; /* primitive ID used to enable */ 157 156 struct rapl_domain *domain; 158 157 const char *name; 158 + u64 last_power_limit; 159 159 }; 160 160 161 161 static const char pl1_name[] = "long_term"; ··· 1211 1209 struct rapl_domain *rd; 1212 1210 char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/ 1213 1211 struct powercap_zone *power_zone = NULL; 1214 - int nr_pl, ret;; 1212 + int nr_pl, ret; 1215 1213 1216 1214 /* Update the domain data of the new package */ 1217 1215 rapl_update_domain_data(rp); ··· 1535 1533 1536 1534 static enum cpuhp_state pcap_rapl_online; 1537 1535 1536 + static void power_limit_state_save(void) 1537 + { 1538 + struct rapl_package *rp; 1539 + struct rapl_domain *rd; 1540 + int nr_pl, ret, i; 1541 + 1542 + get_online_cpus(); 1543 + list_for_each_entry(rp, &rapl_packages, plist) { 1544 + if (!rp->power_zone) 1545 + continue; 1546 + rd = power_zone_to_rapl_domain(rp->power_zone); 1547 + nr_pl = find_nr_power_limit(rd); 1548 + for (i = 0; i < nr_pl; i++) { 1549 + switch (rd->rpl[i].prim_id) { 1550 + case PL1_ENABLE: 1551 + ret = rapl_read_data_raw(rd, 1552 + POWER_LIMIT1, 1553 + true, 1554 + &rd->rpl[i].last_power_limit); 1555 + if (ret) 1556 + rd->rpl[i].last_power_limit = 0; 1557 + break; 1558 + case PL2_ENABLE: 1559 + ret = rapl_read_data_raw(rd, 1560 + POWER_LIMIT2, 1561 + true, 1562 + &rd->rpl[i].last_power_limit); 1563 + if (ret) 1564 + rd->rpl[i].last_power_limit = 0; 1565 + break; 1566 + } 1567 + } 1568 + } 1569 + put_online_cpus(); 1570 + } 1571 + 1572 + static void power_limit_state_restore(void) 1573 + { 1574 + struct rapl_package *rp; 1575 + struct rapl_domain *rd; 1576 + int nr_pl, i; 1577 + 1578 + get_online_cpus(); 1579 + list_for_each_entry(rp, &rapl_packages, plist) { 1580 + if (!rp->power_zone) 1581 + continue; 1582 + rd = power_zone_to_rapl_domain(rp->power_zone); 1583 + nr_pl = find_nr_power_limit(rd); 1584 + for (i = 0; i < nr_pl; i++) { 1585 + switch (rd->rpl[i].prim_id) { 1586 + case PL1_ENABLE: 1587 + if (rd->rpl[i].last_power_limit) 1588 + rapl_write_data_raw(rd, 1589 + POWER_LIMIT1, 1590 + rd->rpl[i].last_power_limit); 1591 + break; 1592 + case PL2_ENABLE: 1593 + if (rd->rpl[i].last_power_limit) 1594 + rapl_write_data_raw(rd, 1595 + POWER_LIMIT2, 1596 + rd->rpl[i].last_power_limit); 1597 + break; 1598 + } 1599 + } 1600 + } 1601 + put_online_cpus(); 1602 + } 1603 + 1604 + static int rapl_pm_callback(struct notifier_block *nb, 1605 + unsigned long mode, void *_unused) 1606 + { 1607 + switch (mode) { 1608 + case PM_SUSPEND_PREPARE: 1609 + power_limit_state_save(); 1610 + break; 1611 + case PM_POST_SUSPEND: 1612 + power_limit_state_restore(); 1613 + break; 1614 + } 1615 + return NOTIFY_OK; 1616 + } 1617 + 1618 + static struct notifier_block rapl_pm_notifier = { 1619 + .notifier_call = rapl_pm_callback, 1620 + }; 1621 + 1538 1622 static int __init rapl_init(void) 1539 1623 { 1540 1624 const struct x86_cpu_id *id; ··· 1648 1560 1649 1561 /* Don't bail out if PSys is not supported */ 1650 1562 rapl_register_psys(); 1563 + 1564 + ret = register_pm_notifier(&rapl_pm_notifier); 1565 + if (ret) 1566 + goto err_unreg_all; 1567 + 1651 1568 return 0; 1569 + 1570 + err_unreg_all: 1571 + cpuhp_remove_state(pcap_rapl_online); 1652 1572 1653 1573 err_unreg: 1654 1574 rapl_unregister_powercap(); ··· 1665 1569 1666 1570 static void __exit rapl_exit(void) 1667 1571 { 1572 + unregister_pm_notifier(&rapl_pm_notifier); 1668 1573 cpuhp_remove_state(pcap_rapl_online); 1669 1574 rapl_unregister_powercap(); 1670 1575 }
+2 -4
drivers/powercap/powercap_sys.c
··· 673 673 674 674 static int __init powercap_init(void) 675 675 { 676 - int result = 0; 676 + int result; 677 677 678 678 result = seed_constraint_attributes(); 679 679 if (result) 680 680 return result; 681 681 682 - result = class_register(&powercap_class); 683 - 684 - return result; 682 + return class_register(&powercap_class); 685 683 } 686 684 687 685 device_initcall(powercap_init);
+15
kernel/configs/nopm.config
··· 1 + CONFIG_PM=n 2 + CONFIG_SUSPEND=n 3 + CONFIG_HIBERNATION=n 4 + 5 + # Triggers PM on OMAP 6 + CONFIG_CPU_IDLE=n 7 + 8 + # Triggers enablement via hibernate callbacks 9 + CONFIG_XEN=n 10 + 11 + # ARM/ARM64 architectures that select PM unconditionally 12 + CONFIG_ARCH_OMAP2PLUS_TYPICAL=n 13 + CONFIG_ARCH_RENESAS=n 14 + CONFIG_ARCH_TEGRA=n 15 + CONFIG_ARCH_VEXPRESS=n