Power management updates for 7.2-rc1

- Fix a race between cpufreq suspend and CPU hotplug during system
    shutdown (Tianxiang Chen)
 
  - Avoid redundant target() calls for unchanged limits and fix a typo
    in a comment in the cpufreq core (Viresh Kumar)
 
  - Fix concurrency issues related to sysfs attributes access that affect
    cpufreq governors using the common governor code (Zhongqiu Han)
 
  - Simplify frequency limit handling in the conservative cpufreq
    governor (Lifeng Zheng)
 
  - Fix descriptions of the conservative governor freq_step tunable and
    the ondemand governor sampling_down_factor tunable in the cpufreq
    documentation (Pengjie Zhang)
 
  - Fix use-after-free and double free during _OSC evaluation in the PCC
    cpufreq driver (Yuho Choi)
 
  - Rework the handling of policy min and max frequency values in the
    cpufreq core to allow drivers to specify special initial values for
    the scaling_min_freq and scaling_max_freq sysfs attributes (Pierre
    Gondois)
 
  - Add cpufreq scaling support for Qualcomm Shikra SoC (Taniya Das,
    Imran Shaik).
 
  - Improve the warning message on HWP-disabled hybrid processors printed
    by the intel_pstate driver and sync policy->cur during CPU offline in
    it (Yohei Kojima, Fushuai Wang)
 
  - Drop cpufreq support for AMD Elan SC4* (Sean Young)
 
  - Minor fixes for cpufreq drivers (Krzysztof Kozlowski, Akashdeep Kaur,
    Hans Zhang, Guangshuo Li, Xueqin Luo)
 
  - Clean up dead dependencies on X86 in the cpufreq Kconfig (Julian
    Braha)
 
  - Allow the intel_idle driver to avoid exposing C-states that are
    redundant when PC6 is disabled (Artem Bityutskiy)
 
  - Fix memory leak and a potential race in the OPP core (Abdun Nihaal,
    Di Shen)
 
  - Mark Rust OPP methods as inline (Nicolás Antinori)
 
  - Fix misc device registration failure path in the PM QoS core (Yuho
    Choi)
 
  - Add sysctl interface for DPM watchdog timeouts (Tzung-Bi Shih)
 
  - Use complete() instead of complete_all() in device_pm_sleep_init() to
    avoid a false-positive warning from lockdep_assert_RT_in_threaded_ctx()
    when CONFIG_PROVE_RAW_LOCK_NESTING is enabled (Jiakai Xu)
 
  - Use a flexible array for CRC uncompressed buffers during hibernation
    image saving (Rosen Penev)
 
  - Make the LZ4 algorithm available for hibernation compression (l1rox3)
 
  - Move the preallocate_image() call during hibernation after the
    "prepare" phase of the "freeze" transition (Matthew Leach)
 
  - Fix a memory leak in rapl_add_package_cpuslocked() in the intel_rapl
    power capping driver and use sysfs_emit() in cpumask_show() in that
    driver (Sumeet Pawnikar, Yury Norov)
 
  - Fix ValueError when parsing incomplete device properties in the
    pm-graph utility (Gongwei Li)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmor9R8SHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1ODoIAInJsQeeWGXfUq4hAFnoA/gtS2oBw7Kw
 QVjoGG/DUbM/+ZtlbUee27pqvaYRY+q/Tv9RWKkl5vckASPFIAgCjImbm0g3P7Rz
 9OgoBwppqv0Yn5whFgc7nt9jOa7FQKV+jHiJgzRqwMxDFLkk0LldYVzsYpB6m+Lx
 Kca0LBeSv8o16EZX7RChC+6W7E5UhGxekSg9AzMPJTCe0gKciwARYiBhbSU5nAlI
 WdL5j+ycR3QTApbHA2tueaPKa1qnomLwJscmsE6UxlbikfcCBFZ9EvIsBnwl1WM4
 EcPA57IAYcr29N9Cdh/cs6MFkpWdzDBOs/ECZsgdI6fUWniQrPINThI=
 =oafL
 -----END PGP SIGNATURE-----

Merge tag 'pm-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:
 "Over a half of the changes here are cpufreq updates that include core
  modifications, fixes of the old-style governors, new hardware support
  in drivers, assorded driver fixes and cleanups, and the removal of one
  driver (AMD Elan SC4*).

  Apart from that, the intel_idle driver will now be able to avoid
  exposing redundant C-states if PC6 is disabled and there are new
  sysctl knobs for device suspend/resume watchdog timeouts, hibernation
  gets built-in LZ4 support for image compression and there is the usual
  collection of assorted fixes and cleanups.

  Specifics:

   - Fix a race between cpufreq suspend and CPU hotplug during system
     shutdown (Tianxiang Chen)

   - Avoid redundant target() calls for unchanged limits and fix a typo
     in a comment in the cpufreq core (Viresh Kumar)

   - Fix concurrency issues related to sysfs attributes access that
     affect cpufreq governors using the common governor code (Zhongqiu
     Han)

   - Simplify frequency limit handling in the conservative cpufreq
     governor (Lifeng Zheng)

   - Fix descriptions of the conservative governor freq_step tunable and
     the ondemand governor sampling_down_factor tunable in the cpufreq
     documentation (Pengjie Zhang)

   - Fix use-after-free and double free during _OSC evaluation in the
     PCC cpufreq driver (Yuho Choi)

   - Rework the handling of policy min and max frequency values in the
     cpufreq core to allow drivers to specify special initial values for
     the scaling_min_freq and scaling_max_freq sysfs attributes (Pierre
     Gondois)

   - Add cpufreq scaling support for Qualcomm Shikra SoC (Taniya Das,
     Imran Shaik).

   - Improve the warning message on HWP-disabled hybrid processors
     printed by the intel_pstate driver and sync policy->cur during CPU
     offline in it (Yohei Kojima, Fushuai Wang)

   - Drop cpufreq support for AMD Elan SC4* (Sean Young)

   - Minor fixes for cpufreq drivers (Krzysztof Kozlowski, Akashdeep
     Kaur, Hans Zhang, Guangshuo Li, Xueqin Luo)

   - Clean up dead dependencies on X86 in the cpufreq Kconfig (Julian
     Braha)

   - Allow the intel_idle driver to avoid exposing C-states that are
     redundant when PC6 is disabled (Artem Bityutskiy)

   - Fix memory leak and a potential race in the OPP core (Abdun Nihaal,
     Di Shen)

   - Mark Rust OPP methods as inline (Nicolás Antinori)

   - Fix misc device registration failure path in the PM QoS core (Yuho
     Choi)

   - Add sysctl interface for DPM watchdog timeouts (Tzung-Bi Shih)

   - Use complete() instead of complete_all() in device_pm_sleep_init()
     to avoid a false-positive warning from lockdep_assert_RT_in_threaded_ctx()
     when CONFIG_PROVE_RAW_LOCK_NESTING is enabled (Jiakai Xu)

   - Use a flexible array for CRC uncompressed buffers during
     hibernation image saving (Rosen Penev)

   - Make the LZ4 algorithm available for hibernation compression
     (l1rox3)

   - Move the preallocate_image() call during hibernation after the
     "prepare" phase of the "freeze" transition (Matthew Leach)

   - Fix a memory leak in rapl_add_package_cpuslocked() in the
     intel_rapl power capping driver and use sysfs_emit() in
     cpumask_show() in that driver (Sumeet Pawnikar, Yury Norov)

   - Fix ValueError when parsing incomplete device properties in the
     pm-graph utility (Gongwei Li)"

