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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm+acpi-4.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more power management and ACPI updates from Rafael Wysocki:
"These are mostly fixes and cleanups on top of the previous PM+ACPI
pull request (cpufreq core and drivers, cpuidle, generic power domains
framework). Some of them didn't make to that pull request and some
fix issues introduced by it.

The only really new thing is the support for suspend frequency in the
cpufreq-dt driver, but it is needed to fix an issue with Exynos
platforms.

Specifics:

- build fix for the new Mediatek MT8173 cpufreq driver (Guenter
Roeck).

- generic power domains framework fixes (power on error code path,
subdomain removal) and cleanup of a deprecated API user (Geert
Uytterhoeven, Jon Hunter, Ulf Hansson).

- cpufreq-dt driver fixes including two fixes for bugs related to the
new Operating Performance Points Device Tree bindings introduced
recently (Viresh Kumar).

- suspend frequency support for the cpufreq-dt driver (Bartlomiej
Zolnierkiewicz, Viresh Kumar).

- cpufreq core cleanups (Viresh Kumar).

- intel_pstate driver fixes (Chen Yu, Kristen Carlson Accardi).

- additional sanity check in the cpuidle core (Xunlei Pang).

- fix for a comment related to CPU power management (Lina Iyer)"

* tag 'pm+acpi-4.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
intel_pstate: fix PCT_TO_HWP macro
intel_pstate: Fix user input of min/max to legal policy region
PM / OPP: Return suspend_opp only if it is enabled
cpufreq-dt: add suspend frequency support
cpufreq: allow cpufreq_generic_suspend() to work without suspend frequency
PM / OPP: add dev_pm_opp_get_suspend_opp() helper
staging: board: Migrate away from __pm_genpd_name_add_device()
cpufreq: Use __func__ to print function's name
cpufreq: staticize cpufreq_cpu_get_raw()
PM / Domains: Ensure subdomain is not in use before removing
cpufreq: Add ARM_MT8173_CPUFREQ dependency on THERMAL
cpuidle/coupled: Add sanity check for safe_state_index
PM / Domains: Try power off masters in error path of __pm_genpd_poweron()
cpufreq: dt: Tolerance applies on both sides of target voltage
cpufreq: dt: Print error on failing to mark OPPs as shared
cpufreq: dt: Check OPP count before marking them shared
kernel/cpu_pm: fix cpu_cluster_pm_exit comment

