Merge back earlier cpufreq material for 7.2

This commit is contained in:
Rafael J. Wysocki 2026-05-29 14:39:36 +02:00
commit f02504316b
11 changed files with 72 additions and 287 deletions

View File

@ -1669,10 +1669,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

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

@ -1972,6 +1972,7 @@ void cpufreq_suspend(void)
if (!cpufreq_driver)
return;
cpus_read_lock();
if (!has_target() && !cpufreq_driver->suspend)
goto suspend;
@ -1991,6 +1992,7 @@ void cpufreq_suspend(void)
suspend:
cpufreq_suspended = true;
cpus_read_unlock();
}
/**
@ -2366,9 +2368,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 +2626,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 +2659,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

@ -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);
@ -3824,6 +3826,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;

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)