* tag 'pm-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/rafael/linux-pm: (40 commits)
  PM: dpm_watchdog: Add sysctl interface for DPM watchdog timeouts
  PM: QoS: Fix misc device registration unwind
  cpufreq: Use policy->min/max init as QoS request
  cpufreq: Remove driver default policy->min/max init
  cpufreq: Set default policy->min/max values for all drivers
  cpufreq: Extract cpufreq_policy_init_qos() function
  cpufreq: Documentation: fix conservative governor freq_step description
  cpufreq: ti: Add EPROBE_DEFER for K3 SoCs
  cpufreq: qcom: Add cpufreq scaling support for Qualcomm Shikra SoC
  dt-bindings: cpufreq: Document Qualcomm Shikra SoC EPSS
  powercap: intel_rapl: Use sysfs_emit() in cpumask_show()
  cpufreq: governor: Fix stale prev_cpu_nice spike when enabling ignore_nice_load
  cpufreq: governor: Fix data races on per-CPU idle/nice baselines
  PM: hibernate: Use flexible array for CRC uncompressed buffers
  powercap: intel_rapl: Fix memory leak in rapl_add_package_cpuslocked()
  PM: hibernate: make LZ4 available for hibernation compression
  PM: sleep: Use complete() in device_pm_sleep_init()
  opp: rust: mark OPP methods as inline
  cpufreq: intel_pstate: Improve warning message on HWP-disabled hybrid CPUs
  cpufreq: elanfreq: Drop support for AMD Elan SC4*
  ...
This commit is contained in:
Linus Torvalds 2026-06-15 11:37:18 +05:30
commit 5504ce0317
36 changed files with 494 additions and 462 deletions

View File

@ -1651,10 +1651,6 @@ Kernel parameters
very early in the boot process. For early debugging
via a serial port see kgdboc_earlycon instead.
elanfreq= [X86-32]
See comment before function elanfreq_setup() in
arch/x86/kernel/cpu/cpufreq/elanfreq.c.
elfcorehdr=[size[KMG]@]offset[KMG] [PPC,SH,X86,S390,EARLY]
Specifies physical address of start of kernel core
image elf header and optionally the size. Generally

View File

@ -516,7 +516,7 @@ This governor exposes the following tunables:
of those tasks above 0 and set this attribute to 1.
``sampling_down_factor``
Temporary multiplier, between 1 (default) and 100 inclusive, to apply to
Temporary multiplier, between 1 (default) and 100000 inclusive, to apply to
the ``sampling_rate`` value if the CPU load goes above ``up_threshold``.
This causes the next execution of the governor's worker routine (after
@ -586,8 +586,8 @@ This governor exposes the following tunables:
100 (5 by default).
This is how much the frequency is allowed to change in one go. Setting
it to 0 will cause the default frequency step (5 percent) to be used
and setting it to 100 effectively causes the governor to periodically
it to 0 disables frequency changes by the governor entirely and setting
it to 100 effectively causes the governor to periodically
switch the frequency between the ``scaling_min_freq`` and
``scaling_max_freq`` policy limits.

View File

@ -114,8 +114,13 @@ Then, the driver must fill in the following values:
|policy->cur | The current operating frequency of |
| | this CPU (if appropriate) |
+-----------------------------------+--------------------------------------+
|policy->min, | |
|policy->max, | |
|policy->min, | The min/max scaling frequency. |
|policy->max | If set by the driver in ->init(), |
| | used as the lower/upper bound for |
| | policy frequency QoS requests; |
| | otherwise, reflects the min/max |
| | frequency the driver can set |
+-----------------------------------+--------------------------------------+
|policy->policy and, if necessary, | |
|policy->governor | must contain the "default policy" for|
| | this CPU. A few moments later, |

View File

@ -0,0 +1,96 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/cpufreq/qcom,shikra-epss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Shikra SoC EPSS
maintainers:
- Imran Shaik <imran.shaik@oss.qualcomm.com>
- Taniya Das <taniya.das@oss.qualcomm.com>
description: |
EPSS is a hardware engine used by some Qualcomm SoCs to manage
frequency in hardware. It is capable of controlling frequency for
multiple clusters.
The Qualcomm Shikra SoC EPSS supports up to 12 frequency lookup table
(LUT) entries.
properties:
compatible:
enum:
- qcom,shikra-epss
reg:
items:
- description: Frequency domain 0 register region
- description: Frequency domain 1 register region
reg-names:
items:
- const: freq-domain0
- const: freq-domain1
clocks:
items:
- description: XO Clock
- description: GPLL0 Clock
clock-names:
items:
- const: xo
- const: alternate
interrupts:
items:
- description: IRQ line for DCVSH 0
- description: IRQ line for DCVSH 1
interrupt-names:
items:
- const: dcvsh-irq-0
- const: dcvsh-irq-1
'#freq-domain-cells':
const: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- interrupt-names
- '#freq-domain-cells'
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <1>;
#size-cells = <1>;
cpufreq@fd91000 {
compatible = "qcom,shikra-epss";
reg = <0x0fd91000 0x1000>, <0x0fd92000 0x1000>;
reg-names = "freq-domain0", "freq-domain1";
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gpll0>;
clock-names = "xo", "alternate";
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1";
#freq-domain-cells = <1>;
#clock-cells = <1>;
};
};
...

View File

@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sysctl.h>
#include <linux/async.h>
#include <linux/suspend.h>
#include <trace/events/power.h>
@ -115,7 +116,7 @@ void device_pm_sleep_init(struct device *dev)
dev->power.is_noirq_suspended = false;
dev->power.is_late_suspended = false;
init_completion(&dev->power.completion);
complete_all(&dev->power.completion);
complete(&dev->power.completion);
dev->power.wakeup = NULL;
INIT_LIST_HEAD(&dev->power.entry);
}
@ -252,6 +253,10 @@ static void dpm_wait(struct device *dev, bool async)
if (!dev)
return;
/* Devices with no PM support don't use the completion. */
if (dev->power.no_pm)
return;
if (async || (pm_async_enabled && dev->power.async_suspend))
wait_for_completion(&dev->power.completion);
}
@ -527,6 +532,58 @@ module_param(dpm_watchdog_all_cpu_backtrace, bool, 0644);
MODULE_PARM_DESC(dpm_watchdog_all_cpu_backtrace,
"Backtrace all CPUs on DPM watchdog timeout");
static unsigned int __read_mostly dpm_watchdog_timeout = CONFIG_DPM_WATCHDOG_TIMEOUT;
static unsigned int __read_mostly dpm_watchdog_warning_timeout =
CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
static const unsigned int dpm_watchdog_timeout_max = CONFIG_DPM_WATCHDOG_TIMEOUT;
static int proc_dodpm_watchdog_timeout_secs(const struct ctl_table *table,
int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct ctl_table ctl = *table;
unsigned int val = dpm_watchdog_timeout;
int ret;
ctl.data = &val;
ret = proc_douintvec_minmax(&ctl, write, buffer, lenp, ppos);
if (ret || !write)
return ret;
if (val < dpm_watchdog_warning_timeout)
dpm_watchdog_warning_timeout = val;
dpm_watchdog_timeout = val;
return 0;
}
static const struct ctl_table dpm_watchdog_sysctls[] = {
{
.procname = "dpm_watchdog_timeout_secs",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dodpm_watchdog_timeout_secs,
.extra1 = SYSCTL_ONE,
.extra2 = (void *)&dpm_watchdog_timeout_max,
},
{
.procname = "dpm_watchdog_warning_timeout_secs",
.data = &dpm_watchdog_warning_timeout,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_douintvec_minmax,
.extra1 = SYSCTL_ONE,
.extra2 = (void *)&dpm_watchdog_timeout,
},
};
static int __init dpm_watchdog_sysctl_init(void)
{
register_sysctl_init("kernel", dpm_watchdog_sysctls);
return 0;
}
subsys_initcall(dpm_watchdog_sysctl_init);
/**
* dpm_watchdog_handler - Driver suspend / resume watchdog handler.
* @t: The timer that PM watchdog depends on.
@ -552,9 +609,9 @@ static void dpm_watchdog_handler(struct timer_list *t)
dev_driver_string(wd->dev), dev_name(wd->dev));
}
time_left = CONFIG_DPM_WATCHDOG_TIMEOUT - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
time_left = dpm_watchdog_timeout - dpm_watchdog_warning_timeout;
dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n",
CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT, time_left);
dpm_watchdog_warning_timeout, time_left);
show_stack(wd->tsk, NULL, KERN_WARNING);
wd->fatal = true;
@ -572,11 +629,11 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
wd->dev = dev;
wd->tsk = current;
wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
wd->fatal = dpm_watchdog_timeout == dpm_watchdog_warning_timeout;
timer_setup_on_stack(timer, dpm_watchdog_handler, 0);
/* use same timeout value for both suspend and resume */
timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
timer->expires = jiffies + HZ * dpm_watchdog_warning_timeout;
add_timer(timer);
}