+187 -44
+25 -13
drivers/base/power/domain.c
··· 213 213 } 214 214 215 215 /** 216 + * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff(). 217 + * @genpd: PM domait to power off. 218 + * 219 + * Queue up the execution of pm_genpd_poweroff() unless it's already been done 220 + * before. 221 + */ 222 + static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) 223 + { 224 + queue_work(pm_wq, &genpd->power_off_work); 225 + } 226 + 227 + /** 216 228 * __pm_genpd_poweron - Restore power to a given PM domain and its masters. 217 229 * @genpd: PM domain to power up. 218 230 * ··· 271 259 return 0; 272 260 273 261 err: 274 - list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node) 262 + list_for_each_entry_continue_reverse(link, 263 + &genpd->slave_links, 264 + slave_node) { 275 265 genpd_sd_counter_dec(link->master); 266 + genpd_queue_power_off_work(link->master); 267 + } 276 268 277 269 return ret; 278 270 } ··· 362 346 } 363 347 364 348 return NOTIFY_DONE; 365 - } 366 - 367 - /** 368 - * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff(). 369 - * @genpd: PM domait to power off. 370 - * 371 - * Queue up the execution of pm_genpd_poweroff() unless it's already been done 372 - * before. 373 - */ 374 - static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) 375 - { 376 - queue_work(pm_wq, &genpd->power_off_work); 377 349 } 378 350 379 351 /** ··· 1473 1469 1474 1470 mutex_lock(&genpd->lock); 1475 1471 1472 + if (!list_empty(&subdomain->slave_links) || subdomain->device_count) { 1473 + pr_warn("%s: unable to remove subdomain %s\n", genpd->name, 1474 + subdomain->name); 1475 + ret = -EBUSY; 1476 + goto out; 1477 + } 1478 + 1476 1479 list_for_each_entry(link, &genpd->master_links, master_node) { 1477 1480 if (link->slave != subdomain) 1478 1481 continue; ··· 1498 1487 break; 1499 1488 } 1500 1489 1490 + out: 1501 1491 mutex_unlock(&genpd->lock); 1502 1492 1503 1493 return ret;
+28
drivers/base/power/opp.c
··· 341 341 EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); 342 342 343 343 /** 344 + * dev_pm_opp_get_suspend_opp() - Get suspend opp 345 + * @dev: device for which we do this operation 346 + * 347 + * Return: This function returns pointer to the suspend opp if it is 348 + * defined and available, otherwise it returns NULL. 349 + * 350 + * Locking: This function must be called under rcu_read_lock(). opp is a rcu 351 + * protected pointer. The reason for the same is that the opp pointer which is 352 + * returned will remain valid for use with opp_get_{voltage, freq} only while 353 + * under the locked area. The pointer returned must be used prior to unlocking 354 + * with rcu_read_unlock() to maintain the integrity of the pointer. 355 + */ 356 + struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev) 357 + { 358 + struct device_opp *dev_opp; 359 + 360 + opp_rcu_lockdep_assert(); 361 + 362 + dev_opp = _find_device_opp(dev); 363 + if (IS_ERR(dev_opp) || !dev_opp->suspend_opp || 364 + !dev_opp->suspend_opp->available) 365 + return NULL; 366 + 367 + return dev_opp->suspend_opp; 368 + } 369 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp); 370 + 371 + /** 344 372 * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list 345 373 * @dev: device for which we do this operation 346 374 *
+1
drivers/cpufreq/Kconfig.arm
··· 84 84 config ARM_MT8173_CPUFREQ 85 85 bool "Mediatek MT8173 CPUFreq support" 86 86 depends on ARCH_MEDIATEK && REGULATOR 87 + depends on !CPU_THERMAL || THERMAL=y 87 88 select PM_OPP 88 89 help 89 90 This adds the CPUFreq driver support for Mediatek MT8173 SoC.
+26 -13
drivers/cpufreq/cpufreq-dt.c
··· 196 196 struct device *cpu_dev; 197 197 struct regulator *cpu_reg; 198 198 struct clk *cpu_clk; 199 + struct dev_pm_opp *suspend_opp; 199 200 unsigned long min_uV = ~0, max_uV = 0; 200 201 unsigned int transition_latency; 201 202 bool need_update = false; ··· 240 239 */ 241 240 of_cpumask_init_opp_table(policy->cpus); 242 241 242 + /* 243 + * But we need OPP table to function so if it is not there let's 244 + * give platform code chance to provide it for us. 245 + */ 246 + ret = dev_pm_opp_get_opp_count(cpu_dev); 247 + if (ret <= 0) { 248 + pr_debug("OPP table is not ready, deferring probe\n"); 249 + ret = -EPROBE_DEFER; 250 + goto out_free_opp; 251 + } 252 + 243 253 if (need_update) { 244 254 struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data(); 245 255 ··· 261 249 * OPP tables are initialized only for policy->cpu, do it for 262 250 * others as well. 263 251 */ 264 - set_cpus_sharing_opps(cpu_dev, policy->cpus); 252 + ret = set_cpus_sharing_opps(cpu_dev, policy->cpus); 253 + if (ret) 254 + dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", 255 + __func__, ret); 265 256 266 257 of_property_read_u32(np, "clock-latency", &transition_latency); 267 258 } else { 268 259 transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev); 269 - } 270 - 271 - /* 272 - * But we need OPP table to function so if it is not there let's 273 - * give platform code chance to provide it for us. 274 - */ 275 - ret = dev_pm_opp_get_opp_count(cpu_dev); 276 - if (ret <= 0) { 277 - pr_debug("OPP table is not ready, deferring probe\n"); 278 - ret = -EPROBE_DEFER; 279 - goto out_free_opp; 280 260 } 281 261 282 262 priv = kzalloc(sizeof(*priv), GFP_KERNEL); ··· 304 300 rcu_read_unlock(); 305 301 306 302 tol_uV = opp_uV * priv->voltage_tolerance / 100; 307 - if (regulator_is_supported_voltage(cpu_reg, opp_uV, 303 + if (regulator_is_supported_voltage(cpu_reg, 304 + opp_uV - tol_uV, 308 305 opp_uV + tol_uV)) { 309 306 if (opp_uV < min_uV) 310 307 min_uV = opp_uV; ··· 334 329 policy->driver_data = priv; 335 330 336 331 policy->clk = cpu_clk; 332 + 333 + rcu_read_lock(); 334 + suspend_opp = dev_pm_opp_get_suspend_opp(cpu_dev); 335 + if (suspend_opp) 336 + policy->suspend_freq = dev_pm_opp_get_freq(suspend_opp) / 1000; 337 + rcu_read_unlock(); 338 + 337 339 ret = cpufreq_table_validate_and_show(policy, freq_table); 338 340 if (ret) { 339 341 dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__, ··· 431 419 .ready = cpufreq_ready, 432 420 .name = "cpufreq-dt", 433 421 .attr = cpufreq_dt_attr, 422 + .suspend = cpufreq_generic_suspend, 434 423 }; 435 424 436 425 static int dt_cpufreq_probe(struct platform_device *pdev)
+4 -5
drivers/cpufreq/cpufreq.c
··· 239 239 EXPORT_SYMBOL_GPL(cpufreq_generic_init); 240 240 241 241 /* Only for cpufreq core internal use */ 242 - struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu) 242 + static struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu) 243 243 { 244 244 struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); 245 245 ··· 1626 1626 int ret; 1627 1627 1628 1628 if (!policy->suspend_freq) { 1629 - pr_err("%s: suspend_freq can't be zero\n", __func__); 1630 - return -EINVAL; 1629 + pr_debug("%s: suspend_freq not defined\n", __func__); 1630 + return 0; 1631 1631 } 1632 1632 1633 1633 pr_debug("%s: Setting suspend-freq: %u\n", __func__, ··· 2031 2031 if (!try_module_get(policy->governor->owner)) 2032 2032 return -EINVAL; 2033 2033 2034 - pr_debug("__cpufreq_governor for CPU %u, event %u\n", 2035 - policy->cpu, event); 2034 + pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event); 2036 2035 2037 2036 mutex_lock(&cpufreq_governor_lock); 2038 2037 if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
+28 -10
drivers/cpufreq/intel_pstate.c
··· 260 260 cpu->pstate.max_pstate == cpu->pstate.turbo_pstate); 261 261 } 262 262 263 - #define PCT_TO_HWP(x) (x * 255 / 100) 264 263 static void intel_pstate_hwp_set(void) 265 264 { 266 - int min, max, cpu; 267 - u64 value, freq; 265 + int min, hw_min, max, hw_max, cpu, range, adj_range; 266 + u64 value, cap; 267 + 268 + rdmsrl(MSR_HWP_CAPABILITIES, cap); 269 + hw_min = HWP_LOWEST_PERF(cap); 270 + hw_max = HWP_HIGHEST_PERF(cap); 271 + range = hw_max - hw_min; 268 272 269 273 get_online_cpus(); 270 274 271 275 for_each_online_cpu(cpu) { 272 276 rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value); 273 - min = PCT_TO_HWP(limits.min_perf_pct); 277 + adj_range = limits.min_perf_pct * range / 100; 278 + min = hw_min + adj_range; 274 279 value &= ~HWP_MIN_PERF(~0L); 275 280 value |= HWP_MIN_PERF(min); 276 281 277 - max = PCT_TO_HWP(limits.max_perf_pct); 282 + adj_range = limits.max_perf_pct * range / 100; 283 + max = hw_min + adj_range; 278 284 if (limits.no_turbo) { 279 - rdmsrl( MSR_HWP_CAPABILITIES, freq); 280 - max = HWP_GUARANTEED_PERF(freq); 285 + hw_max = HWP_GUARANTEED_PERF(cap); 286 + if (hw_max < max) 287 + max = hw_max; 281 288 } 282 289 283 290 value &= ~HWP_MAX_PERF(~0L); ··· 430 423 431 424 limits.max_sysfs_pct = clamp_t(int, input, 0 , 100); 432 425 limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); 426 + limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct); 427 + limits.max_perf_pct = max(limits.min_perf_pct, limits.max_perf_pct); 433 428 limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); 434 429 435 430 if (hwp_active) ··· 451 442 452 443 limits.min_sysfs_pct = clamp_t(int, input, 0 , 100); 453 444 limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); 445 + limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct); 446 + limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct); 454 447 limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); 455 448 456 449 if (hwp_active) ··· 1000 989 1001 990 limits.min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq; 1002 991 limits.min_policy_pct = clamp_t(int, limits.min_policy_pct, 0 , 100); 1003 - limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); 1004 - limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); 1005 - 1006 992 limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq; 1007 993 limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100); 994 + 995 + /* Normalize user input to [min_policy_pct, max_policy_pct] */ 996 + limits.min_perf_pct = max(limits.min_policy_pct, limits.min_sysfs_pct); 997 + limits.min_perf_pct = min(limits.max_policy_pct, limits.min_perf_pct); 1008 998 limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct); 999 + limits.max_perf_pct = max(limits.min_policy_pct, limits.max_perf_pct); 1000 + 1001 + /* Make sure min_perf_pct <= max_perf_pct */ 1002 + limits.min_perf_pct = min(limits.max_perf_pct, limits.min_perf_pct); 1003 + 1004 + limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100)); 1009 1005 limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100)); 1010 1006 1011 1007 if (hwp_active)
+22
drivers/cpuidle/coupled.c
··· 187 187 } 188 188 189 189 /** 190 + * cpuidle_coupled_state_verify - check if the coupled states are correctly set. 191 + * @drv: struct cpuidle_driver for the platform 192 + * 193 + * Returns 0 for valid state values, a negative error code otherwise: 194 + * * -EINVAL if any coupled state(safe_state_index) is wrongly set. 195 + */ 196 + int cpuidle_coupled_state_verify(struct cpuidle_driver *drv) 197 + { 198 + int i; 199 + 200 + for (i = drv->state_count - 1; i >= 0; i--) { 201 + if (cpuidle_state_is_coupled(drv, i) && 202 + (drv->safe_state_index == i || 203 + drv->safe_state_index < 0 || 204 + drv->safe_state_index >= drv->state_count)) 205 + return -EINVAL; 206 + } 207 + 208 + return 0; 209 + } 210 + 211 + /** 190 212 * cpuidle_coupled_set_ready - mark a cpu as ready 191 213 * @coupled: the struct coupled that contains the current cpu 192 214 */
+6
drivers/cpuidle/cpuidle.h
··· 35 35 36 36 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED 37 37 bool cpuidle_state_is_coupled(struct cpuidle_driver *drv, int state); 38 + int cpuidle_coupled_state_verify(struct cpuidle_driver *drv); 38 39 int cpuidle_enter_state_coupled(struct cpuidle_device *dev, 39 40 struct cpuidle_driver *drv, int next_state); 40 41 int cpuidle_coupled_register_device(struct cpuidle_device *dev); ··· 45 44 bool cpuidle_state_is_coupled(struct cpuidle_driver *drv, int state) 46 45 { 47 46 return false; 47 + } 48 + 49 + static inline int cpuidle_coupled_state_verify(struct cpuidle_driver *drv) 50 + { 51 + return 0; 48 52 } 49 53 50 54 static inline int cpuidle_enter_state_coupled(struct cpuidle_device *dev,
+4
drivers/cpuidle/driver.c
··· 227 227 if (!drv || !drv->state_count) 228 228 return -EINVAL; 229 229 230 + ret = cpuidle_coupled_state_verify(drv); 231 + if (ret) 232 + return ret; 233 + 230 234 if (cpuidle_disabled()) 231 235 return -ENODEV; 232 236
+1 -1
drivers/staging/board/armadillo800eva.c
··· 91 91 .pdev = &lcdc0_device, 92 92 .clocks = lcdc0_clocks, 93 93 .nclocks = ARRAY_SIZE(lcdc0_clocks), 94 - .domain = "a4lc", 94 + .domain = "/system-controller@e6180000/pm-domains/c5/a4lc@1" 95 95 }, 96 96 }; 97 97
+35 -1
drivers/staging/board/board.c
··· 135 135 return error; 136 136 } 137 137 138 + #ifdef CONFIG_PM_GENERIC_DOMAINS_OF 139 + static int board_staging_add_dev_domain(struct platform_device *pdev, 140 + const char *domain) 141 + { 142 + struct of_phandle_args pd_args; 143 + struct generic_pm_domain *pd; 144 + struct device_node *np; 145 + 146 + np = of_find_node_by_path(domain); 147 + if (!np) { 148 + pr_err("Cannot find domain node %s\n", domain); 149 + return -ENOENT; 150 + } 151 + 152 + pd_args.np = np; 153 + pd_args.args_count = 0; 154 + pd = of_genpd_get_from_provider(&pd_args); 155 + if (IS_ERR(pd)) { 156 + pr_err("Cannot find genpd %s (%ld)\n", domain, PTR_ERR(pd)); 157 + return PTR_ERR(pd); 158 + 159 + } 160 + pr_debug("Found genpd %s for device %s\n", pd->name, pdev->name); 161 + 162 + return pm_genpd_add_device(pd, &pdev->dev); 163 + } 164 + #else 165 + static inline int board_staging_add_dev_domain(struct platform_device *pdev, 166 + const char *domain) 167 + { 168 + return 0; 169 + } 170 + #endif 171 + 138 172 int __init board_staging_register_device(const struct board_staging_dev *dev) 139 173 { 140 174 struct platform_device *pdev = dev->pdev; ··· 195 161 } 196 162 197 163 if (dev->domain) 198 - __pm_genpd_name_add_device(dev->domain, &pdev->dev, NULL); 164 + board_staging_add_dev_domain(pdev, dev->domain); 199 165 200 166 return error; 201 167 }
+6
include/linux/pm_opp.h
··· 34 34 35 35 int dev_pm_opp_get_opp_count(struct device *dev); 36 36 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev); 37 + struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev); 37 38 38 39 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, 39 40 unsigned long freq, ··· 79 78 static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) 80 79 { 81 80 return 0; 81 + } 82 + 83 + static inline struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev) 84 + { 85 + return NULL; 82 86 } 83 87 84 88 static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+1 -1
kernel/cpu_pm.c
··· 180 180 * low power state that may have caused some blocks in the same power domain 181 181 * to reset. 182 182 * 183 - * Must be called after cpu_pm_exit has been called on all cpus in the power 183 + * Must be called after cpu_cluster_pm_enter has been called for the power 184 184 * domain, and before cpu_pm_exit has been called on any cpu in the power 185 185 * domain. Notified drivers can include VFP co-processor, interrupt controller 186 186 * and its PM extensions, local CPU timers context save/restore which