From 29dcbea92460e82181774b46f08b55a917615a97 Mon Sep 17 00:00:00 2001 From: Christian Loehle Date: Thu, 17 Oct 2024 23:00:33 +0100 Subject: [PATCH 1/3] cpufreq: docs: Reflect latency changes in docs There were two changes related to transition latency recently. Namely commit e13aa799c2a6 ("cpufreq: Change default transition delay to 2ms") and commit 37c6dccd6837 ("cpufreq: Remove LATENCY_MULTIPLIER"). Both changed the defaults / maximums so let the documentation reflect that. Signed-off-by: Christian Loehle Link: https://patch.msgid.link/46853b6e-bad5-4ace-9b23-ff157f234ae3@arm.com Signed-off-by: Rafael J. Wysocki --- Documentation/admin-guide/pm/cpufreq.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/admin-guide/pm/cpufreq.rst b/Documentation/admin-guide/pm/cpufreq.rst index fe1be4ad88cb..a21369eba034 100644 --- a/Documentation/admin-guide/pm/cpufreq.rst +++ b/Documentation/admin-guide/pm/cpufreq.rst @@ -425,8 +425,8 @@ This governor exposes only one tunable: ``rate_limit_us`` Minimum time (in microseconds) that has to pass between two consecutive - runs of governor computations (default: 1000 times the scaling driver's - transition latency). + runs of governor computations (default: 1.5 times the scaling driver's + transition latency or the maximum 2ms). The purpose of this tunable is to reduce the scheduler context overhead of the governor which might be excessive without it. @@ -474,17 +474,17 @@ This governor exposes the following tunables: This is how often the governor's worker routine should run, in microseconds. - Typically, it is set to values of the order of 10000 (10 ms). Its - default value is equal to the value of ``cpuinfo_transition_latency`` - for each policy this governor is attached to (but since the unit here - is greater by 1000, this means that the time represented by - ``sampling_rate`` is 1000 times greater than the transition latency by - default). + Typically, it is set to values of the order of 2000 (2 ms). Its + default value is to add a 50% breathing room + to ``cpuinfo_transition_latency`` on each policy this governor is + attached to. The minimum is typically the length of two scheduler + ticks. If this tunable is per-policy, the following shell command sets the time - represented by it to be 750 times as high as the transition latency:: + represented by it to be 1.5 times as high as the transition latency + (the default):: - # echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) > ondemand/sampling_rate + # echo `$(($(cat cpuinfo_transition_latency) * 3 / 2)) > ondemand/sampling_rate ``up_threshold`` If the estimated CPU load is above this value (in percent), the governor From 5209d1b654f1db80509040cc694c7814a1b547e3 Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Fri, 18 Oct 2024 10:12:05 +0800 Subject: [PATCH 2/3] powercap: dtpm_devfreq: Fix error check against dev_pm_qos_add_request() The caller of the function dev_pm_qos_add_request() checks again a non zero value but dev_pm_qos_add_request() can return '1' if the request already exists. Therefore, the setup function fails while the QoS request actually did not failed. Fix that by changing the check against a negative value like all the other callers of the function. Fixes: e44655617317 ("powercap/drivers/dtpm: Add dtpm devfreq with energy model support") Signed-off-by: Yuan Can Reviewed-by: Lukasz Luba Link: https://patch.msgid.link/20241018021205.46460-1-yuancan@huawei.com [ rjw: Subject edit ] Signed-off-by: Rafael J. Wysocki --- drivers/powercap/dtpm_devfreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/powercap/dtpm_devfreq.c b/drivers/powercap/dtpm_devfreq.c index f40bce8176df..d1dff6ccab12 100644 --- a/drivers/powercap/dtpm_devfreq.c +++ b/drivers/powercap/dtpm_devfreq.c @@ -178,7 +178,7 @@ static int __dtpm_devfreq_setup(struct devfreq *devfreq, struct dtpm *parent) ret = dev_pm_qos_add_request(dev, &dtpm_devfreq->qos_req, DEV_PM_QOS_MAX_FREQUENCY, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); - if (ret) { + if (ret < 0) { pr_err("Failed to add QoS request: %d\n", ret); goto out_dtpm_unregister; } From d93df29bdab133b85e94b3c328e7fe26a0ebd56c Mon Sep 17 00:00:00 2001 From: liwei Date: Thu, 24 Oct 2024 10:29:52 +0800 Subject: [PATCH 3/3] cpufreq: CPPC: fix perf_to_khz/khz_to_perf conversion exception When the nominal_freq recorded by the kernel is equal to the lowest_freq, and the frequency adjustment operation is triggered externally, there is a logic error in cppc_perf_to_khz()/cppc_khz_to_perf(), resulting in perf and khz conversion errors. Fix this by adding a branch processing logic when nominal_freq is equal to lowest_freq. Fixes: ec1c7ad47664 ("cpufreq: CPPC: Fix performance/frequency conversion") Signed-off-by: liwei Acked-by: Viresh Kumar Link: https://patch.msgid.link/20241024022952.2627694-1-liwei728@huawei.com [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index b73b3aa92f3f..c3fc2c05d868 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -1916,9 +1916,15 @@ unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf) u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - mul = caps->nominal_freq - caps->lowest_freq; + /* Avoid special case when nominal_freq is equal to lowest_freq */ + if (caps->lowest_freq == caps->nominal_freq) { + mul = caps->nominal_freq; + div = caps->nominal_perf; + } else { + mul = caps->nominal_freq - caps->lowest_freq; + div = caps->nominal_perf - caps->lowest_perf; + } mul *= KHZ_PER_MHZ; - div = caps->nominal_perf - caps->lowest_perf; offset = caps->nominal_freq * KHZ_PER_MHZ - div64_u64(caps->nominal_perf * mul, div); } else { @@ -1939,11 +1945,17 @@ unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq) { s64 retval, offset = 0; static u64 max_khz; - u64 mul, div; + u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - mul = caps->nominal_perf - caps->lowest_perf; - div = caps->nominal_freq - caps->lowest_freq; + /* Avoid special case when nominal_freq is equal to lowest_freq */ + if (caps->lowest_freq == caps->nominal_freq) { + mul = caps->nominal_perf; + div = caps->nominal_freq; + } else { + mul = caps->nominal_perf - caps->lowest_perf; + div = caps->nominal_freq - caps->lowest_freq; + } /* * We don't need to convert to kHz for computing offset and can * directly use nominal_freq and lowest_freq as the div64_u64