Skip to content

Commit 5cbba60

Browse files
committed
Merge tag 'pm-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These address some PCI device power management issues, add new hardware support to the RAPL power capping driver, add HWP guaranteed performance change notification support to the intel_pstate driver, replace deprecated CPU-hotplug functions in a few places, update CPU PM notifiers to use raw spinlocks, update the PM domains framework (new DT property support, Kconfig fix), do a couple of cleanups in code related to system sleep, and improve the energy model and the schedutil cpufreq governor. Specifics: - Address 3 PCI device power management issues (Rafael Wysocki). - Add Power Limit4 support for Alder Lake to the Intel RAPL power capping driver (Sumeet Pawnikar). - Add HWP guaranteed performance change notification support to the intel_pstate driver (Srinivas Pandruvada). - Replace deprecated CPU-hotplug functions in code related to power management (Sebastian Andrzej Siewior). - Update CPU PM notifiers to use raw spinlocks (Valentin Schneider). - Add support for 'required-opps' DT property to the generic power domains (genpd) framework and use this property for I2C on ARM64 sc7180 (Rajendra Nayak). - Fix Kconfig issue related to genpd (Geert Uytterhoeven). - Increase energy calculation precision in the Energy Model (Lukasz Luba). - Fix kobject deletion in the exit code of the schedutil cpufreq governor (Kevin Hao). - Unmark some functions as kernel-doc in the PM core to avoid false-positive documentation build warnings (Randy Dunlap). - Check RTC features instead of ops in suspend_test Alexandre Belloni)" * tag 'pm-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM: domains: Fix domain attach for CONFIG_PM_OPP=n powercap: Add Power Limit4 support for Alder Lake SoC cpufreq: intel_pstate: Process HWP Guaranteed change notification thermal: intel: Allow processing of HWP interrupt notifier: Remove atomic_notifier_call_chain_robust() PM: cpu: Make notifier chain use a raw_spinlock_t PM: sleep: unmark 'state' functions as kernel-doc arm64: dts: sc7180: Add required-opps for i2c PM: domains: Add support for 'required-opps' to set default perf state opp: Don't print an error if required-opps is missing cpufreq: schedutil: Use kobject release() method to free sugov_tunables PM: EM: Increase energy calculation precision PM: sleep: check RTC features instead of ops in suspend_test PM: sleep: s2idle: Replace deprecated CPU-hotplug functions cpufreq: Replace deprecated CPU-hotplug functions powercap: intel_rapl: Replace deprecated CPU-hotplug functions PCI: PM: Enable PME if it can be signaled from D3cold PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently PCI: Use pci_update_current_state() in pci_enable_device_flags()
2 parents 9b2eacd + fe58335 commit 5cbba60

File tree

24 files changed

+235
-107
lines changed

24 files changed

+235
-107
lines changed

arch/arm64/boot/dts/qcom/sc7180.dtsi

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,8 @@
786786
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
787787
interconnect-names = "qup-core", "qup-config",
788788
"qup-memory";
789+
power-domains = <&rpmhpd SC7180_CX>;
790+
required-opps = <&rpmhpd_opp_low_svs>;
789791
status = "disabled";
790792
};
791793

@@ -838,6 +840,8 @@
838840
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
839841
interconnect-names = "qup-core", "qup-config",
840842
"qup-memory";
843+
power-domains = <&rpmhpd SC7180_CX>;
844+
required-opps = <&rpmhpd_opp_low_svs>;
841845
status = "disabled";
842846
};
843847

@@ -890,6 +894,8 @@
890894
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
891895
interconnect-names = "qup-core", "qup-config",
892896
"qup-memory";
897+
power-domains = <&rpmhpd SC7180_CX>;
898+
required-opps = <&rpmhpd_opp_low_svs>;
893899
status = "disabled";
894900
};
895901

@@ -924,6 +930,8 @@
924930
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
925931
interconnect-names = "qup-core", "qup-config",
926932
"qup-memory";
933+
power-domains = <&rpmhpd SC7180_CX>;
934+
required-opps = <&rpmhpd_opp_low_svs>;
927935
status = "disabled";
928936
};
929937

