Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
Merge tag 'pm-5.14-rc1-2' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
 "These include cpufreq core simplifications and fixes, cpufreq driver
  updates, cpuidle driver update, a generic power domains (genpd)
  locking fix and a debug-related simplification of the PM core.

  Specifics:

   - Drop the ->stop_cpu() (not really useful) and ->resolve_freq()
     (unused) cpufreq driver callbacks and modify the users of the
     former accordingly (Viresh Kumar, Rafael Wysocki).

   - Add frequency invariance support to the ACPI CPPC cpufreq driver
     again along with the related fixes and cleanups (Viresh Kumar).

   - Update the Meditak, qcom and SCMI ARM cpufreq drivers (Fabien
     Parent, Seiya Wang, Sibi Sankar, Christophe JAILLET).

   - Rename black/white-lists in the DT cpufreq driver (Viresh Kumar).

   - Add generic performance domains support to the dvfs DT bindings
     (Sudeep Holla).

   - Refine locking in the generic power domains (genpd) support code to
     avoid lock dependency issues (Stephen Boyd).

   - Update the MSM and qcom ARM cpuidle drivers (Bartosz Dudziak).

   - Simplify the PM core debug code by using ktime_us_delta() to
     compute time interval lengths (Mark-PK Tsai)"

* tag 'pm-5.14-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (21 commits)
  PM: domains: Shrink locking area of the gpd_list_lock
  PM: sleep: Use ktime_us_delta() in initcall_debug_report()
  cpufreq: CPPC: Add support for frequency invariance
  arch_topology: Avoid use-after-free for scale_freq_data
  cpufreq: CPPC: Pass structure instance by reference
  cpufreq: CPPC: Fix potential memleak in cppc_cpufreq_cpu_init
  cpufreq: Remove ->resolve_freq()
  cpufreq: Reuse cpufreq_driver_resolve_freq() in __cpufreq_driver_target()
  cpufreq: Remove the ->stop_cpu() driver callback
  cpufreq: powernv: Migrate to ->exit() callback instead of ->stop_cpu()
  cpufreq: CPPC: Migrate to ->exit() callback instead of ->stop_cpu()
  cpufreq: intel_pstate: Combine ->stop_cpu() and ->offline()
  cpuidle: qcom: Add SPM register data for MSM8226
  dt-bindings: arm: msm: Add SAW2 for MSM8226
  dt-bindings: cpufreq: update cpu type and clock name for MT8173 SoC
  clk: mediatek: remove deprecated CLK_INFRA_CA57SEL for MT8173 SoC
  cpufreq: dt: Rename black/white-lists
  cpufreq: scmi: Fix an error message
  cpufreq: mediatek: add support for mt8365
  dt-bindings: dvfs: Add support for generic performance domains
  ...
  • Loading branch information
torvalds committed Jul 7, 2021
2 parents c6e8c51 + 843372d commit aef4226
Show file tree
Hide file tree
Showing 22 changed files with 474 additions and 149 deletions.
6 changes: 0 additions & 6 deletions Documentation/cpu-freq/cpu-drivers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ And optionally

.driver_data - cpufreq driver specific data.

.resolve_freq - Returns the most appropriate frequency for a target
frequency. Doesn't change the frequency though.

.get_intermediate and target_intermediate - Used to switch to stable
frequency while changing CPU frequency.

Expand All @@ -71,9 +68,6 @@ And optionally
.exit - A pointer to a per-policy cleanup function called during
CPU_POST_DEAD phase of cpu hotplug process.

.stop_cpu - A pointer to a per-policy stop function called during
CPU_DOWN_PREPARE phase of cpu hotplug process.

.suspend - A pointer to a per-policy suspend function which is called
with interrupts disabled and _after_ the governor is stopped for the
policy.
Expand Down
7 changes: 7 additions & 0 deletions Documentation/devicetree/bindings/arm/cpus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,13 @@ properties:

where voltage is in V, frequency is in MHz.

performance-domains:
maxItems: 1
description:
List of phandles and performance domain specifiers, as defined by
bindings of the performance domain provider. See also
dvfs/performance-domain.yaml.

power-domains:
description:
List of phandles and PM domain specifiers, as defined by bindings of the
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ PROPERTIES
"qcom,saw2"
A more specific value could be one of:
"qcom,apq8064-saw2-v1.1-cpu"
"qcom,msm8226-saw2-v2.1-cpu"
"qcom,msm8974-saw2-v2.1-cpu"
"qcom,apq8084-saw2-v2.1-cpu"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,23 @@ Example 2 (MT8173 SoC):