View File

@ -153,7 +153,7 @@ config ARM_QCOM_CPUFREQ_NVMEM
If in doubt, say N.
config ARM_QCOM_CPUFREQ_HW
tristate "QCOM CPUFreq HW driver"
tristate "Qualcomm CPUFreq HW driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on COMMON_CLK
help

View File

@ -5,7 +5,6 @@
config X86_INTEL_PSTATE
bool "Intel P state control"
depends on X86
select ACPI_PROCESSOR if ACPI
select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO
select CPU_FREQ_GOV_PERFORMANCE
@ -36,7 +35,7 @@ config X86_PCC_CPUFREQ
config X86_AMD_PSTATE
bool "AMD Processor P-State driver"
depends on X86 && ACPI
depends on ACPI
select ACPI_PROCESSOR
select ACPI_CPPC_LIB if X86_64
select CPU_FREQ_GOV_SCHEDUTIL if SMP
@ -72,7 +71,7 @@ config X86_AMD_PSTATE_DEFAULT_MODE
config X86_AMD_PSTATE_UT
tristate "selftest for AMD Processor P-State driver"
depends on X86 && ACPI_PROCESSOR
depends on ACPI_PROCESSOR
depends on X86_AMD_PSTATE
default n
help
@ -114,21 +113,6 @@ config X86_ACPI_CPUFREQ_CPB
By enabling this option the acpi_cpufreq driver provides the old
entry in addition to the new boost ones, for compatibility reasons.
config ELAN_CPUFREQ
tristate "AMD Elan SC400 and SC410"
depends on MELAN
help
This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors.
You need to specify the processor maximum speed as boot
parameter: elanfreq=maxspeed (in kHz) or as module
parameter "max_freq".
For details, take a look at <file:Documentation/cpu-freq/>.
If in doubt, say N.
config SC520_CPUFREQ
tristate "AMD Elan SC520"
depends on MELAN

View File

@ -40,7 +40,6 @@ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
obj-$(CONFIG_X86_E_POWERSAVER) += e_powersaver.o
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
obj-$(CONFIG_X86_LONGRUN) += longrun.o
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o

View File

@ -242,12 +242,10 @@ static int msr_update_perf(struct cpufreq_policy *policy, u8 min_perf,
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK |
AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK);
value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf);
value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf);
value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf);
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_MAX_PERF_MASK, &value, max_perf);
FIELD_MODIFY(AMD_CPPC_DES_PERF_MASK, &value, des_perf);
FIELD_MODIFY(AMD_CPPC_MIN_PERF_MASK, &value, min_perf);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = READ_ONCE(cpudata->perf);
@ -296,8 +294,7 @@ static int msr_set_epp(struct cpufreq_policy *policy, u8 epp)
int ret;
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~AMD_CPPC_EPP_PERF_MASK;
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = cpudata->perf;
@ -437,8 +434,7 @@ static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp)
}
value = READ_ONCE(cpudata->cppc_req_cached);
value &= ~AMD_CPPC_EPP_PERF_MASK;
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
WRITE_ONCE(cpudata->cppc_req_cached, value);
return ret;
@ -571,12 +567,10 @@ static int shmem_update_perf(struct cpufreq_policy *policy, u8 min_perf,
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK |
AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK);
value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf);
value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf);
value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf);
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_MAX_PERF_MASK, &value, max_perf);
FIELD_MODIFY(AMD_CPPC_DES_PERF_MASK, &value, des_perf);
FIELD_MODIFY(AMD_CPPC_MIN_PERF_MASK, &value, min_perf);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = READ_ONCE(cpudata->perf);
@ -1086,10 +1080,9 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
perf = READ_ONCE(cpudata->perf);
policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
cpudata->nominal_freq,
perf.lowest_perf);
policy->cpuinfo.max_freq = policy->max = cpudata->max_freq;
policy->cpuinfo.min_freq = perf_to_freq(perf, cpudata->nominal_freq,
perf.lowest_perf);
policy->cpuinfo.max_freq = cpudata->max_freq;
policy->driver_data = cpudata;
ret = amd_pstate_cppc_enable(policy);
@ -1915,10 +1908,9 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
perf = READ_ONCE(cpudata->perf);
policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf,
cpudata->nominal_freq,
perf.lowest_perf);
policy->cpuinfo.max_freq = policy->max = cpudata->max_freq;
policy->cpuinfo.min_freq = perf_to_freq(perf, cpudata->nominal_freq,
perf.lowest_perf);
policy->cpuinfo.max_freq = cpudata->max_freq;
policy->driver_data = cpudata;
ret = amd_pstate_cppc_enable(policy);

View File

@ -187,10 +187,8 @@ static int apple_soc_cpufreq_set_target(struct cpufreq_policy *policy,
reg &= ~priv->info->ps1_mask;
reg |= pstate << priv->info->ps1_shift;
if (priv->info->has_ps2) {
reg &= ~APPLE_DVFS_CMD_PS2;
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
}
if (priv->info->has_ps2)
FIELD_MODIFY(APPLE_DVFS_CMD_PS2, &reg, pstate);
reg |= APPLE_DVFS_CMD_SET;
writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD);

View File

