Skip to content

Commit 0c67f6b

Browse files
committed
Merge tag 'pm-5.8-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki: "These are operating performance points (OPP) framework updates mostly, including support for interconnect bandwidth in the OPP core, plus a few cpufreq changes, including boost support in the CPPC cpufreq driver, an ACPI device power management fix and a hibernation code cleanup. Specifics: - Add support for interconnect bandwidth to the OPP core (Georgi Djakov, Saravana Kannan, Sibi Sankar, Viresh Kumar). - Add support for regulator enable/disable to the OPP core (Kamil Konieczny). - Add boost support to the CPPC cpufreq driver (Xiongfeng Wang). - Make the tegra186 cpufreq driver set the CPUFREQ_NEED_INITIAL_FREQ_CHECK flag (Mian Yousaf Kaukab). - Prevent the ACPI power management from using power resources with devices where the list of power resources for power state D0 (full power) is missing (Rafael Wysocki). - Annotate a hibernation-related function with __init (Christophe JAILLET)" * tag 'pm-5.8-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: PM: Avoid using power resources if there are none for D0 cpufreq: CPPC: add SW BOOST support cpufreq: change '.set_boost' to act on one policy PM: hibernate: Add __init annotation to swsusp_header_init() opp: Don't parse icc paths unnecessarily opp: Remove bandwidth votes when target_freq is zero opp: core: add regulators enable and disable opp: Reorder the code for !target_freq case opp: Expose bandwidth information via debugfs cpufreq: dt: Add support for interconnect bandwidth scaling opp: Update the bandwidth on OPP frequency changes opp: Add sanity checks in _read_opp_key() opp: Add support for parsing interconnect bandwidth cpufreq: tegra186: add CPUFREQ_NEED_INITIAL_FREQ_CHECK flag OPP: Add helpers for reading the binding properties dt-bindings: opp: Introduce opp-peak-kBps and opp-avg-kBps bindings
2 parents 49f13b0 + 50dd154 commit 0c67f6b

File tree

18 files changed

+511
-79
lines changed

18 files changed

+511
-79
lines changed

Documentation/devicetree/bindings/opp/opp.txt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,14 @@ properties.
8383

8484
Required properties:
8585
- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. This is a
86-
required property for all device nodes but devices like power domains. The
87-
power domain nodes must have another (implementation dependent) property which
88-
uniquely identifies the OPP nodes.
86+
required property for all device nodes, unless another "required" property to
87+
uniquely identify the OPP nodes exists. Devices like power domains must have
88+
another (implementation dependent) property.
89+
90+
- opp-peak-kBps: Peak bandwidth in kilobytes per second, expressed as an array
91+
of 32-bit big-endian integers. Each element of the array represents the
92+
peak bandwidth value of each interconnect path. The number of elements should
93+
match the number of interconnect paths.
8994

9095
Optional properties:
9196
- opp-microvolt: voltage in micro Volts.
@@ -132,6 +137,12 @@ Optional properties:
132137
- opp-level: A value representing the performance level of the device,
133138
expressed as a 32-bit integer.
134139

140+
- opp-avg-kBps: Average bandwidth in kilobytes per second, expressed as an array
141+
of 32-bit big-endian integers. Each element of the array represents the
142+
average bandwidth value of each interconnect path. The number of elements
143+
should match the number of interconnect paths. This property is only
144+
meaningful in OPP tables where opp-peak-kBps is present.
145+
135146
- clock-latency-ns: Specifies the maximum possible transition latency (in
136147
nanoseconds) for switching to this OPP from any other OPP.
137148

Documentation/devicetree/bindings/property-units.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,7 @@ Temperature
4141
Pressure
4242
----------------------------------------
4343
-kpascal : kilopascal
44+
45+
Throughput
46+
----------------------------------------
47+
-kBps : kilobytes per second

drivers/acpi/device_pm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ int acpi_device_set_power(struct acpi_device *device, int state)
186186
* possibly drop references to the power resources in use.
187187
*/
188188
state = ACPI_STATE_D3_HOT;
189-
/* If _PR3 is not available, use D3hot as the target state. */
189+
/* If D3cold is not supported, use D3hot as the target state. */
190190
if (!device->power.states[ACPI_STATE_D3_COLD].flags.valid)
191191
target_state = state;
192192
} else if (!device->power.states[state].flags.valid) {

drivers/acpi/scan.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -918,12 +918,9 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
918918

919919
if (buffer.length && package
920920
&& package->type == ACPI_TYPE_PACKAGE
921-
&& package->package.count) {
922-
int err = acpi_extract_power_resources(package, 0,
923-
&ps->resources);
924-
if (!err)
925-
device->power.flags.power_resources = 1;
926-
}
921+
&& package->package.count)
922+
acpi_extract_power_resources(package, 0, &ps->resources);
923+
927924
ACPI_FREE(buffer.pointer);
928925
}
929926

