提交 dbb3c260 编写于 作者: L Linus Torvalds

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

Pull power management fixes from Rafael Wysocki:
 "These remove a stale DT entry left behind after recent removal of a
  cpufreq driver without users, fix up error handling in the imx6q
  cpufreq driver, fix two issues in the cpufreq documentation, and
  update the ARM cpufreq driver.

  Specifics:

   - Drop stale DT binding for the arm_big_little_dt driver removed
     recently (Sudeep Holla).

   - Fix up error handling in the imx6q cpufreq driver to make it report
     voltage scaling failures (Anson Huang).

   - Fix two issues in the cpufreq documentation (Viresh Kumar, Zhao Wei
     Liew).

   - Fix ARM cpuidle driver initialization regression from the 4.19 time
     frame and rework the driver registration part of it to simplify
     code (Ulf Hansson)"

* tag 'pm-4.20-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ARM: cpuidle: Convert to use cpuidle_register|unregister()
  ARM: cpuidle: Don't register the driver when back-end init returns -ENXIO
  dt-bindings: cpufreq: remove stale arm_big_little_dt entry
  Documentation: cpufreq: Correct a typo
  cpufreq: imx6q: add return value check for voltage scale
  Documentation: cpu-freq: Frequencies aren't always sorted
...@@ -150,7 +150,7 @@ data structures necessary to handle the given policy and, possibly, to add ...@@ -150,7 +150,7 @@ data structures necessary to handle the given policy and, possibly, to add
a governor ``sysfs`` interface to it. Next, the governor is started by a governor ``sysfs`` interface to it. Next, the governor is started by
invoking its ``->start()`` callback. invoking its ``->start()`` callback.
That callback it expected to register per-CPU utilization update callbacks for That callback is expected to register per-CPU utilization update callbacks for
all of the online CPUs belonging to the given policy with the CPU scheduler. all of the online CPUs belonging to the given policy with the CPU scheduler.
The utilization update callbacks will be invoked by the CPU scheduler on The utilization update callbacks will be invoked by the CPU scheduler on
important events, like task enqueue and dequeue, on every iteration of the important events, like task enqueue and dequeue, on every iteration of the
......
...@@ -86,9 +86,11 @@ transitions. ...@@ -86,9 +86,11 @@ transitions.
This will give a fine grained information about all the CPU frequency This will give a fine grained information about all the CPU frequency
transitions. The cat output here is a two dimensional matrix, where an entry transitions. The cat output here is a two dimensional matrix, where an entry
<i,j> (row i, column j) represents the count of number of transitions from <i,j> (row i, column j) represents the count of number of transitions from
Freq_i to Freq_j. Freq_i is in descending order with increasing rows and Freq_i to Freq_j. Freq_i rows and Freq_j columns follow the sorting order in
Freq_j is in descending order with increasing columns. The output here also which the driver has provided the frequency table initially to the cpufreq core
contains the actual freq values for each row and column for better readability. and so can be sorted (ascending or descending) or unsorted. The output here
also contains the actual freq values for each row and column for better
readability.
If the transition table is bigger than PAGE_SIZE, reading this will If the transition table is bigger than PAGE_SIZE, reading this will
return an -EFBIG error. return an -EFBIG error.
......
Generic ARM big LITTLE cpufreq driver's DT glue
-----------------------------------------------
This is DT specific glue layer for generic cpufreq driver for big LITTLE
systems.
Both required and optional properties listed below must be defined
under node /cpus/cpu@x. Where x is the first cpu inside a cluster.
FIXME: Cpus should boot in the order specified in DT and all cpus for a cluster
must be present contiguously. Generic DT driver will check only node 'x' for
cpu:x.
Required properties:
- operating-points: Refer to Documentation/devicetree/bindings/opp/opp.txt
for details
Optional properties:
- clock-latency: Specify the possible maximum transition latency for clock,
in unit of nanoseconds.
Examples:
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a15";
reg = <0>;
next-level-cache = <&L2>;
operating-points = <
/* kHz uV */
792000 1100000
396000 950000
198000 850000
>;
clock-latency = <61036>; /* two CLK32 periods */
};
cpu@1 {
compatible = "arm,cortex-a15";
reg = <1>;
next-level-cache = <&L2>;
};
cpu@100 {
compatible = "arm,cortex-a7";
reg = <100>;
next-level-cache = <&L2>;
operating-points = <
/* kHz uV */
792000 950000
396000 750000
198000 450000
>;
clock-latency = <61036>; /* two CLK32 periods */
};
cpu@101 {
compatible = "arm,cortex-a7";
reg = <101>;
next-level-cache = <&L2>;
};
};
...@@ -160,8 +160,13 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -160,8 +160,13 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
/* Ensure the arm clock divider is what we expect */ /* Ensure the arm clock divider is what we expect */
ret = clk_set_rate(clks[ARM].clk, new_freq * 1000); ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);
if (ret) { if (ret) {
int ret1;
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
regulator_set_voltage_tol(arm_reg, volt_old, 0); ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0);
if (ret1)
dev_warn(cpu_dev,
"failed to restore vddarm voltage: %d\n", ret1);
return ret; return ret;
} }
......
...@@ -82,7 +82,6 @@ static int __init arm_idle_init_cpu(int cpu) ...@@ -82,7 +82,6 @@ static int __init arm_idle_init_cpu(int cpu)
{ {
int ret; int ret;
struct cpuidle_driver *drv; struct cpuidle_driver *drv;
struct cpuidle_device *dev;
drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL); drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL);
if (!drv) if (!drv)
...@@ -103,13 +102,6 @@ static int __init arm_idle_init_cpu(int cpu) ...@@ -103,13 +102,6 @@ static int __init arm_idle_init_cpu(int cpu)
goto out_kfree_drv; goto out_kfree_drv;
} }
ret = cpuidle_register_driver(drv);
if (ret) {
if (ret != -EBUSY)
pr_err("Failed to register cpuidle driver\n");
goto out_kfree_drv;
}
/* /*
* Call arch CPU operations in order to initialize * Call arch CPU operations in order to initialize
* idle states suspend back-end specific data * idle states suspend back-end specific data
...@@ -117,37 +109,21 @@ static int __init arm_idle_init_cpu(int cpu) ...@@ -117,37 +109,21 @@ static int __init arm_idle_init_cpu(int cpu)
ret = arm_cpuidle_init(cpu); ret = arm_cpuidle_init(cpu);
/* /*
* Skip the cpuidle device initialization if the reported * Allow the initialization to continue for other CPUs, if the reported
* failure is a HW misconfiguration/breakage (-ENXIO). * failure is a HW misconfiguration/breakage (-ENXIO).
*/ */
if (ret == -ENXIO)
return 0;
if (ret) { if (ret) {
pr_err("CPU %d failed to init idle CPU ops\n", cpu); pr_err("CPU %d failed to init idle CPU ops\n", cpu);
goto out_unregister_drv; ret = ret == -ENXIO ? 0 : ret;
} goto out_kfree_drv;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto out_unregister_drv;
} }
dev->cpu = cpu;
ret = cpuidle_register_device(dev); ret = cpuidle_register(drv, NULL);
if (ret) { if (ret)
pr_err("Failed to register cpuidle device for CPU %d\n", goto out_kfree_drv;
cpu);
goto out_kfree_dev;
}
return 0; return 0;
out_kfree_dev:
kfree(dev);
out_unregister_drv:
cpuidle_unregister_driver(drv);
out_kfree_drv: out_kfree_drv:
kfree(drv); kfree(drv);
return ret; return ret;
...@@ -178,9 +154,7 @@ static int __init arm_idle_init(void) ...@@ -178,9 +154,7 @@ static int __init arm_idle_init(void)
while (--cpu >= 0) { while (--cpu >= 0) {
dev = per_cpu(cpuidle_devices, cpu); dev = per_cpu(cpuidle_devices, cpu);
drv = cpuidle_get_cpu_driver(dev); drv = cpuidle_get_cpu_driver(dev);
cpuidle_unregister_device(dev); cpuidle_unregister(drv);
cpuidle_unregister_driver(drv);
kfree(dev);
kfree(drv); kfree(drv);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册