@ -660,8 +660,6 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
* Section 8.4.7.1.1.5 of ACPI 6.1 spec)
*/
policy->min = cppc_perf_to_khz(caps, caps->lowest_nonlinear_perf);
policy->max = cppc_perf_to_khz(caps, policy->boost_enabled ?
caps->highest_perf : caps->nominal_perf);
/*
* Set cpuinfo.min_freq to Lowest to make the full range of performance
@ -669,7 +667,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
* nonlinear perf
*/
policy->cpuinfo.min_freq = cppc_perf_to_khz(caps, caps->lowest_perf);
policy->cpuinfo.max_freq = policy->max;
policy->cpuinfo.max_freq = cppc_perf_to_khz(caps, policy->boost_enabled ?
caps->highest_perf : caps->nominal_perf);
policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
policy->shared_type = cpu_data->shared_type;
@ -982,7 +981,34 @@ store_energy_performance_preference_val(struct cpufreq_policy *policy,
return count;
}
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited,
static int cppc_get_perf_limited_filtered(int cpu, u64 *perf_limited)
{
struct cpufreq_policy *policy;
struct cppc_cpudata *cpu_data;
int ret;
ret = cppc_get_perf_limited(cpu, perf_limited);
if (ret)
return ret;
policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
return -EINVAL;
cpu_data = policy->driver_data;
/*
* Desired Excursion is ignored when autonomous selection is
* enabled. Clear the bit to avoid exposing meaningless state
* to userspace.
*/
if (cpu_data && cpu_data->perf_ctrls.auto_sel)
*perf_limited &= ~CPPC_PERF_LIMITED_DESIRED_EXCURSION;
return 0;
}
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited_filtered,
cppc_set_perf_limited)
cpufreq_freq_attr_ro(freqdomain_cpus);

View File

@ -355,8 +355,8 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
min_fsb = NFORCE2_MIN_FSB;
/* cpuinfo and default policy values */
policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100;
policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100;
policy->cpuinfo.min_freq = min_fsb * fid * 100;
policy->cpuinfo.max_freq = max_fsb * fid * 100;
return 0;
}

View File

