Skip to content

Commit 815fb87

Browse files
committed
Merge tag 'pm-6.7-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "These fix issues in two cpufreq drivers, in the AMD P-state driver and in the power-capping DTPM framework. Specifics: - Fix the AMD P-state driver's EPP sysfs interface in the cases when the performance governor is in use (Ayush Jain) - Make the ->fast_switch() callback in the AMD P-state driver return the target frequency as expected (Gautham R. Shenoy) - Allow user space to control the range of frequencies to use via scaling_min_freq and scaling_max_freq when AMD P-state driver is in use (Wyes Karny) - Prevent power domains needed for wakeup signaling from being turned off during system suspend on Qualcomm systems and prevent performance states votes from runtime-suspended devices from being lost across a system suspend-resume cycle in qcom-cpufreq-nvmem (Stephan Gerhold) - Fix disabling the 792 Mhz OPP in the imx6q cpufreq driver for the i.MX6ULL types that can run at that frequency (Christoph Niedermaier) - Eliminate unnecessary and harmful conversions to uW from the DTPM (dynamic thermal and power management) framework (Lukasz Luba)" * tag 'pm-6.7-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: cpufreq/amd-pstate: Only print supported EPP values for performance governor cpufreq/amd-pstate: Fix scaling_min_freq and scaling_max_freq update powercap: DTPM: Fix unneeded conversions to micro-Watts cpufreq/amd-pstate: Fix the return value of amd_pstate_fast_switch() pmdomain: qcom: rpmpd: Set GENPD_FLAG_ACTIVE_WAKEUP cpufreq: qcom-nvmem: Preserve PM domain votes in system suspend cpufreq: qcom-nvmem: Enable virtual power domain devices cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
2 parents ce474ae + a6b3125 commit 815fb87

File tree

7 files changed

+136
-32
lines changed

7 files changed

+136
-32
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
307307
highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
308308

309309
WRITE_ONCE(cpudata->highest_perf, highest_perf);
310-
310+
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
311311
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
312312
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
313313
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
314-
314+
WRITE_ONCE(cpudata->min_limit_perf, AMD_CPPC_LOWEST_PERF(cap1));
315315
return 0;
316316
}
317317

@@ -329,11 +329,12 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
329329
highest_perf = cppc_perf.highest_perf;
330330

331331
WRITE_ONCE(cpudata->highest_perf, highest_perf);
332-
332+
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
333333
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
334334
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
335335
cppc_perf.lowest_nonlinear_perf);
336336
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
337+
WRITE_ONCE(cpudata->min_limit_perf, cppc_perf.lowest_perf);
337338

338339
if (cppc_state == AMD_PSTATE_ACTIVE)
339340
return 0;
@@ -432,6 +433,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
432433
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
433434
u64 value = prev;
434435

436+
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
437+
cpudata->max_limit_perf);
438+
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
439+
cpudata->max_limit_perf);
435440
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
436441

437442
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
@@ -470,6 +475,22 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
470475
return 0;
471476
}
472477

478+
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
479+
{
480+
u32 max_limit_perf, min_limit_perf;
481+
struct amd_cpudata *cpudata = policy->driver_data;
482+
483+
max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
484+
min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
485+
486+
WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
487+
WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
488+
WRITE_ONCE(cpudata->max_limit_freq, policy->max);
489+
WRITE_ONCE(cpudata->min_limit_freq, policy->min);
490+
491+
return 0;
492+
}
493+
473494
static int amd_pstate_update_freq(struct cpufreq_policy *policy,
474495
unsigned int target_freq, bool fast_switch)
475496
{
@@ -480,6 +501,9 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy,
480501
if (!cpudata->max_freq)
481502
return -ENODEV;
482503

504+
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
505+
amd_pstate_update_min_max_limit(policy);
506+
483507
cap_perf = READ_ONCE(cpudata->highest_perf);
484508
min_perf = READ_ONCE(cpudata->lowest_perf);
485509
max_perf = cap_perf;
@@ -518,7 +542,9 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
518542
static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
519543
unsigned int target_freq)
520544
{
521-
return amd_pstate_update_freq(policy, target_freq, true);
545+
if (!amd_pstate_update_freq(policy, target_freq, true))
546+
return target_freq;
547+
return policy->cur;
522548
}
523549