@@ -976,6 +984,8 @@
976984
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
977985
interconnect-names = "qup-core", "qup-config",
978986
"qup-memory";
987+
power-domains = <&rpmhpd SC7180_CX>;
988+
required-opps = <&rpmhpd_opp_low_svs>;
979989
status = "disabled";
980990
};
981991

@@ -1010,6 +1020,8 @@
10101020
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
10111021
interconnect-names = "qup-core", "qup-config",
10121022
"qup-memory";
1023+
power-domains = <&rpmhpd SC7180_CX>;
1024+
required-opps = <&rpmhpd_opp_low_svs>;
10131025
status = "disabled";
10141026
};
10151027

@@ -1075,6 +1087,8 @@
10751087
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
10761088
interconnect-names = "qup-core", "qup-config",
10771089
"qup-memory";
1090+
power-domains = <&rpmhpd SC7180_CX>;
1091+
required-opps = <&rpmhpd_opp_low_svs>;
10781092
status = "disabled";
10791093
};
10801094

@@ -1127,6 +1141,8 @@
11271141
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
11281142
interconnect-names = "qup-core", "qup-config",
11291143
"qup-memory";
1144+
power-domains = <&rpmhpd SC7180_CX>;
1145+
required-opps = <&rpmhpd_opp_low_svs>;
11301146
status = "disabled";
11311147
};
11321148

@@ -1161,6 +1177,8 @@
11611177
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
11621178
interconnect-names = "qup-core", "qup-config",
11631179
"qup-memory";
1180+
power-domains = <&rpmhpd SC7180_CX>;
1181+
required-opps = <&rpmhpd_opp_low_svs>;
11641182
status = "disabled";
11651183
};
11661184

@@ -1213,6 +1231,8 @@
12131231
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
12141232
interconnect-names = "qup-core", "qup-config",
12151233
"qup-memory";
1234+
power-domains = <&rpmhpd SC7180_CX>;
1235+
required-opps = <&rpmhpd_opp_low_svs>;
12161236
status = "disabled";
12171237
};
12181238

@@ -1247,6 +1267,8 @@
12471267
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
12481268
interconnect-names = "qup-core", "qup-config",
12491269
"qup-memory";
1270+
power-domains = <&rpmhpd SC7180_CX>;
1271+
required-opps = <&rpmhpd_opp_low_svs>;
12501272
status = "disabled";
12511273
};
12521274

@@ -1299,6 +1321,8 @@
12991321
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
13001322
interconnect-names = "qup-core", "qup-config",
13011323
"qup-memory";
1324+
power-domains = <&rpmhpd SC7180_CX>;
1325+
required-opps = <&rpmhpd_opp_low_svs>;
13021326
status = "disabled";
13031327
};
13041328

drivers/base/power/domain.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
26042604

26052605
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
26062606

2607+
/* Drop the default performance state */
2608+
if (dev_gpd_data(dev)->default_pstate) {
2609+
dev_pm_genpd_set_performance_state(dev, 0);
2610+
dev_gpd_data(dev)->default_pstate = 0;
2611+
}
2612+
26072613
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
26082614
ret = genpd_remove_device(pd, dev);
26092615
if (ret != -EAGAIN)
@@ -2643,6 +2649,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
26432649
{
26442650
struct of_phandle_args pd_args;
26452651
struct generic_pm_domain *pd;
2652+
int pstate;
26462653
int ret;
26472654

26482655
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
@@ -2681,10 +2688,29 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
26812688
genpd_unlock(pd);
26822689
}
26832690

2684-
if (ret)
2691+
if (ret) {
26852692
genpd_remove_device(pd, dev);
2693+
return -EPROBE_DEFER;
2694+
}
26862695

2687-
return ret ? -EPROBE_DEFER : 1;
2696+
/* Set the default performance state */
2697+
pstate = of_get_required_opp_performance_state(dev->of_node, index);
2698+
if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) {
2699+
ret = pstate;
2700+
goto err;
2701+
} else if (pstate > 0) {
2702+
ret = dev_pm_genpd_set_performance_state(dev, pstate);
2703+
if (ret)
2704+
goto err;
2705+
dev_gpd_data(dev)->default_pstate = pstate;
2706+
}
2707+
return 1;
2708+
2709+
err:
2710+
dev_err(dev, "failed to set required performance state for power-domain %s: %d\n",
2711+
pd->name, ret);
2712+
genpd_remove_device(pd, dev);
2713+
return ret;
26882714
}
26892715