cpu2: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a57";
compatible = "arm,cortex-a72";
reg = <0x100>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0>;
clocks = <&infracfg CLK_INFRA_CA57SEL>,
clocks = <&infracfg CLK_INFRA_CA72SEL>,
<&apmixedsys CLK_APMIXED_MAINPLL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cpu_opp_table_b>;
};

cpu3: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a57";
compatible = "arm,cortex-a72";
reg = <0x101>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0>;
clocks = <&infracfg CLK_INFRA_CA57SEL>,
clocks = <&infracfg CLK_INFRA_CA72SEL>,
<&apmixedsys CLK_APMIXED_MAINPLL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cpu_opp_table_b>;
Expand Down
74 changes: 74 additions & 0 deletions Documentation/devicetree/bindings/dvfs/performance-domain.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/dvfs/performance-domain.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Generic performance domains

maintainers:
- Sudeep Holla <[email protected]>

description: |+
This binding is intended for performance management of groups of devices or
CPUs that run in the same performance domain. Performance domains must not
be confused with power domains. A performance domain is defined by a set
of devices that always have to run at the same performance level. For a given
performance domain, there is a single point of control that affects all the
devices in the domain, making it impossible to set the performance level of
an individual device in the domain independently from other devices in
that domain. For example, a set of CPUs that share a voltage domain, and
have a common frequency control, is said to be in the same performance
domain.
This device tree binding can be used to bind performance domain consumer
devices with their performance domains provided by performance domain
providers. A performance domain provider can be represented by any node in
the device tree and can provide one or more performance domains. A consumer
node can refer to the provider by a phandle and a set of phandle arguments
(so called performance domain specifiers) of length specified by the
\#performance-domain-cells property in the performance domain provider node.
select: true

properties:
"#performance-domain-cells":
description:
Number of cells in a performance domain specifier. Typically 0 for nodes
representing a single performance domain and 1 for nodes providing
multiple performance domains (e.g. performance controllers), but can be
any value as specified by device tree binding documentation of particular
provider.
enum: [ 0, 1 ]

performance-domains:
$ref: '/schemas/types.yaml#/definitions/phandle-array'
maxItems: 1
description:
A phandle and performance domain specifier as defined by bindings of the
performance controller/provider specified by phandle.

additionalProperties: true

examples:
- |
performance: performance-controller@12340000 {
compatible = "qcom,cpufreq-hw";
reg = <0x12340000 0x1000>;
#performance-domain-cells = <1>;
};
// The node above defines a performance controller that is a performance
// domain provider and expects one cell as its phandle argument.
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a57";
reg = <0x0 0x0>;
performance-domains = <&performance 1>;
};
};
5 changes: 0 additions & 5 deletions Documentation/translations/zh_CN/cpu-freq/cpu-drivers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ CPUfreq核心层注册一个cpufreq_driver结构体。

.driver_data - cpufreq驱动程序的特定数据。

.resolve_freq - 返回最适合目标频率的频率。不过并不能改变频率。

.get_intermediate 和 target_intermediate - 用于在改变CPU频率时切换到稳定
的频率。

Expand All @@ -76,9 +74,6 @@ CPUfreq核心层注册一个cpufreq_driver结构体。
.exit - 一个指向per-policy清理函数的指针,该函数在cpu热插拔过程的CPU_POST_DEAD
阶段被调用。

.stop_cpu - 一个指向per-policy停止函数的指针,该函数在cpu热插拔过程的CPU_DOWN_PREPARE
阶段被调用。

.suspend - 一个指向per-policy暂停函数的指针,该函数在关中断且在该策略的调节器停止
后被调用。

Expand Down
27 changes: 21 additions & 6 deletions drivers/base/arch_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/smp.h>

static DEFINE_PER_CPU(struct scale_freq_data *, sft_data);
static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
static struct cpumask scale_freq_counters_mask;
static bool scale_freq_invariant;

Expand Down Expand Up @@ -66,16 +67,20 @@ void topology_set_scale_freq_source(struct scale_freq_data *data,
if (cpumask_empty(&scale_freq_counters_mask))
scale_freq_invariant = topology_scale_freq_invariant();

rcu_read_lock();

for_each_cpu(cpu, cpus) {
sfd = per_cpu(sft_data, cpu);
sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu));

/* Use ARCH provided counters whenever possible */
if (!sfd || sfd->source != SCALE_FREQ_SOURCE_ARCH) {
per_cpu(sft_data, cpu) = data;
rcu_assign_pointer(per_cpu(sft_data, cpu), data);
cpumask_set_cpu(cpu, &scale_freq_counters_mask);
}
}

rcu_read_unlock();