524550
static void amd_pstate_adjust_perf(unsigned int cpu,
@@ -532,6 +558,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
532558
struct amd_cpudata *cpudata = policy->driver_data;
533559
unsigned int target_freq;
534560

561+
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
562+
amd_pstate_update_min_max_limit(policy);
563+
564+
535565
cap_perf = READ_ONCE(cpudata->highest_perf);
536566
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
537567
max_freq = READ_ONCE(cpudata->max_freq);
@@ -745,6 +775,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
745775
/* Initial processor data capability frequencies */
746776
cpudata->max_freq = max_freq;
747777
cpudata->min_freq = min_freq;
778+
cpudata->max_limit_freq = max_freq;
779+
cpudata->min_limit_freq = min_freq;
748780
cpudata->nominal_freq = nominal_freq;
749781
cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
750782

@@ -850,11 +882,16 @@ static ssize_t show_energy_performance_available_preferences(
850882
{
851883
int i = 0;
852884
int offset = 0;
885+
struct amd_cpudata *cpudata = policy->driver_data;
886+
887+
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
888+
return sysfs_emit_at(buf, offset, "%s\n",
889+
energy_perf_strings[EPP_INDEX_PERFORMANCE]);
853890

854891
while (energy_perf_strings[i] != NULL)
855892
offset += sysfs_emit_at(buf, offset, "%s ", energy_perf_strings[i++]);
856893

857-
sysfs_emit_at(buf, offset, "\n");
894+
offset += sysfs_emit_at(buf, offset, "\n");
858895

859896
return offset;
860897
}
@@ -1183,16 +1220,25 @@ static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
11831220
return 0;
11841221
}
11851222

1186-
static void amd_pstate_epp_init(unsigned int cpu)
1223+
static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
11871224
{
1188-
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
11891225
struct amd_cpudata *cpudata = policy->driver_data;
1190-
u32 max_perf, min_perf;
1226+
u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
11911227
u64 value;
11921228
s16 epp;
11931229

11941230
max_perf = READ_ONCE(cpudata->highest_perf);
11951231
min_perf = READ_ONCE(cpudata->lowest_perf);
1232+
max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
1233+
min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
1234+
1235+
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
1236+
cpudata->max_limit_perf);
1237+
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
1238+
cpudata->max_limit_perf);
1239+
1240+
WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
1241+
WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
11961242

11971243
value = READ_ONCE(cpudata->cppc_req_cached);
11981244

@@ -1210,9 +1256,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
12101256
value &= ~AMD_CPPC_DES_PERF(~0L);
12111257
value |= AMD_CPPC_DES_PERF(0);
12121258

1213-
if (cpudata->epp_policy == cpudata->policy)
1214-
goto skip_epp;
1215-
12161259
cpudata->epp_policy = cpudata->policy;
12171260

12181261
/* Get BIOS pre-defined epp value */
@@ -1222,7 +1265,7 @@ static void amd_pstate_epp_init(unsigned int cpu)
12221265
* This return value can only be negative for shared_memory
12231266
* systems where EPP register read/write not supported.
12241267
*/
1225-
goto skip_epp;
1268+
return;
12261269
}
12271270

12281271
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
@@ -1236,8 +1279,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
12361279

12371280
WRITE_ONCE(cpudata->cppc_req_cached, value);
12381281
amd_pstate_set_epp(cpudata, epp);
1239-
skip_epp:
1240-
cpufreq_cpu_put(policy);
12411282
}
12421283

12431284
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
@@ -1252,7 +1293,7 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
12521293

12531294
cpudata->policy = policy->policy;
12541295

1255-
amd_pstate_epp_init(policy->cpu);
1296+
amd_pstate_epp_update_limit(policy);
12561297

12571298
return 0;
12581299
}

drivers/cpufreq/imx6q-cpufreq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ static int imx6ul_opp_check_speed_grading(struct device *dev)
327327
imx6x_disable_freq_in_opp(dev, 696000000);
328328

329329
if (of_machine_is_compatible("fsl,imx6ull")) {
330-
if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
330+
if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
331331
imx6x_disable_freq_in_opp(dev, 792000000);
332332

333333
if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)

drivers/cpufreq/qcom-cpufreq-nvmem.c

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
#include <linux/nvmem-consumer.h>
2424
#include <linux/of.h>
2525
#include <linux/platform_device.h>
26+
#include <linux/pm.h>
2627
#include <linux/pm_domain.h>
2728
#include <linux/pm_opp.h>
29+
#include <linux/pm_runtime.h>
2830
#include <linux/slab.h>
2931
#include <linux/soc/qcom/smem.h>
3032