26902716
/**

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
163163
if (ret || val > 1)
164164
return -EINVAL;
165165

166-
get_online_cpus();
166+
cpus_read_lock();
167167
set_boost(policy, val);
168-
put_online_cpus();
168+
cpus_read_unlock();
169169

170170
return count;
171171
}

drivers/cpufreq/cpufreq.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,18 +2654,18 @@ int cpufreq_boost_trigger_state(int state)
26542654
cpufreq_driver->boost_enabled = state;
26552655
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
26562656

2657-
get_online_cpus();
2657+
cpus_read_lock();
26582658
for_each_active_policy(policy) {
26592659
ret = cpufreq_driver->set_boost(policy, state);
26602660
if (ret)
26612661
goto err_reset_state;
26622662
}
2663-
put_online_cpus();
2663+
cpus_read_unlock();
26642664

26652665
return 0;
26662666

26672667
err_reset_state:
2668-
put_online_cpus();
2668+
cpus_read_unlock();
26692669

26702670
write_lock_irqsave(&cpufreq_driver_lock, flags);
26712671
cpufreq_driver->boost_enabled = !state;

drivers/cpufreq/cpufreq_ondemand.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
418418
default_powersave_bias = powersave_bias;
419419
cpumask_clear(&done);
420420

421-
get_online_cpus();
421+
cpus_read_lock();
422422
for_each_online_cpu(cpu) {
423423
struct cpufreq_policy *policy;
424424
struct policy_dbs_info *policy_dbs;
@@ -442,7 +442,7 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
442442
od_tuners = dbs_data->tuners;
443443
od_tuners->powersave_bias = default_powersave_bias;
444444
}
445-
put_online_cpus();
445+
cpus_read_unlock();
446446
}
447447

448448
void od_register_powersave_bias_handler(unsigned int (*f)

drivers/cpufreq/intel_pstate.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <asm/cpu_device_id.h>
3333
#include <asm/cpufeature.h>
3434
#include <asm/intel-family.h>
35+
#include "../drivers/thermal/intel/thermal_interrupt.h"
3536

3637
#define INTEL_PSTATE_SAMPLING_INTERVAL (10 * NSEC_PER_MSEC)
3738

@@ -219,6 +220,7 @@ struct global_params {
219220
* @sched_flags: Store scheduler flags for possible cross CPU update
220221
* @hwp_boost_min: Last HWP boosted min performance
221222
* @suspended: Whether or not the driver has been suspended.
223+
* @hwp_notify_work: workqueue for HWP notifications.
222224
*
223225
* This structure stores per CPU instance data for all CPUs.
224226
*/
@@ -257,6 +259,7 @@ struct cpudata {
257259
unsigned int sched_flags;
258260
u32 hwp_boost_min;
259261
bool suspended;
262+
struct delayed_work hwp_notify_work;
260263
};
261264

262265
static struct cpudata **all_cpu_data;
@@ -1625,6 +1628,40 @@ static void intel_pstate_sysfs_hide_hwp_dynamic_boost(void)
16251628

16261629
/************************** sysfs end ************************/
16271630

1631+
static void intel_pstate_notify_work(struct work_struct *work)
1632+
{
1633+
mutex_lock(&intel_pstate_driver_lock);
1634+
cpufreq_update_policy(smp_processor_id());
1635+
wrmsrl(MSR_HWP_STATUS, 0);
1636+
mutex_unlock(&intel_pstate_driver_lock);
1637+
}
1638+
1639+
void notify_hwp_interrupt(void)
1640+
{
1641+
unsigned int this_cpu = smp_processor_id();
1642+
struct cpudata *cpudata;
1643+
u64 value;
1644+
1645+
if (!hwp_active || !boot_cpu_has(X86_FEATURE_HWP_NOTIFY))
1646+
return;
1647+
1648+
rdmsrl(MSR_HWP_STATUS, value);
1649+
if (!(value & 0x01))
1650+
return;
1651+
1652+
cpudata = all_cpu_data[this_cpu];
1653+
schedule_delayed_work_on(this_cpu, &cpudata->hwp_notify_work, msecs_to_jiffies(10));
1654+
}
1655+
1656+
static void intel_pstate_enable_hwp_interrupt(struct cpudata *cpudata)
1657+
{
1658+
/* Enable HWP notification interrupt for guaranteed performance change */
1659+
if (boot_cpu_has(X86_FEATURE_HWP_NOTIFY)) {
1660+
INIT_DELAYED_WORK(&cpudata->hwp_notify_work, intel_pstate_notify_work);
1661+
wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x01);
1662+
}
1663+
}
1664+
16281665
static void intel_pstate_hwp_enable(struct cpudata *cpudata)
16291666
{
16301667
/* First disable HWP notification interrupt as we don't process them */
@@ -1634,6 +1671,8 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
16341671
wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
16351672
if (cpudata->epp_default == -EINVAL)
16361673
cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
1674+
1675+
intel_pstate_enable_hwp_interrupt(cpudata);
16371676
}
16381677