@ -1397,6 +1397,40 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
kfree(policy);
}
static int cpufreq_policy_init_qos(struct cpufreq_policy *policy)
{
unsigned int min_freq, max_freq;
int ret;
/* Use policy->min/max set by the driver as QoS requests. */
min_freq = max(FREQ_QOS_MIN_DEFAULT_VALUE, policy->min);
if (policy->max)
max_freq = min(FREQ_QOS_MAX_DEFAULT_VALUE, policy->max);
else
max_freq = FREQ_QOS_MAX_DEFAULT_VALUE;
if (policy->boost_supported) {
ret = freq_qos_add_request(&policy->constraints,
&policy->boost_freq_req,
FREQ_QOS_MAX,
policy->cpuinfo.max_freq);
if (ret < 0)
return ret;
}
ret = freq_qos_add_request(&policy->constraints, &policy->min_freq_req,
FREQ_QOS_MIN, min_freq);
if (ret < 0)
return ret;
ret = freq_qos_add_request(&policy->constraints, &policy->max_freq_req,
FREQ_QOS_MAX, max_freq);
if (ret < 0)
return ret;
return 0;
}
static int cpufreq_policy_online(struct cpufreq_policy *policy,
unsigned int cpu, bool new_policy)
{
@ -1442,6 +1476,19 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
if (ret)
goto out_offline_policy;
if (new_policy) {
ret = cpufreq_policy_init_qos(policy);
if (ret < 0)
goto out_offline_policy;
}
/*
* If the driver hasn't set policy->min/max, set them as they
* are used for clamping frequency requests.
*/
policy->min = policy->min ? policy->min : policy->cpuinfo.min_freq;
policy->max = policy->max ? policy->max : policy->cpuinfo.max_freq;
/* related_cpus should at least include policy->cpus. */
cpumask_copy(policy->related_cpus, policy->cpus);
}
@ -1458,27 +1505,6 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
add_cpu_dev_symlink(policy, j, get_cpu_device(j));
}
if (policy->boost_supported) {
ret = freq_qos_add_request(&policy->constraints,
&policy->boost_freq_req,
FREQ_QOS_MAX,
policy->cpuinfo.max_freq);
if (ret < 0)
goto out_destroy_policy;
}
ret = freq_qos_add_request(&policy->constraints,
&policy->min_freq_req, FREQ_QOS_MIN,
FREQ_QOS_MIN_DEFAULT_VALUE);
if (ret < 0)
goto out_destroy_policy;
ret = freq_qos_add_request(&policy->constraints,
&policy->max_freq_req, FREQ_QOS_MAX,
FREQ_QOS_MAX_DEFAULT_VALUE);
if (ret < 0)
goto out_destroy_policy;
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_CREATE_POLICY, policy);
}
@ -1972,6 +1998,7 @@ void cpufreq_suspend(void)
if (!cpufreq_driver)
return;
cpus_read_lock();
if (!has_target() && !cpufreq_driver->suspend)
goto suspend;
@ -1991,6 +2018,7 @@ void cpufreq_suspend(void)
suspend:
cpufreq_suspended = true;
cpus_read_unlock();
}
/**
@ -2366,9 +2394,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
* exactly same freq is called again and so we can save on few function
* calls.
*/
if (target_freq == policy->cur &&
!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
return 0;
if (target_freq == policy->cur) {
if (!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS) ||
!policy->update_limits)
return 0;
policy->update_limits = false;
}
if (cpufreq_driver->target) {
/*
@ -2620,6 +2652,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
{
struct cpufreq_policy_data new_data;
struct cpufreq_governor *old_gov;
unsigned int freq;
int ret;
memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
@ -2652,12 +2685,20 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
* compiler optimizations around them because they may be accessed
* concurrently by cpufreq_driver_resolve_freq() during the update.
*/
WRITE_ONCE(policy->max, __resolve_freq(policy, new_data.max,
new_data.min, new_data.max,
CPUFREQ_RELATION_H));
new_data.min = __resolve_freq(policy, new_data.min, new_data.min,
new_data.max, CPUFREQ_RELATION_L);
WRITE_ONCE(policy->min, new_data.min > policy->max ? policy->max : new_data.min);
freq = __resolve_freq(policy, new_data.max, new_data.min, new_data.max,
CPUFREQ_RELATION_H);
if (freq != policy->max) {
WRITE_ONCE(policy->max, freq);
policy->update_limits = true;
}
freq = __resolve_freq(policy, new_data.min, new_data.min, new_data.max,
CPUFREQ_RELATION_L);
freq = min(freq, policy->max);
if (freq != policy->min) {
WRITE_ONCE(policy->min, freq);
policy->update_limits = true;
}
trace_cpu_frequency_limits(policy);

View File

@ -103,10 +103,6 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
if (load > dbs_data->up_threshold) {
dbs_info->down_skip = 0;
/* if we are already at full speed then break out early */
if (requested_freq == policy->max)
goto out;
requested_freq += freq_step;
if (requested_freq > policy->max)
requested_freq = policy->max;
@ -124,13 +120,7 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
/* Check for frequency decrease */
if (load < cs_tuners->down_threshold) {
/*
* if we cannot reduce the frequency anymore, break out early
*/
if (requested_freq == policy->min)
goto out;
if (requested_freq > freq_step)
if (requested_freq > policy->min + freq_step)
requested_freq -= freq_step;
else
requested_freq = policy->min;

View File

@ -90,7 +90,14 @@ EXPORT_SYMBOL_GPL(sampling_rate_store);
* (that may be a single policy or a bunch of them if governor tunables are
* system-wide).
*
* Call under the @dbs_data mutex.
* Call under the @dbs_data->attr_set.update_lock. The per-policy
* update_mutex is acquired and released internally for each policy.
*
* Note: prev_cpu_nice is reset here unconditionally alongside prev_cpu_idle.
* When io_is_busy changes, both baselines must be advanced to the same
* timestamp so that the next dbs_update() computes idle_time and nice_delta
* over the same interval, preventing an artificially inflated idle_time when
* ignore_nice_load is enabled.
*/
void gov_update_cpu_data(struct dbs_data *dbs_data)
{
@ -99,14 +106,15 @@ void gov_update_cpu_data(struct dbs_data *dbs_data)
list_for_each_entry(policy_dbs, &dbs_data->attr_set.policy_list, list) {
unsigned int j;
mutex_lock(&policy_dbs->update_mutex);
for_each_cpu(j, policy_dbs->policy->cpus) {
struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_update_time,
dbs_data->io_is_busy);
if (dbs_data->ignore_nice_load)
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
}
mutex_unlock(&policy_dbs->update_mutex);
}
}
EXPORT_SYMBOL_GPL(gov_update_cpu_data);
@ -118,6 +126,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
unsigned int ignore_nice = dbs_data->ignore_nice_load;
unsigned int max_load = 0, idle_periods = UINT_MAX;
unsigned int sampling_rate, io_busy, j;
u64 cur_nice;
/*
* Sometimes governors may use an additional multiplier to increase
@ -164,12 +173,18 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
j_cdbs->prev_cpu_idle = cur_idle_time;
if (ignore_nice) {
u64 cur_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
/*
* Always sample cur_nice and advance prev_cpu_nice, regardless
* of ignore_nice. This keeps prev_cpu_nice current so that
* enabling ignore_nice_load via sysfs never produces a
* stale-baseline spike (the delta will be at most one sampling
* interval of accumulated nice time, not since boot).
*/
cur_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
if (ignore_nice)
idle_time += div_u64(cur_nice - j_cdbs->prev_cpu_nice, NSEC_PER_USEC);
j_cdbs->prev_cpu_nice = cur_nice;
}
j_cdbs->prev_cpu_nice = cur_nice;
if (unlikely(!time_elapsed)) {
/*
@ -516,7 +531,7 @@ int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
struct dbs_governor *gov = dbs_governor_of(policy);
struct policy_dbs_info *policy_dbs = policy->governor_data;
struct dbs_data *dbs_data = policy_dbs->dbs_data;
unsigned int sampling_rate, ignore_nice, j;
unsigned int sampling_rate, j;
unsigned int io_busy;
if (!policy->cur)
@ -526,9 +541,9 @@ int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
policy_dbs->rate_mult = 1;
sampling_rate = dbs_data->sampling_rate;
ignore_nice = dbs_data->ignore_nice_load;
io_busy = dbs_data->io_is_busy;
mutex_lock(&policy_dbs->update_mutex);
io_busy = dbs_data->io_is_busy;
for_each_cpu(j, policy->cpus) {
struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
@ -537,10 +552,9 @@ int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
* Make the first invocation of dbs_update() compute the load.
*/
j_cdbs->prev_load = 0;
if (ignore_nice)
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
}
mutex_unlock(&policy_dbs->update_mutex);
gov->start(policy);

View File

@ -1,226 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* elanfreq: cpufreq driver for the AMD ELAN family
*
* (c) Copyright 2002 Robert Schwebel <r.schwebel@pengutronix.de>
*
* Parts of this code are (c) Sven Geggus <sven@geggus.net>
*
* All Rights Reserved.
*
* 2002-02-13: - initial revision for 2.4.18-pre9 by Robert Schwebel
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/cpufreq.h>
#include <asm/cpu_device_id.h>
#include <linux/timex.h>
#include <linux/io.h>
#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
/* Module parameter */
static int max_freq;
struct s_elan_multiplier {
int clock; /* frequency in kHz */
int val40h; /* PMU Force Mode register */
int val80h; /* CPU Clock Speed Register */
};
/*
* It is important that the frequencies
* are listed in ascending order here!
*/
static struct s_elan_multiplier elan_multiplier[] = {
{1000, 0x02, 0x18},
{2000, 0x02, 0x10},
{4000, 0x02, 0x08},
{8000, 0x00, 0x00},
{16000, 0x00, 0x02},
{33000, 0x00, 0x04},
{66000, 0x01, 0x04},
{99000, 0x01, 0x05}
};
static struct cpufreq_frequency_table elanfreq_table[] = {
{0, 0, 1000},
{0, 1, 2000},
{0, 2, 4000},
{0, 3, 8000},
{0, 4, 16000},
{0, 5, 33000},
{0, 6, 66000},
{0, 7, 99000},
{0, 0, CPUFREQ_TABLE_END},
};
/**
* elanfreq_get_cpu_frequency: determine current cpu speed
*
* Finds out at which frequency the CPU of the Elan SOC runs
* at the moment. Frequencies from 1 to 33 MHz are generated
* the normal way, 66 and 99 MHz are called "Hyperspeed Mode"
* and have the rest of the chip running with 33 MHz.
*/
static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
{
u8 clockspeed_reg; /* Clock Speed Register */
local_irq_disable();
outb_p(0x80, REG_CSCIR);
clockspeed_reg = inb_p(REG_CSCDR);
local_irq_enable();
if ((clockspeed_reg & 0xE0) == 0xE0)
return 0;
/* Are we in CPU clock multiplied mode (66/99 MHz)? */
if ((clockspeed_reg & 0xE0) == 0xC0) {
if ((clockspeed_reg & 0x01) == 0)
return 66000;
else
return 99000;
}
/* 33 MHz is not 32 MHz... */
if ((clockspeed_reg & 0xE0) == 0xA0)
return 33000;
return (1<<((clockspeed_reg & 0xE0) >> 5)) * 1000;
}
static int elanfreq_target(struct cpufreq_policy *policy,
unsigned int state)
{
/*
* Access to the Elan's internal registers is indexed via
* 0x22: Chip Setup & Control Register Index Register (CSCI)
* 0x23: Chip Setup & Control Register Data Register (CSCD)
*
*/
/*
* 0x40 is the Power Management Unit's Force Mode Register.
* Bit 6 enables Hyperspeed Mode (66/100 MHz core frequency)
*/
local_irq_disable();
outb_p(0x40, REG_CSCIR); /* Disable hyperspeed mode */
outb_p(0x00, REG_CSCDR);
local_irq_enable(); /* wait till internal pipelines and */
udelay(1000); /* buffers have cleaned up */
local_irq_disable();
/* now, set the CPU clock speed register (0x80) */
outb_p(0x80, REG_CSCIR);
outb_p(elan_multiplier[state].val80h, REG_CSCDR);
/* now, the hyperspeed bit in PMU Force Mode Register (0x40) */
outb_p(0x40, REG_CSCIR);
outb_p(elan_multiplier[state].val40h, REG_CSCDR);
udelay(10000);
local_irq_enable();
return 0;
}
/*
* Module init and exit code
*/
static int elanfreq_cpu_init(struct cpufreq_policy *policy)
{
struct cpuinfo_x86 *c = &cpu_data(0);
struct cpufreq_frequency_table *pos;
/* capability check */
if ((c->x86_vendor != X86_VENDOR_AMD) ||
(c->x86 != 4) || (c->x86_model != 10))
return -ENODEV;
/* max freq */
if (!max_freq)
max_freq = elanfreq_get_cpu_frequency(0);
/* table init */
cpufreq_for_each_entry(pos, elanfreq_table)
if (pos->frequency > max_freq)
pos->frequency = CPUFREQ_ENTRY_INVALID;
policy->freq_table = elanfreq_table;
return 0;
}
#ifndef MODULE
/**
* elanfreq_setup - elanfreq command line parameter parsing
*
* elanfreq command line parameter. Use:
* elanfreq=66000
* to set the maximum CPU frequency to 66 MHz. Note that in
* case you do not give this boot parameter, the maximum
* frequency will fall back to _current_ CPU frequency which
* might be lower. If you build this as a module, use the
* max_freq module parameter instead.
*/
static int __init elanfreq_setup(char *str)
{
max_freq = simple_strtoul(str, &str, 0);
pr_warn("You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n");
return 1;
}
__setup("elanfreq=", elanfreq_setup);
#endif
static struct cpufreq_driver elanfreq_driver = {
.get = elanfreq_get_cpu_frequency,
.flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = elanfreq_target,
.init = elanfreq_cpu_init,
.name = "elanfreq",
};
static const struct x86_cpu_id elan_id[] = {
X86_MATCH_VENDOR_FAM_MODEL(AMD, 4, 10, NULL),
{}
};
MODULE_DEVICE_TABLE(x86cpu, elan_id);
static int __init elanfreq_init(void)
{
if (!x86_match_cpu(elan_id))
return -ENODEV;
return cpufreq_register_driver(&elanfreq_driver);
}
static void __exit elanfreq_exit(void)
{
cpufreq_unregister_driver(&elanfreq_driver);
}
module_param(max_freq, int, 0444);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, "
"Sven Geggus <sven@geggus.net>");
MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
module_init(elanfreq_init);
module_exit(elanfreq_exit);

