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

Merge tag 'pm-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
"These fix a nasty hibernation regression introduced during the 6.16
cycle, an issue related to energy model management occurring on Intel
hybrid systems where some CPUs are offline to start with, and two
regressions in the amd-pstate driver:

- Restore a pm_restrict_gfp_mask() call in hibernation_snapshot()
that was removed incorrectly during the 6.16 development cycle
(Rafael Wysocki)

- Introduce a function for registering a perf domain without
triggering a system-wide CPU capacity update and make the
intel_pstate driver use it to avoid reocurring unsuccessful
attempts to update capacities of all CPUs in the system (Rafael
Wysocki)

- Fix setting of CPPC.min_perf in the active mode with performance
governor in the amd-pstate driver to restore its expected behavior
changed recently (Gautham Shenoy)

- Avoid mistakenly setting EPP to 0 in the amd-pstate driver after
system resume as a result of recent code changes (Mario
Limonciello)"

* tag 'pm-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM: hibernate: Restrict GFP mask in hibernation_snapshot()
PM: EM: Add function for registering a PD without capacity update
cpufreq/amd-pstate: Fix a regression leading to EPP 0 after resume
cpufreq/amd-pstate: Fix setting of CPPC.min_perf in active mode for performance governor

+49 -14
+11 -8
drivers/cpufreq/amd-pstate.c
··· 1554 1554 pr_debug("CPU %d exiting\n", policy->cpu); 1555 1555 } 1556 1556 1557 - static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) 1557 + static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy, bool policy_change) 1558 1558 { 1559 1559 struct amd_cpudata *cpudata = policy->driver_data; 1560 1560 union perf_cached perf; 1561 1561 u8 epp; 1562 1562 1563 - if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) 1563 + if (policy_change || 1564 + policy->min != cpudata->min_limit_freq || 1565 + policy->max != cpudata->max_limit_freq) 1564 1566 amd_pstate_update_min_max_limit(policy); 1565 1567 1566 1568 if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) ··· 1586 1584 1587 1585 cpudata->policy = policy->policy; 1588 1586 1589 - ret = amd_pstate_epp_update_limit(policy); 1587 + ret = amd_pstate_epp_update_limit(policy, true); 1590 1588 if (ret) 1591 1589 return ret; 1592 1590 ··· 1628 1626 * min_perf value across kexec reboots. If this CPU is just resumed back without kexec, 1629 1627 * the limits, epp and desired perf will get reset to the cached values in cpudata struct 1630 1628 */ 1631 - ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); 1629 + ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 1630 + FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached), 1631 + FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), 1632 + FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached), 1633 + false); 1632 1634 if (ret) 1633 1635 return ret; 1634 - 1635 - /* invalidate to ensure it's rewritten during resume */ 1636 - cpudata->cppc_req_cached = 0; 1637 1636 1638 1637 /* set this flag to avoid setting core offline*/ 1639 1638 cpudata->suspended = true; ··· 1661 1658 int ret; 1662 1659 1663 1660 /* enable amd pstate from suspend state*/ 1664 - ret = amd_pstate_epp_update_limit(policy); 1661 + ret = amd_pstate_epp_update_limit(policy, false); 1665 1662 if (ret) 1666 1663 return ret; 1667 1664
+2 -2
drivers/cpufreq/intel_pstate.c
··· 1034 1034 if (!cpu_dev) 1035 1035 return false; 1036 1036 1037 - if (em_dev_register_perf_domain(cpu_dev, HYBRID_EM_STATE_COUNT, &cb, 1038 - cpumask_of(cpu), false)) 1037 + if (em_dev_register_pd_no_update(cpu_dev, HYBRID_EM_STATE_COUNT, &cb, 1038 + cpumask_of(cpu), false)) 1039 1039 return false; 1040 1040 1041 1041 cpudata->pd_registered = true;
+10
include/linux/energy_model.h
··· 171 171 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 172 172 const struct em_data_callback *cb, 173 173 const cpumask_t *cpus, bool microwatts); 174 + int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, 175 + const struct em_data_callback *cb, 176 + const cpumask_t *cpus, bool microwatts); 174 177 void em_dev_unregister_perf_domain(struct device *dev); 175 178 struct em_perf_table *em_table_alloc(struct em_perf_domain *pd); 176 179 void em_table_free(struct em_perf_table *table); ··· 350 347 int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, 351 348 const struct em_data_callback *cb, 352 349 const cpumask_t *cpus, bool microwatts) 350 + { 351 + return -EINVAL; 352 + } 353 + static inline 354 + int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, 355 + const struct em_data_callback *cb, 356 + const cpumask_t *cpus, bool microwatts) 353 357 { 354 358 return -EINVAL; 355 359 }
+25 -4
kernel/power/energy_model.c
··· 553 553 const struct em_data_callback *cb, 554 554 const cpumask_t *cpus, bool microwatts) 555 555 { 556 + int ret = em_dev_register_pd_no_update(dev, nr_states, cb, cpus, microwatts); 557 + 558 + if (_is_cpu_device(dev)) 559 + em_check_capacity_update(); 560 + 561 + return ret; 562 + } 563 + EXPORT_SYMBOL_GPL(em_dev_register_perf_domain); 564 + 565 + /** 566 + * em_dev_register_pd_no_update() - Register a perf domain for a device 567 + * @dev : Device to register the PD for 568 + * @nr_states : Number of performance states in the new PD 569 + * @cb : Callback functions for populating the energy model 570 + * @cpus : CPUs to include in the new PD (mandatory if @dev is a CPU device) 571 + * @microwatts : Whether or not the power values in the EM will be in uW 572 + * 573 + * Like em_dev_register_perf_domain(), but does not trigger a CPU capacity 574 + * update after registering the PD, even if @dev is a CPU device. 575 + */ 576 + int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, 577 + const struct em_data_callback *cb, 578 + const cpumask_t *cpus, bool microwatts) 579 + { 556 580 struct em_perf_table *em_table; 557 581 unsigned long cap, prev_cap = 0; 558 582 unsigned long flags = 0; ··· 660 636 unlock: 661 637 mutex_unlock(&em_pd_mutex); 662 638 663 - if (_is_cpu_device(dev)) 664 - em_check_capacity_update(); 665 - 666 639 return ret; 667 640 } 668 - EXPORT_SYMBOL_GPL(em_dev_register_perf_domain); 641 + EXPORT_SYMBOL_GPL(em_dev_register_pd_no_update); 669 642 670 643 /** 671 644 * em_dev_unregister_perf_domain() - Unregister Energy Model (EM) for a device
+1
kernel/power/hibernate.c
··· 449 449 shrink_shmem_memory(); 450 450 451 451 console_suspend_all(); 452 + pm_restrict_gfp_mask(); 452 453 453 454 error = dpm_suspend(PMSG_FREEZE); 454 455