@@ -970,14 +967,27 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
970967
acpi_bus_init_power_state(device, i);
971968

972969
INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources);
973-
if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
974-
device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
975970

976-
/* Set defaults for D0 and D3hot states (always valid) */
971+
/* Set the defaults for D0 and D3hot (always supported). */
977972
device->power.states[ACPI_STATE_D0].flags.valid = 1;
978973
device->power.states[ACPI_STATE_D0].power = 100;
979974
device->power.states[ACPI_STATE_D3_HOT].flags.valid = 1;
980975

976+
/*
977+
* Use power resources only if the D0 list of them is populated, because
978+
* some platforms may provide _PR3 only to indicate D3cold support and
979+
* in those cases the power resources list returned by it may be bogus.
980+
*/
981+
if (!list_empty(&device->power.states[ACPI_STATE_D0].resources)) {
982+
device->power.flags.power_resources = 1;
983+
/*
984+
* D3cold is supported if the D3hot list of power resources is
985+
* not empty.
986+
*/
987+
if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
988+
device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
989+
}
990+
981991
if (acpi_bus_init_power(device))
982992
device->flags.power_manageable = 0;
983993
}

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ static void boost_set_msr_each(void *p_en)
126126
boost_set_msr(enable);
127127
}
128128

129-
static int set_boost(int val)
129+
static int set_boost(struct cpufreq_policy *policy, int val)
130130
{
131-
get_online_cpus();
132-
on_each_cpu(boost_set_msr_each, (void *)(long)val, 1);
133-
put_online_cpus();
134-
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
131+
on_each_cpu_mask(policy->cpus, boost_set_msr_each,
132+
(void *)(long)val, 1);
133+
pr_debug("CPU %*pbl: Core Boosting %sabled.\n",
134+
cpumask_pr_args(policy->cpus), val ? "en" : "dis");
135135

136136
return 0;
137137
}
@@ -162,7 +162,9 @@ static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
162162
if (ret || val > 1)
163163
return -EINVAL;
164164

165-
set_boost(val);
165+
get_online_cpus();
166+
set_boost(policy, val);
167+
put_online_cpus();
166168

167169
return count;
168170
}

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* requested etc.
3838
*/
3939
static struct cppc_cpudata **all_cpu_data;
40+
static bool boost_supported;
4041

4142
struct cppc_workaround_oem_info {
4243
char oem_id[ACPI_OEM_ID_SIZE + 1];
@@ -310,15 +311,15 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
310311
* Section 8.4.7.1.1.5 of ACPI 6.1 spec)
311312
*/
312313
policy->min = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_nonlinear_perf);
313-
policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
314+
policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf);
314315

315316
/*
316317
* Set cpuinfo.min_freq to Lowest to make the full range of performance
317318
* available if userspace wants to use any perf between lowest & lowest
318319
* nonlinear perf
319320
*/
320321
policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_perf);
321-
policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
322+
policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf);
322323

323324
policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num);
324325
policy->shared_type = cpu->shared_type;
@@ -343,6 +344,13 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
343344

344345
cpu->cur_policy = policy;
345346

347+
/*
348+
* If 'highest_perf' is greater than 'nominal_perf', we assume CPU Boost
349+
* is supported.
350+
*/
351+
if (cpu->perf_caps.highest_perf > cpu->perf_caps.nominal_perf)
352+
boost_supported = true;
353+
346354
/* Set policy->cur to max now. The governors will adjust later. */
347355
policy->cur = cppc_cpufreq_perf_to_khz(cpu,
348356
cpu->perf_caps.highest_perf);
@@ -410,13 +418,40 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum)
410418
return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1);
411419
}
412420

421+
static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
422+
{
423+
struct cppc_cpudata *cpudata;
424+
int ret;
425+
426+
if (!boost_supported) {
427+
pr_err("BOOST not supported by CPU or firmware\n");
428+
return -EINVAL;
429+
}
430+
431+
cpudata = all_cpu_data[policy->cpu];
432+
if (state)
433+
policy->max = cppc_cpufreq_perf_to_khz(cpudata,
434+
cpudata->perf_caps.highest_perf);
435+
else
436+
policy->max = cppc_cpufreq_perf_to_khz(cpudata,
437+
cpudata->perf_caps.nominal_perf);
438+
policy->cpuinfo.max_freq = policy->max;
439+
440+
ret = freq_qos_update_request(policy->max_freq_req, policy->max);
441+
if (ret < 0)
442+
return ret;
443+
444+
return 0;
445+
}
446+
413447
static struct cpufreq_driver cppc_cpufreq_driver = {
414448
.flags = CPUFREQ_CONST_LOOPS,
415449
.verify = cppc_verify_policy,
416450
.target = cppc_cpufreq_set_target,
417451
.get = cppc_cpufreq_get_rate,
418452
.init = cppc_cpufreq_cpu_init,
419453
.stop_cpu = cppc_cpufreq_stop_cpu,
454+
.set_boost = cppc_cpufreq_set_boost,
420455
.name = "cppc_cpufreq",
421456
};
422457