View File

@ -49,16 +49,15 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
max_freq = freq;
}
policy->min = policy->cpuinfo.min_freq = min_freq;
policy->max = max_freq;
policy->cpuinfo.min_freq = min_freq;
/*
* If the driver has set its own cpuinfo.max_freq above max_freq, leave
* it as is.
*/
if (policy->cpuinfo.max_freq < max_freq)
policy->max = policy->cpuinfo.max_freq = max_freq;
policy->cpuinfo.max_freq = max_freq;
if (policy->min == ~0)
if (min_freq == ~0)
return -EINVAL;
else
return 0;

View File

@ -421,7 +421,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
policy->min = maxfreq / max_duration;
else
policy->min = maxfreq / POLICY_MIN_DIV;
policy->max = maxfreq;
policy->cpuinfo.min_freq = maxfreq / max_duration;
policy->cpuinfo.max_freq = maxfreq;

View File

@ -2984,10 +2984,12 @@ static int intel_cpufreq_cpu_offline(struct cpufreq_policy *policy)
* from getting to lower performance levels, so force the minimum
* performance on CPU offline to prevent that from happening.
*/
if (hwp_active)
if (hwp_active) {
intel_pstate_hwp_offline(cpu);
else
} else {
intel_pstate_set_min_pstate(cpu);
policy->cur = cpu->pstate.min_freq;
}
intel_pstate_exit_perf_limits(policy);
@ -3049,9 +3051,6 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = READ_ONCE(global.no_turbo) ?
cpu->pstate.max_freq : cpu->pstate.turbo_freq;
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
intel_pstate_init_acpi_perf_limits(policy);
policy->fast_switch_possible = true;
@ -3824,6 +3823,12 @@ static int __init intel_pstate_init(void)
if (no_load)
return -ENODEV;
id = x86_match_cpu(intel_hybrid_scaling_factor);
if (id) {
pr_info("HWP-disabled hybrid CPU is not supported\n");
return -ENODEV;
}
id = x86_match_cpu(intel_pstate_cpu_ids);
if (!id) {
pr_info("CPU model not supported\n");

View File

@ -352,6 +352,8 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
}
kfree(output.pointer);
output.pointer = NULL;
output.length = ACPI_ALLOCATE_BUFFER;
capabilities[0] = 0x0;
capabilities[1] = 0x1;
@ -551,13 +553,11 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
goto out;
}
policy->max = policy->cpuinfo.max_freq =
ioread32(&pcch_hdr->nominal) * 1000;
policy->min = policy->cpuinfo.min_freq =
ioread32(&pcch_hdr->minimum_frequency) * 1000;
policy->cpuinfo.max_freq = ioread32(&pcch_hdr->nominal) * 1000;
policy->cpuinfo.min_freq = ioread32(&pcch_hdr->minimum_frequency) * 1000;
pr_debug("init: policy->max is %d, policy->min is %d\n",
policy->max, policy->min);
pr_debug("init: max_freq is %d, min_freq is %d\n",
policy->cpuinfo.max_freq, policy->cpuinfo.min_freq);
out:
return result;
}

View File

@ -185,9 +185,8 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
int ret = -EINVAL;
/* set default policy and cpuinfo */
policy->min = policy->cpuinfo.min_freq = 104000;
policy->max = policy->cpuinfo.max_freq =
(cpu_is_pxa320()) ? 806000 : 624000;
policy->cpuinfo.min_freq = 104000;
policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
if (cpu_is_pxa300() || cpu_is_pxa310())

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/bitfield.h>
@ -40,6 +41,7 @@ struct qcom_cpufreq_soc_data {
u32 reg_intr_clr;
u32 reg_current_vote;
u32 reg_perf_state;
u32 lut_max_entries;
u8 lut_row_size;
};
@ -156,7 +158,7 @@ static unsigned int qcom_cpufreq_get_freq(struct cpufreq_policy *policy)
soc_data = qcom_cpufreq.soc_data;
index = readl_relaxed(data->base + soc_data->reg_perf_state);
index = min(index, LUT_MAX_ENTRIES - 1);
index = min(index, soc_data->lut_max_entries - 1);
return policy->freq_table[index].frequency;
}
@ -211,7 +213,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
struct qcom_cpufreq_data *drv_data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
table = kzalloc_objs(*table, LUT_MAX_ENTRIES + 1);
table = kzalloc_objs(*table, soc_data->lut_max_entries + 1);
if (!table)
return -ENOMEM;
@ -236,7 +238,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
icc_scaling_enabled = false;
}
for (i = 0; i < LUT_MAX_ENTRIES; i++) {
for (i = 0; i < soc_data->lut_max_entries; i++) {
data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut +
i * soc_data->lut_row_size);
src = FIELD_GET(LUT_SRC, data);
@ -405,6 +407,7 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
.reg_current_vote = 0x704,
.reg_perf_state = 0x920,
.lut_row_size = 32,
.lut_max_entries = LUT_MAX_ENTRIES,
};
static const struct qcom_cpufreq_soc_data epss_soc_data = {
@ -416,11 +419,25 @@ static const struct qcom_cpufreq_soc_data epss_soc_data = {
.reg_intr_clr = 0x308,
.reg_perf_state = 0x320,
.lut_row_size = 4,
.lut_max_entries = LUT_MAX_ENTRIES,
};
static const struct qcom_cpufreq_soc_data shikra_epss_soc_data = {
.reg_enable = 0x0,
.reg_domain_state = 0x20,
.reg_dcvs_ctrl = 0xb0,
.reg_freq_lut = 0x100,
.reg_volt_lut = 0x200,
.reg_intr_clr = 0x308,
.reg_perf_state = 0x320,
.lut_row_size = 4,
.lut_max_entries = 12,
};
static const struct of_device_id qcom_cpufreq_hw_match[] = {
{ .compatible = "qcom,cpufreq-hw", .data = &qcom_soc_data },
{ .compatible = "qcom,cpufreq-epss", .data = &epss_soc_data },
{ .compatible = "qcom,shikra-epss", .data = &shikra_epss_soc_data },
{}
};
MODULE_DEVICE_TABLE(of, qcom_cpufreq_hw_match);
@ -578,7 +595,6 @@ static void qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
qcom_cpufreq_hw_lmh_exit(data);
kfree(policy->freq_table);
kfree(data);
}
static void qcom_cpufreq_ready(struct cpufreq_policy *policy)