@@ -55,6 +57,7 @@ struct qcom_cpufreq_match_data {
5557

5658
struct qcom_cpufreq_drv_cpu {
5759
int opp_token;
60+
struct device **virt_devs;
5861
};
5962

6063
struct qcom_cpufreq_drv {
@@ -424,6 +427,30 @@ static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
424427
.get_version = qcom_cpufreq_ipq8074_name_version,
425428
};
426429

430+
static void qcom_cpufreq_suspend_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
431+
{
432+
const char * const *name = drv->data->genpd_names;
433+
int i;
434+
435+
if (!drv->cpus[cpu].virt_devs)
436+
return;
437+
438+
for (i = 0; *name; i++, name++)
439+
device_set_awake_path(drv->cpus[cpu].virt_devs[i]);
440+
}
441+
442+
static void qcom_cpufreq_put_virt_devs(struct qcom_cpufreq_drv *drv, unsigned int cpu)
443+
{
444+
const char * const *name = drv->data->genpd_names;
445+
int i;
446+
447+
if (!drv->cpus[cpu].virt_devs)
448+
return;
449+
450+
for (i = 0; *name; i++, name++)
451+
pm_runtime_put(drv->cpus[cpu].virt_devs[i]);
452+
}
453+
427454
static int qcom_cpufreq_probe(struct platform_device *pdev)
428455
{
429456
struct qcom_cpufreq_drv *drv;
@@ -478,6 +505,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
478505
of_node_put(np);
479506

480507
for_each_possible_cpu(cpu) {
508+
struct device **virt_devs = NULL;
481509
struct dev_pm_opp_config config = {
482510
.supported_hw = NULL,
483511
};
@@ -498,7 +526,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
498526

499527
if (drv->data->genpd_names) {
500528
config.genpd_names = drv->data->genpd_names;
501-
config.virt_devs = NULL;
529+
config.virt_devs = &virt_devs;
502530
}
503531

504532
if (config.supported_hw || config.genpd_names) {
@@ -509,6 +537,27 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
509537
goto free_opp;
510538
}
511539
}
540+
541+
if (virt_devs) {
542+
const char * const *name = config.genpd_names;
543+
int i, j;
544+
545+
for (i = 0; *name; i++, name++) {
546+
ret = pm_runtime_resume_and_get(virt_devs[i]);
547+
if (ret) {
548+
dev_err(cpu_dev, "failed to resume %s: %d\n",
549+
*name, ret);
550+
551+
/* Rollback previous PM runtime calls */
552+
name = config.genpd_names;
553+
for (j = 0; *name && j < i; j++, name++)
554+
pm_runtime_put(virt_devs[j]);
555+
556+
goto free_opp;
557+
}
558+
}
559+
drv->cpus[cpu].virt_devs = virt_devs;
560+
}
512561
}
513562

514563
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
@@ -522,8 +571,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
522571
dev_err(cpu_dev, "Failed to register platform device\n");
523572

524573
free_opp:
525-
for_each_possible_cpu(cpu)
574+
for_each_possible_cpu(cpu) {
575+
qcom_cpufreq_put_virt_devs(drv, cpu);
526576
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
577+
}
527578
return ret;
528579
}
529580

@@ -534,15 +585,31 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
534585

535586
platform_device_unregister(cpufreq_dt_pdev);
536587

537-
for_each_possible_cpu(cpu)
588+
for_each_possible_cpu(cpu) {
589+
qcom_cpufreq_put_virt_devs(drv, cpu);
538590
dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
591+
}
539592
}
540593

594+
static int qcom_cpufreq_suspend(struct device *dev)
595+
{
596+
struct qcom_cpufreq_drv *drv = dev_get_drvdata(dev);
597+
unsigned int cpu;
598+
599+
for_each_possible_cpu(cpu)
600+
qcom_cpufreq_suspend_virt_devs(drv, cpu);
601+
602+
return 0;
603+
}
604+
605+
static DEFINE_SIMPLE_DEV_PM_OPS(qcom_cpufreq_pm_ops, qcom_cpufreq_suspend, NULL);
606+
541607
static struct platform_driver qcom_cpufreq_driver = {
542608
.probe = qcom_cpufreq_probe,
543609
.remove_new = qcom_cpufreq_remove,
544610
.driver = {
545611
.name = "qcom-cpufreq-nvmem",
612+
.pm = pm_sleep_ptr(&qcom_cpufreq_pm_ops),
546613
},
547614
};
548615

drivers/pmdomain/qcom/rpmpd.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ static int rpmpd_probe(struct platform_device *pdev)
10441044
rpmpds[i]->pd.power_off = rpmpd_power_off;
10451045
rpmpds[i]->pd.power_on = rpmpd_power_on;
10461046
rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
1047+
rpmpds[i]->pd.flags = GENPD_FLAG_ACTIVE_WAKEUP;
10471048
pm_genpd_init(&rpmpds[i]->pd, NULL, true);
10481049

10491050
data->domains[i] = &rpmpds[i]->pd;

drivers/powercap/dtpm_cpu.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include <linux/of.h>
2525
#include <linux/pm_qos.h>
2626
#include <linux/slab.h>
27-
#include <linux/units.h>
2827

2928
struct dtpm_cpu {
3029
struct dtpm dtpm;
@@ -104,8 +103,7 @@ static u64 get_pd_power_uw(struct dtpm *dtpm)
104103
if (pd->table[i].frequency < freq)
105104
continue;
106105

107-
return scale_pd_power_uw(pd_mask, pd->table[i].power *
108-
MICROWATT_PER_MILLIWATT);
106+
return scale_pd_power_uw(pd_mask, pd->table[i].power);
109107
}
110108

111109
return 0;
@@ -122,11 +120,9 @@ static int update_pd_power_uw(struct dtpm *dtpm)
122120
nr_cpus = cpumask_weight(&cpus);
123121

124122
dtpm->power_min = em->table[0].power;
125-
dtpm->power_min *= MICROWATT_PER_MILLIWATT;
126123
dtpm->power_min *= nr_cpus;
127124

128125
dtpm->power_max = em->table[em->nr_perf_states - 1].power;
129-
dtpm->power_max *= MICROWATT_PER_MILLIWATT;
130126
dtpm->power_max *= nr_cpus;
131127

132128
return 0;

0 commit comments

Comments
 (0)