update_scale_freq_invariant(true);
}
EXPORT_SYMBOL_GPL(topology_set_scale_freq_source);
Expand All @@ -86,22 +91,32 @@ void topology_clear_scale_freq_source(enum scale_freq_source source,
struct scale_freq_data *sfd;
int cpu;

rcu_read_lock();

for_each_cpu(cpu, cpus) {
sfd = per_cpu(sft_data, cpu);
sfd = rcu_dereference(*per_cpu_ptr(&sft_data, cpu));

if (sfd && sfd->source == source) {
per_cpu(sft_data, cpu) = NULL;
rcu_assign_pointer(per_cpu(sft_data, cpu), NULL);
cpumask_clear_cpu(cpu, &scale_freq_counters_mask);
}
}

rcu_read_unlock();

/*
* Make sure all references to previous sft_data are dropped to avoid
* use-after-free races.
*/
synchronize_rcu();

update_scale_freq_invariant(false);
}
EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source);

void topology_scale_freq_tick(void)
{
struct scale_freq_data *sfd = *this_cpu_ptr(&sft_data);
struct scale_freq_data *sfd = rcu_dereference_sched(*this_cpu_ptr(&sft_data));

if (sfd)
sfd->set_freq_scale();
Expand Down
38 changes: 17 additions & 21 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -2018,8 +2018,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,

mutex_lock(&gpd_list_lock);
list_add(&genpd->gpd_list_node, &gpd_list);
genpd_debug_add(genpd);
mutex_unlock(&gpd_list_lock);
genpd_debug_add(genpd);

return 0;
}
Expand Down Expand Up @@ -2206,12 +2206,19 @@ static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,

static bool genpd_present(const struct generic_pm_domain *genpd)
{
bool ret = false;
const struct generic_pm_domain *gpd;

list_for_each_entry(gpd, &gpd_list, gpd_list_node)
if (gpd == genpd)
return true;
return false;
mutex_lock(&gpd_list_lock);
list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
if (gpd == genpd) {
ret = true;
break;
}
}
mutex_unlock(&gpd_list_lock);

return ret;
}

/**
Expand All @@ -2222,15 +2229,13 @@ static bool genpd_present(const struct generic_pm_domain *genpd)
int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
{
int ret = -EINVAL;
int ret;

if (!np || !genpd)
return -EINVAL;

mutex_lock(&gpd_list_lock);

if (!genpd_present(genpd))
goto unlock;
return -EINVAL;

genpd->dev.of_node = np;

Expand All @@ -2241,7 +2246,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
if (ret != -EPROBE_DEFER)
dev_err(&genpd->dev, "Failed to add OPP table: %d\n",
ret);
goto unlock;
return ret;
}

/*
Expand All @@ -2259,16 +2264,13 @@ int of_genpd_add_provider_simple(struct device_node *np,
dev_pm_opp_of_remove_table(&genpd->dev);
}

goto unlock;
return ret;
}

genpd->provider = &np->fwnode;
genpd->has_provider = true;

unlock:
mutex_unlock(&gpd_list_lock);

return ret;
return 0;
}
EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);

Expand All @@ -2287,8 +2289,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
if (!np || !data)
return -EINVAL;

mutex_lock(&gpd_list_lock);

if (!data->xlate)
data->xlate = genpd_xlate_onecell;

Expand Down Expand Up @@ -2328,8 +2328,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
if (ret < 0)
goto error;

mutex_unlock(&gpd_list_lock);

return 0;

error:
Expand All @@ -2348,8 +2346,6 @@ int of_genpd_add_provider_onecell(struct device_node *np,
}
}

mutex_unlock(&gpd_list_lock);

return ret;
}
EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
Expand Down
5 changes: 1 addition & 4 deletions drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,13 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
void *cb, int error)
{
ktime_t rettime;
s64 nsecs;

if (!pm_print_times_enabled)
return;

rettime = ktime_get();
nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));

dev_info(dev, "%pS returned %d after %Ld usecs\n", cb, error,
(unsigned long long)nsecs >> 10);
(unsigned long long)ktime_us_delta(rettime, calltime));
}

/**
Expand Down
10 changes: 10 additions & 0 deletions drivers/cpufreq/Kconfig.arm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ config ACPI_CPPC_CPUFREQ

If in doubt, say N.

config ACPI_CPPC_CPUFREQ_FIE
bool "Frequency Invariance support for CPPC cpufreq driver"
depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
default y
help
This extends frequency invariance support in the CPPC cpufreq driver,
by using CPPC delivered and reference performance counters.

If in doubt, say N.

config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
tristate "Allwinner nvmem based SUN50I CPUFreq driver"
depends on ARCH_SUNXI
Expand Down
Loading

0 comments on commit aef4226

Please sign in to comment.