View File

@ -124,10 +124,8 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
dev_notice(dev, "no frequency table found, falling back "
"to rate rounding.\n");
policy->min = policy->cpuinfo.min_freq =
(clk_round_rate(cpuclk, 1) + 500) / 1000;
policy->max = policy->cpuinfo.max_freq =
(clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
}
return 0;

View File

@ -99,6 +99,7 @@ struct ti_cpufreq_soc_data {
unsigned long efuse_shift;
unsigned long rev_offset;
bool multi_regulator;
bool needs_k3_socinfo;
/* Backward compatibility hack: Might have missing syscon */
#define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1
/* Backward compatibility hack: new syscon size is 1 register wide */
@ -347,6 +348,7 @@ static struct ti_cpufreq_soc_data am625_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
.quirks = TI_QUIRK_SYSCON_IS_SINGLE_REG,
};
@ -356,6 +358,7 @@ static struct ti_cpufreq_soc_data am62a7_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
static struct ti_cpufreq_soc_data am62l3_soc_data = {
@ -364,6 +367,7 @@ static struct ti_cpufreq_soc_data am62l3_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
static struct ti_cpufreq_soc_data am62p5_soc_data = {
@ -372,6 +376,7 @@ static struct ti_cpufreq_soc_data am62p5_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
/**
@ -443,6 +448,11 @@ static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
goto done;
}
/* Defer if k3-socinfo hasn't registered the SoC device yet */
if (opp_data->soc_data->needs_k3_socinfo)
return dev_err_probe(opp_data->cpu_dev, -EPROBE_DEFER,
"SoC device not registered by k3-socinfo\n");
ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset,
&revision);
if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) {

View File

@ -164,10 +164,7 @@ static int virt_cpufreq_get_freq_info(struct cpufreq_policy *policy)
policy->cpuinfo.min_freq = 1;
policy->cpuinfo.max_freq = virt_cpufreq_get_perftbl_entry(policy->cpu, 0);
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
policy->cur = policy->max;
policy->cur = policy->cpuinfo.max_freq;
return 0;
}

View File

@ -81,6 +81,11 @@ static bool ibrs_off __read_mostly;
/* Maximum allowed C-state target residency */
#define MAX_CMDLINE_RESIDENCY_US (100 * USEC_PER_MSEC)
/* The Package C-State Limit bits in MSR_PKG_CST_CONFIG_CONTROL */
#define SKX_PKG_CST_LIMIT_MASK GENMASK(2, 0)
/* PC6 is enabled when Package C-State Limit >= this value */
#define SKX_PKG_CST_LIMIT_PC6 2
static char cmdline_table_str[MAX_CMDLINE_TABLE_LEN] __read_mostly;
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
@ -2074,12 +2079,13 @@ static void __init sklh_idle_state_table_update(void)
}
/**
* skx_idle_state_table_update - Adjust the Sky Lake/Cascade Lake
* idle states table.
* skx_is_pc6_disabled() - Check if PC6 is disabled in BIOS.
*
* Return: %true if PC6 is disabled, %false otherwise.
*/
static void __init skx_idle_state_table_update(void)
static bool __init skx_is_pc6_disabled(void)
{
unsigned long long msr;
u64 msr;
rdmsrq(MSR_PKG_CST_CONFIG_CONTROL, msr);
@ -2090,40 +2096,86 @@ static void __init skx_idle_state_table_update(void)
* 011b: C6 (retention)
* 111b: No Package C state limits.
*/
if ((msr & 0x7) < 2) {
/*
* Uses the CC6 + PC0 latency and 3 times of
* latency for target_residency if the PC6
* is disabled in BIOS. This is consistent
* with how intel_idle driver uses _CST
* to set the target_residency.
*/
return (msr & SKX_PKG_CST_LIMIT_MASK) < SKX_PKG_CST_LIMIT_PC6;
}
/**
* skx_idle_state_table_update - Adjust the SKX/CLX idle states table.
*
* Adjust Sky Lake or Cascade Lake Xeon idle states if PC6 is disabled in BIOS.
* Use the CC6 + PC0 latency and 3 times of that latency for target_residency.
* This is consistent with how the intel_idle driver uses _CST to set the
* target_residency.
*/
static void __init skx_idle_state_table_update(void)
{
if (skx_is_pc6_disabled()) {
skx_cstates[2].exit_latency = 92;
skx_cstates[2].target_residency = 276;
}
}
/**
* spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
* spr_idle_state_table_update - Adjust Sapphire Rapids Xeon idle states table.
*
* By default, the C6 state assumes the worst-case scenario of package C6.
* However, if PC6 is disabled in BIOS, update the numbers to match core C6.
*/
static void __init spr_idle_state_table_update(void)
{
unsigned long long msr;
/*
* By default, the C6 state assumes the worst-case scenario of package
* C6. However, if PC6 is disabled, we update the numbers to match
* core C6.
*/
rdmsrq(MSR_PKG_CST_CONFIG_CONTROL, msr);
/* Limit value 2 and above allow for PC6. */
if ((msr & 0x7) < 2) {
if (skx_is_pc6_disabled()) {
spr_cstates[2].exit_latency = 190;
spr_cstates[2].target_residency = 600;
}
}
/**
* drop_pc6_redundant_cstates() - Drop C-states redundant when PC6 is disabled.
* @states: Idle states table to modify.
*
* When PC6 is disabled in BIOS, C-states that exist solely to enable PC6
* entry (such as C6P or C6SP) become identical to shallower C-states like
* C6, and are therefore redundant. Should be called only on systems with
* multiple C6 flavors.
*/
static void __init drop_pc6_redundant_cstates(struct cpuidle_state *states)
{
int count;
if (!skx_is_pc6_disabled())
/* PC6 is not disabled, nothing to do */
return;
for (count = 0; states[count].enter; count++)
continue;
if (count < 2) {
pr_debug("Too few idle states to drop PC6-redundant states\n");
return;
}
/*
* Sanity check: At this point all platforms with multiple C6 flavors
* use the CPUIDLE_FLAG_PARTIAL_HINT_MATCH flag. And the last state in
* the table is the one that becomes redundant when PC6 is disabled.
*/
if (!(states[count - 1].flags & CPUIDLE_FLAG_PARTIAL_HINT_MATCH)) {
pr_debug("Can't drop PC6-redundant states: unexpected flags\n");
return;
}
/*
* On all current platforms with multiple C6 flavors, there is only one
* C-state that becomes redundant when PC6 is disabled. This state is
* the last one in the table. Drop it by marking it with
* CPUIDLE_FLAG_UNUSABLE so that cpuidle excludes it when registering
* idle states.
*/
pr_info("Dropping idle state %s because PC6 is disabled\n",
states[count - 1].name);
states[count - 1].flags |= CPUIDLE_FLAG_UNUSABLE;
}
/**
* byt_cht_auto_demotion_disable - Disable Bay/Cherry Trail auto-demotion.
*/
@ -2213,6 +2265,12 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
case INTEL_ATOM_AIRMONT:
byt_cht_auto_demotion_disable();
break;
case INTEL_GRANITERAPIDS_D:
case INTEL_GRANITERAPIDS_X:
case INTEL_ATOM_CRESTMONT_X:
case INTEL_ATOM_DARKMONT_X:
drop_pc6_redundant_cstates(cpuidle_state_table);
break;
}
for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {

View File

@ -2088,11 +2088,10 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
return ret;
list_add(&new_opp->node, head);
new_opp->opp_table = opp_table;
kref_init(&new_opp->kref);
}
new_opp->opp_table = opp_table;
kref_init(&new_opp->kref);
opp_debug_create_one(new_opp, opp_table);
if (!_opp_supported_by_regulators(new_opp, opp_table)) {

View File

@ -673,7 +673,7 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
*/
if (unlikely(opp_table->regulator_count == -1)) {
opp_table->regulator_count = 0;
return 0;
goto free_microwatt;
}
for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
@ -696,6 +696,7 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
opp->supplies[i].u_watt = microwatt[i];
}
free_microwatt:
kfree(microwatt);
free_microamp:
kfree(microamp);

View File

@ -1441,7 +1441,7 @@ static ssize_t cpumask_show(struct device *dev,
}
cpus_read_unlock();
ret = cpumap_print_to_pagebuf(true, buf, cpu_mask);
ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpu_mask));
free_cpumask_var(cpu_mask);
@ -1770,7 +1770,8 @@ struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *pr
topology_physical_package_id(id) : topology_logical_die_id(id);
if ((int)(rp->id) < 0) {
pr_err("topology_logical_(package/die)_id() returned a negative value");
return ERR_PTR(-EINVAL);
ret = -EINVAL;
goto err_free_package;
}
rp->lead_cpu = id;
if (!rapl_msrs_are_pkg_scope() && topology_max_dies_per_package() > 1)