drivers/cpufreq/cpufreq-dt.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ static int resources_available(void)
121121

122122
clk_put(cpu_clk);
123123

124+
ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
125+
if (ret)
126+
return ret;
127+
124128
name = find_supply_name(cpu_dev);
125129
/* Platform doesn't require regulator */
126130
if (!name)

drivers/cpufreq/cpufreq.c

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,34 +2532,29 @@ EXPORT_SYMBOL_GPL(cpufreq_update_limits);
25322532
/*********************************************************************
25332533
* BOOST *
25342534
*********************************************************************/
2535-
static int cpufreq_boost_set_sw(int state)
2535+
static int cpufreq_boost_set_sw(struct cpufreq_policy *policy, int state)
25362536
{
2537-
struct cpufreq_policy *policy;
2538-
2539-
for_each_active_policy(policy) {
2540-
int ret;
2537+
int ret;
25412538

2542-
if (!policy->freq_table)
2543-
return -ENXIO;
2539+
if (!policy->freq_table)
2540+
return -ENXIO;
25442541

2545-
ret = cpufreq_frequency_table_cpuinfo(policy,
2546-
policy->freq_table);
2547-
if (ret) {
2548-
pr_err("%s: Policy frequency update failed\n",
2549-
__func__);
2550-
return ret;
2551-
}
2552-
2553-
ret = freq_qos_update_request(policy->max_freq_req, policy->max);
2554-
if (ret < 0)
2555-
return ret;
2542+
ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table);
2543+
if (ret) {
2544+
pr_err("%s: Policy frequency update failed\n", __func__);
2545+
return ret;
25562546
}
25572547

2548+
ret = freq_qos_update_request(policy->max_freq_req, policy->max);
2549+
if (ret < 0)
2550+
return ret;
2551+
25582552
return 0;
25592553
}
25602554

25612555
int cpufreq_boost_trigger_state(int state)
25622556
{
2557+
struct cpufreq_policy *policy;
25632558
unsigned long flags;
25642559
int ret = 0;
25652560

@@ -2570,15 +2565,25 @@ int cpufreq_boost_trigger_state(int state)
25702565
cpufreq_driver->boost_enabled = state;
25712566
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
25722567

2573-
ret = cpufreq_driver->set_boost(state);
2574-
if (ret) {
2575-
write_lock_irqsave(&cpufreq_driver_lock, flags);
2576-
cpufreq_driver->boost_enabled = !state;
2577-
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
2578-
2579-
pr_err("%s: Cannot %s BOOST\n",
2580-
__func__, state ? "enable" : "disable");
2568+
get_online_cpus();
2569+
for_each_active_policy(policy) {
2570+
ret = cpufreq_driver->set_boost(policy, state);
2571+
if (ret)
2572+
goto err_reset_state;
25812573
}
2574+
put_online_cpus();
2575+
2576+
return 0;
2577+
2578+
err_reset_state:
2579+
put_online_cpus();
2580+
2581+
write_lock_irqsave(&cpufreq_driver_lock, flags);
2582+
cpufreq_driver->boost_enabled = !state;
2583+
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
2584+
2585+
pr_err("%s: Cannot %s BOOST\n",
2586+
__func__, state ? "enable" : "disable");
25822587

25832588
return ret;
25842589
}

drivers/cpufreq/tegra186-cpufreq.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy,
9393

9494
static struct cpufreq_driver tegra186_cpufreq_driver = {
9595
.name = "tegra186",
96-
.flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
96+
.flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
97+
CPUFREQ_NEED_INITIAL_FREQ_CHECK,
9798
.verify = cpufreq_generic_frequency_table_verify,
9899
.target_index = tegra186_cpufreq_set_target,
99100
.init = tegra186_cpufreq_init,

drivers/interconnect/core.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,24 @@ void icc_set_tag(struct icc_path *path, u32 tag)
543543
}
544544
EXPORT_SYMBOL_GPL(icc_set_tag);
545545

546+
/**
547+
* icc_get_name() - Get name of the icc path
548+
* @path: reference to the path returned by icc_get()
549+
*
550+
* This function is used by an interconnect consumer to get the name of the icc
551+
* path.
552+
*
553+
* Returns a valid pointer on success, or NULL otherwise.
554+
*/
555+
const char *icc_get_name(struct icc_path *path)
556+
{
557+
if (!path)
558+
return NULL;
559+
560+
return path->name;
561+
}
562+
EXPORT_SYMBOL_GPL(icc_get_name);
563+
546564
/**
547565
* icc_set_bw() - set bandwidth constraints on an interconnect path
548566
* @path: reference to the path returned by icc_get()

0 commit comments

Comments
 (0)