support CPU turbo feature

Backport the following patches:
cpufreq: change '.set_boost' to act on one policy
cpufreq: CPPC: add SW BOOST support
This commit is contained in:
Yu Liao 2023-11-20 16:19:01 +08:00
parent 125bf8f275
commit ec9b7ab953
4 changed files with 334 additions and 1 deletions

View File

@ -32,7 +32,7 @@
Name: kernel
Version: 4.19.90
Release: %{hulkrelease}.0246
Release: %{hulkrelease}.0247
Summary: Linux Kernel
License: GPLv2
URL: http://www.kernel.org/
@ -850,6 +850,9 @@ fi
%changelog
* Mon Nov 20 2023 Yu Liao <liaoyu15@huawei.com> - 4.19.90-2311.3.0.0247
- Backport cpu turbo patches
* Fri Nov 17 2023 Zhou Kaiqi <zhoukaiqi@huawei.com> - 4.19.90-2311.3.0.0246
- genirq: Increase the number of IRQ descriptors
- irqchip: gic-v3: Collection table support muti pages

View File

@ -0,0 +1,186 @@
From a93e5e087b753c9fe954e4a82ae1224ba56732d0 Mon Sep 17 00:00:00 2001
From: Xiongfeng Wang <wangxiongfeng2@huawei.com>
Date: Sat, 30 May 2020 10:08:30 +0800
Subject: [PATCH openEuler-1.0-LTS 1/2] cpufreq: change '.set_boost' to act on
one policy
mainline inclusion
from mainline-v5.8-rc1
commit cf6fada71543ceea0f6228ffdc0b85778f3f5a6e
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I88RXU
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cf6fada71543ceea0f6228ffdc0b85778f3f5a6e
--------------------------------
Macro 'for_each_active_policy()' is defined internally. To avoid some
cpufreq driver needing this macro to iterate over all the policies in
'.set_boost' callback, we redefine '.set_boost' to act on only one
policy and pass the policy as an argument.
'cpufreq_boost_trigger_state()' iterates over all the policies to set
boost for the system.
This is preparation for adding SW BOOST support for CPPC.
To protect Boost enable/disable by sysfs from CPU online/offline,
add 'cpu_hotplug_lock' before calling '.set_boost' for each CPU.
Also move the lock from 'set_boost()' to 'store_cpb()' in
acpi_cpufreq.
Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
Suggested-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Subject & changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Conflicts:
drivers/cpufreq/cpufreq.c
Signed-off-by: Yu Liao <liaoyu15@huawei.com>
---
drivers/cpufreq/acpi-cpufreq.c | 14 ++++----
drivers/cpufreq/cpufreq.c | 58 +++++++++++++++++++---------------
include/linux/cpufreq.h | 2 +-
3 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index ce0a51849f66..189c7c9e2641 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -147,12 +147,12 @@ static void boost_set_msr_each(void *p_en)
boost_set_msr(enable);
}
-static int set_boost(int val)
+static int set_boost(struct cpufreq_policy *policy, int val)
{
- get_online_cpus();
- on_each_cpu(boost_set_msr_each, (void *)(long)val, 1);
- put_online_cpus();
- pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
+ on_each_cpu_mask(policy->cpus, boost_set_msr_each,
+ (void *)(long)val, 1);
+ pr_debug("CPU %*pbl: Core Boosting %sabled.\n",
+ cpumask_pr_args(policy->cpus), val ? "en" : "dis");
return 0;
}
@@ -183,7 +183,9 @@ static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
if (ret || val > 1)
return -EINVAL;
- set_boost(val);
+ get_online_cpus();
+ set_boost(policy, val);
+ put_online_cpus();
return count;
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 99ca9c50a88f..49ed22b45fb7 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2347,34 +2347,32 @@ EXPORT_SYMBOL(cpufreq_update_policy);
/*********************************************************************
* BOOST *
*********************************************************************/
-static int cpufreq_boost_set_sw(int state)
+static int cpufreq_boost_set_sw(struct cpufreq_policy *policy, int state)
{
- struct cpufreq_policy *policy;
int ret = -EINVAL;
- for_each_active_policy(policy) {
- if (!policy->freq_table)
- continue;
-
- ret = cpufreq_frequency_table_cpuinfo(policy,
- policy->freq_table);
- if (ret) {
- pr_err("%s: Policy frequency update failed\n",
- __func__);
- break;
- }
+ if (!policy->freq_table)
+ return -EINVAL;
- down_write(&policy->rwsem);
- policy->user_policy.max = policy->max;
- cpufreq_governor_limits(policy);
- up_write(&policy->rwsem);
+ ret = cpufreq_frequency_table_cpuinfo(policy,
+ policy->freq_table);
+ if (ret) {
+ pr_err("%s: Policy frequency update failed\n",
+ __func__);
+ return ret;
}
+ down_write(&policy->rwsem);
+ policy->user_policy.max = policy->max;
+ cpufreq_governor_limits(policy);
+ up_write(&policy->rwsem);
+
return ret;
}
int cpufreq_boost_trigger_state(int state)
{
+ struct cpufreq_policy *policy;
unsigned long flags;
int ret = 0;
@@ -2385,15 +2383,25 @@ int cpufreq_boost_trigger_state(int state)
cpufreq_driver->boost_enabled = state;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
- ret = cpufreq_driver->set_boost(state);
- if (ret) {
- write_lock_irqsave(&cpufreq_driver_lock, flags);
- cpufreq_driver->boost_enabled = !state;
- write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
- pr_err("%s: Cannot %s BOOST\n",
- __func__, state ? "enable" : "disable");
+ get_online_cpus();
+ for_each_active_policy(policy) {
+ ret = cpufreq_driver->set_boost(policy, state);
+ if (ret)
+ goto err_reset_state;
}
+ put_online_cpus();
+
+ return 0;
+
+err_reset_state:
+ put_online_cpus();
+
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+ cpufreq_driver->boost_enabled = !state;
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ pr_err("%s: Cannot %s BOOST\n",
+ __func__, state ? "enable" : "disable");
return ret;
}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3361663144a1..ff6b10552c86 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -334,7 +334,7 @@ struct cpufreq_driver {
/* platform specific boost support code */
bool boost_enabled;
- int (*set_boost)(int state);
+ int (*set_boost)(struct cpufreq_policy *policy, int state);
};
/* flags */
--
2.25.1

View File

@ -0,0 +1,142 @@
From 5cca93b9a9e4690a8491f6fde455ff0268f1e92a Mon Sep 17 00:00:00 2001
From: Xiongfeng Wang <wangxiongfeng2@huawei.com>
Date: Sat, 30 May 2020 10:08:31 +0800
Subject: [PATCH openEuler-1.0-LTS 2/2] cpufreq: CPPC: add SW BOOST support
mainline inclusion
from mainline-v5.8-rc1
commit 54e74df5d76dea824c7c0c9d1b97150bf9b33793
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I88RXU
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54e74df5d76dea824c7c0c9d1b97150bf9b33793
--------------------------------
To add SW BOOST support for CPPC, we need to get the max frequency of
boost mode and non-boost mode. ACPI spec 6.2 section 8.4.7.1 describes
the following two CPC registers.
"Highest performance is the absolute maximum performance an individual
processor may reach, assuming ideal conditions. This performance level
may not be sustainable for long durations, and may only be achievable if
other platform components are in a specific state; for example, it may
require other processors be in an idle state.
Nominal Performance is the maximum sustained performance level of the
processor, assuming ideal operating conditions. In absence of an
external constraint (power, thermal, etc.) this is the performance level
the platform is expected to be able to maintain continuously. All
processors are expected to be able to sustain their nominal performance
state simultaneously."
To add SW BOOST support for CPPC, we can use Highest Performance as the
max performance in boost mode and Nominal Performance as the max
performance in non-boost mode. If the Highest Performance is greater
than the Nominal Performance, we assume SW BOOST is supported.
The current CPPC driver does not support SW BOOST and use 'Highest
Performance' as the max performance the CPU can achieve. 'Nominal
Performance' is used to convert 'performance' to 'frequency'. That
means, if firmware enable boost and provide a value for Highest
Performance which is greater than Nominal Performance, boost feature is
enabled by default.
Because SW BOOST is disabled by default, so, after this patch, boost
feature is disabled by default even if boost is enabled by firmware.
Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
Suggested-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Subject ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Yu Liao <liaoyu15@huawei.com>
---
drivers/cpufreq/cppc_cpufreq.c | 35 ++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 0a245f1caa95..15cffca10f1a 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -41,6 +41,7 @@
* requested etc.
*/
static struct cppc_cpudata **all_cpu_data;
+static bool boost_supported;
struct cppc_workaround_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
@@ -314,7 +315,7 @@ 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_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_nonlinear_perf);
- policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
+ policy->max = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf);
/*
* Set cpuinfo.min_freq to Lowest to make the full range of performance
@@ -322,7 +323,7 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
* nonlinear perf
*/
policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.lowest_perf);
- policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.highest_perf);
+ policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, cpu->perf_caps.nominal_perf);
policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu_num);
policy->shared_type = cpu->shared_type;
@@ -347,6 +348,13 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpu->cur_policy = policy;
+ /*
+ * If 'highest_perf' is greater than 'nominal_perf', we assume CPU Boost
+ * is supported.
+ */
+ if (cpu->perf_caps.highest_perf > cpu->perf_caps.nominal_perf)
+ boost_supported = true;
+
/* Set policy->cur to max now. The governors will adjust later. */
policy->cur = cppc_cpufreq_perf_to_khz(cpu,
cpu->perf_caps.highest_perf);
@@ -414,6 +422,28 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum)
return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1);
}
+static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
+{
+ struct cppc_cpudata *cpudata;
+ int ret;
+
+ if (!boost_supported) {
+ pr_err("BOOST not supported by CPU or firmware\n");
+ return -EINVAL;
+ }
+
+ cpudata = all_cpu_data[policy->cpu];
+ if (state)
+ policy->max = cppc_cpufreq_perf_to_khz(cpudata,
+ cpudata->perf_caps.highest_perf);
+ else
+ policy->max = cppc_cpufreq_perf_to_khz(cpudata,
+ cpudata->perf_caps.nominal_perf);
+ policy->cpuinfo.max_freq = policy->max;
+
+ return 0;
+}
+
static struct cpufreq_driver cppc_cpufreq_driver = {
.flags = CPUFREQ_CONST_LOOPS,
.verify = cppc_verify_policy,
@@ -421,6 +451,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.get = cppc_cpufreq_get_rate,
.init = cppc_cpufreq_cpu_init,
.stop_cpu = cppc_cpufreq_stop_cpu,
+ .set_boost = cppc_cpufreq_set_boost,
.name = "cppc_cpufreq",
};
--
2.25.1

View File

@ -647,3 +647,5 @@ patches/0643-net-hns3-Fix-ethtool_-Ops-gen_-Improper-modification.patch
patches/0644-net-hns3-Fix-unreasonable-modifications-caused-by-ro.patch
patches/0645-irqchip-gic-v3-Collection-table-support-muti-pages.patch
patches/0646-genirq-Increase-the-number-of-IRQ-descriptors.patch
patches/0647-cpufreq-change-.set_boost-to-act-on-one-policy.patch
patches/0648-cpufreq-CPPC-add-SW-BOOST-support.patch