View File

@ -146,6 +146,9 @@ struct cpufreq_policy {
/* Per policy boost supported flag. */
bool boost_supported;
/* Pending policy->min/max update for the driver */
bool update_limits;
/* Cached frequency lookup from cpufreq_driver_resolve_freq. */
unsigned int cached_target_freq;
unsigned int cached_resolved_idx;
@ -434,7 +437,7 @@ struct cpufreq_driver {
/*
* Set by drivers that need to update internal upper and lower boundaries along
* with the target frequency and so the core and governors should also invoke
* the diver if the target frequency does not change, but the policy min or max
* the driver if the target frequency does not change, but the policy min or max
* may have changed.
*/
#define CPUFREQ_NEED_UPDATE_LIMITS BIT(0)

View File

@ -42,6 +42,7 @@ config HIBERNATION
select CRC32
select CRYPTO
select CRYPTO_LZO
select CRYPTO_LZ4
help
Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the

View File

@ -392,23 +392,6 @@ static int create_image(int platform_mode)
return error;
}
static void shrink_shmem_memory(void)
{
struct sysinfo info;
unsigned long nr_shmem_pages, nr_freed_pages;
si_meminfo(&info);
nr_shmem_pages = info.sharedram; /* current page count used for shmem */
/*
* The intent is to reclaim all shmem pages. Though shrink_all_memory() can
* only reclaim about half of them, it's enough for creating the hibernation
* image.
*/
nr_freed_pages = shrink_all_memory(nr_shmem_pages);
pr_debug("requested to reclaim %lu shmem pages, actually freed %lu pages\n",
nr_shmem_pages, nr_freed_pages);
}
/**
* hibernation_snapshot - Quiesce devices and create a hibernation image.
* @platform_mode: If set, use platform driver to prepare for the transition.
@ -425,14 +408,9 @@ int hibernation_snapshot(int platform_mode)
if (error)
goto Close;
/* Preallocate image memory before shutting down devices. */
error = hibernate_preallocate_memory();
if (error)
goto Close;
error = freeze_kernel_threads();
if (error)
goto Cleanup;
goto Close;
if (hibernation_test(TEST_FREEZER)) {
@ -445,19 +423,13 @@ int hibernation_snapshot(int platform_mode)
}
error = dpm_prepare(PMSG_FREEZE);
if (error) {
dpm_complete(PMSG_RECOVER);
goto Thaw;
}
if (error)
goto Complete;
/*
* Device drivers may move lots of data to shmem in dpm_prepare(). The shmem
* pages will use lots of system memory, causing hibernation image creation
* fail due to insufficient free memory.
* This call is to force flush the shmem pages to swap disk and reclaim
* the system memory so that image creation can succeed.
*/
shrink_shmem_memory();
/* Preallocate image memory before shutting down devices. */
error = hibernate_preallocate_memory();
if (error)
goto Complete;
console_suspend_all();
pm_restrict_gfp_mask();
@ -492,10 +464,10 @@ int hibernation_snapshot(int platform_mode)
platform_end(platform_mode);
return error;
Complete:
dpm_complete(PMSG_RECOVER);
Thaw:
thaw_kernel_threads();
Cleanup:
swsusp_free();
goto Close;
}

View File

@ -519,18 +519,23 @@ static int __init cpu_latency_qos_init(void)
int ret;
ret = misc_register(&cpu_latency_qos_miscdev);
if (ret < 0)
if (ret < 0) {
pr_err("%s: %s setup failed\n", __func__,
cpu_latency_qos_miscdev.name);
return ret;
}
#ifdef CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP
ret = misc_register(&cpu_wakeup_latency_qos_miscdev);
if (ret < 0)
if (ret < 0) {
pr_err("%s: %s setup failed\n", __func__,
cpu_wakeup_latency_qos_miscdev.name);
misc_deregister(&cpu_latency_qos_miscdev);
return ret;
}
#endif
return ret;
return 0;
}
late_initcall(cpu_latency_qos_init);
#endif /* CONFIG_CPU_IDLE */

View File

@ -570,29 +570,23 @@ struct crc_data {
wait_queue_head_t done; /* crc update done */
u32 *crc32; /* points to handle's crc32 */
size_t **unc_len; /* uncompressed lengths */
unsigned char **unc; /* uncompressed data */
unsigned char *unc[]; /* uncompressed data */
};
static struct crc_data *alloc_crc_data(int nr_threads)
{
struct crc_data *crc;
crc = kzalloc_obj(*crc);
crc = kzalloc_flex(*crc, unc, nr_threads);
if (!crc)
return NULL;
crc->unc = kcalloc(nr_threads, sizeof(*crc->unc), GFP_KERNEL);
if (!crc->unc)
goto err_free_crc;
crc->unc_len = kzalloc_objs(*crc->unc_len, nr_threads);
if (!crc->unc_len)
goto err_free_unc;
goto err_free_crc;
return crc;
err_free_unc:
kfree(crc->unc);
err_free_crc:
kfree(crc);
return NULL;
@ -607,7 +601,6 @@ static void free_crc_data(struct crc_data *crc)
kthread_stop(crc->thr);
kfree(crc->unc_len);
kfree(crc->unc);
kfree(crc);
}

View File

@ -1042,11 +1042,13 @@ unsafe impl Sync for OPP {}
/// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted.
unsafe impl AlwaysRefCounted for OPP {
#[inline]
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::dev_pm_opp_get(self.0.get()) };
}
#[inline]
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
unsafe { bindings::dev_pm_opp_put(obj.cast().as_ptr()) }
@ -1095,6 +1097,7 @@ fn as_raw(&self) -> *mut bindings::dev_pm_opp {
}
/// Returns the frequency of an [`OPP`].
#[inline]
pub fn freq(&self, index: Option<u32>) -> Hertz {
let index = index.unwrap_or(0);

View File

@ -3155,7 +3155,7 @@ class TestProps:
dev = f[0]
props[dev] = DevProps()
props[dev].altname = f[1]
if int(f[2]):
if len(f) > 2 and f[2] and int(f[2]):
props[dev].isasync = True
else:
props[dev].isasync = False