16391678
static int atom_get_min_pstate(void)
@@ -2969,7 +3008,7 @@ static void intel_pstate_driver_cleanup(void)
29693008
{
29703009
unsigned int cpu;
29713010

2972-
get_online_cpus();
3011+
cpus_read_lock();
29733012
for_each_online_cpu(cpu) {
29743013
if (all_cpu_data[cpu]) {
29753014
if (intel_pstate_driver == &intel_pstate)
@@ -2979,7 +3018,7 @@ static void intel_pstate_driver_cleanup(void)
29793018
all_cpu_data[cpu] = NULL;
29803019
}
29813020
}
2982-
put_online_cpus();
3021+
cpus_read_unlock();
29833022

29843023
intel_pstate_driver = NULL;
29853024
}

drivers/cpufreq/powernow-k8.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,18 +1180,18 @@ static int powernowk8_init(void)
11801180
if (!x86_match_cpu(powernow_k8_ids))
11811181
return -ENODEV;
11821182

1183-
get_online_cpus();
1183+
cpus_read_lock();
11841184
for_each_online_cpu(i) {
11851185
smp_call_function_single(i, check_supported_cpu, &ret, 1);
11861186
if (!ret)
11871187
supported_cpus++;
11881188
}
11891189

11901190
if (supported_cpus != num_online_cpus()) {
1191-
put_online_cpus();
1191+
cpus_read_unlock();
11921192
return -ENODEV;
11931193
}
1194-
put_online_cpus();
1194+
cpus_read_unlock();
11951195

11961196
ret = cpufreq_register_driver(&cpufreq_amd64_driver);
11971197
if (ret)

drivers/cpufreq/powernv-cpufreq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ static void powernv_cpufreq_work_fn(struct work_struct *work)
918918
unsigned int cpu;
919919
cpumask_t mask;
920920

921-
get_online_cpus();
921+
cpus_read_lock();
922922
cpumask_and(&mask, &chip->mask, cpu_online_mask);
923923
smp_call_function_any(&mask,
924924
powernv_cpufreq_throttle_check, NULL, 0);
@@ -939,7 +939,7 @@ static void powernv_cpufreq_work_fn(struct work_struct *work)
939939
cpufreq_cpu_put(policy);
940940
}
941941
out:
942-
put_online_cpus();
942+
cpus_read_unlock();
943943
}
944944

945945
static int powernv_cpufreq_occ_msg(struct notifier_block *nb,

drivers/opp/of.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,7 @@ static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
9595
static struct device_node *of_parse_required_opp(struct device_node *np,
9696
int index)
9797
{
98-
struct device_node *required_np;
99-
100-
required_np = of_parse_phandle(np, "required-opps", index);
101-
if (unlikely(!required_np)) {
102-
pr_err("%s: Unable to parse required-opps: %pOF, index: %d\n",
103-
__func__, np, index);
104-
}
105-
106-
return required_np;
98+
return of_parse_phandle(np, "required-opps", index);
10799
}
108100

109101
/* The caller must call dev_pm_opp_put_opp_table() after the table is used */
@@ -1328,7 +1320,7 @@ int of_get_required_opp_performance_state(struct device_node *np, int index)
13281320

13291321
required_np = of_parse_required_opp(np, index);
13301322
if (!required_np)
1331-
return -EINVAL;
1323+
return -ENODEV;
13321324

13331325
opp_table = _find_table_of_opp_np(required_np);
13341326
if (IS_ERR(opp_table)) {

0 commit comments

Comments
 (0)