* [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate
@ 2023-05-15 10:00 Zeng Heng
2023-05-15 10:00 ` [PATCH 2/2] acpi: CPPC: read delivered_reg and reference_reg in critical section Zeng Heng
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Zeng Heng @ 2023-05-15 10:00 UTC (permalink / raw)
To: lenb, viresh.kumar, rafael
Cc: weiyongjun1, linux-pm, linux-kernel, xiexiuqi, linux-acpi,
liwei391, wangxiongfeng2
As ARM AMU's document says, all counters are subject to any changes
in clock frequency, including clock stopping caused by the WFI and WFE
instructions.
Therefore, using smp_call_function_single() to trigger target CPU to
read self's AMU counters, which ensures the counters are working
properly during calculation.
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
---
drivers/cpufreq/cppc_cpufreq.c | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 022e3555407c..169af7ff9a2a 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -837,29 +837,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
return (reference_perf * delta_delivered) / delta_reference;
}
+static void cppc_get_perf_ctrs_smp(void *val)
+{
+ int cpu = smp_processor_id();
+ struct cppc_perf_fb_ctrs *fb_ctrs = val;
+
+ cppc_get_perf_ctrs(cpu, fb_ctrs);
+
+ udelay(2); /* 2usec delay between sampling */
+
+ cppc_get_perf_ctrs(cpu, fb_ctrs + 1);
+}
+
static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
{
- struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
+ struct cppc_perf_fb_ctrs fb_ctrs[2] = {0};
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
struct cppc_cpudata *cpu_data = policy->driver_data;
u64 delivered_perf;
- int ret;
cpufreq_cpu_put(policy);
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
- if (ret)
- return ret;
-
- udelay(2); /* 2usec delay between sampling */
-
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
- if (ret)
- return ret;
-
- delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
- &fb_ctrs_t1);
+ smp_call_function_single(cpu, cppc_get_perf_ctrs_smp, fb_ctrs, 1);
+ delivered_perf = cppc_perf_from_fbctrs(cpu_data, fb_ctrs,
+ fb_ctrs + 1);
return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] acpi: CPPC: read delivered_reg and reference_reg in critical section
2023-05-15 10:00 [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate Zeng Heng
@ 2023-05-15 10:00 ` Zeng Heng
2023-05-15 10:00 ` [PATCH 0/2] drivers/cpufreq: gain accurate CPU frequency from cpufreq/scaling_cur_freq Zeng Heng
2023-05-15 10:31 ` [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate liwei (GF)
2 siblings, 0 replies; 4+ messages in thread
From: Zeng Heng @ 2023-05-15 10:00 UTC (permalink / raw)
To: lenb, viresh.kumar, rafael
Cc: weiyongjun1, linux-pm, linux-kernel, xiexiuqi, linux-acpi,
liwei391, wangxiongfeng2
Reading the content of delivered_reg and reference_reg should be in
the same critical section, in case any interrupt comes, which could
lead to inaccurate frequency calculation.
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
---
drivers/acpi/cppc_acpi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index c51d3ccb4cca..176f3e2e67f8 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1315,6 +1315,7 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
struct cppc_pcc_data *pcc_ss_data = NULL;
u64 delivered, reference, ref_perf, ctr_wrap_time;
int ret = 0, regs_in_pcc = 0;
+ unsigned long flags;
if (!cpc_desc) {
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
@@ -1350,8 +1351,11 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
}
}
+ local_irq_save(flags);
cpc_read(cpunum, delivered_reg, &delivered);
cpc_read(cpunum, reference_reg, &reference);
+ local_irq_restore(flags);
+
cpc_read(cpunum, ref_perf_reg, &ref_perf);
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 0/2] drivers/cpufreq: gain accurate CPU frequency from cpufreq/scaling_cur_freq
2023-05-15 10:00 [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate Zeng Heng
2023-05-15 10:00 ` [PATCH 2/2] acpi: CPPC: read delivered_reg and reference_reg in critical section Zeng Heng
@ 2023-05-15 10:00 ` Zeng Heng
2023-05-15 10:31 ` [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate liwei (GF)
2 siblings, 0 replies; 4+ messages in thread
From: Zeng Heng @ 2023-05-15 10:00 UTC (permalink / raw)
To: lenb, viresh.kumar, rafael
Cc: weiyongjun1, linux-pm, linux-kernel, xiexiuqi, linux-acpi,
liwei391, wangxiongfeng2
When users want to get frequency by scaling_cur_freq under cpufreq sysfs,
they often get the invalid result like:
$ cat /sys/devices/system/cpu/cpu6/cpufreq/scaling_cur_freq
4294967295
So this series provides fixes to the concerned issue.
Zeng Heng (2):
cpufreq: CPPC: keep target core awake when reading its cpufreq rate
acpi: CPPC: read delivered_reg and reference_reg in critical section
drivers/acpi/cppc_acpi.c | 4 ++++
drivers/cpufreq/cppc_cpufreq.c | 30 ++++++++++++++++--------------
2 files changed, 20 insertions(+), 14 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate
2023-05-15 10:00 [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate Zeng Heng
2023-05-15 10:00 ` [PATCH 2/2] acpi: CPPC: read delivered_reg and reference_reg in critical section Zeng Heng
2023-05-15 10:00 ` [PATCH 0/2] drivers/cpufreq: gain accurate CPU frequency from cpufreq/scaling_cur_freq Zeng Heng
@ 2023-05-15 10:31 ` liwei (GF)
2 siblings, 0 replies; 4+ messages in thread
From: liwei (GF) @ 2023-05-15 10:31 UTC (permalink / raw)
To: Zeng Heng
Cc: weiyongjun1, linux-pm, linux-kernel, xiexiuqi, linux-acpi,
wangxiongfeng2, lenb, viresh.kumar, rafael
On 2023/5/15 18:00, Zeng Heng wrote:
> As ARM AMU's document says, all counters are subject to any changes
> in clock frequency, including clock stopping caused by the WFI and WFE
> instructions.
>
> Therefore, using smp_call_function_single() to trigger target CPU to
> read self's AMU counters, which ensures the counters are working
> properly during calculation.
>
> Signed-off-by: Zeng Heng <zengheng4@huawei.com>
> ---
> drivers/cpufreq/cppc_cpufreq.c | 30 ++++++++++++++++--------------
> 1 file changed, 16 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 022e3555407c..169af7ff9a2a 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -837,29 +837,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
> return (reference_perf * delta_delivered) / delta_reference;
> }
>
> +static void cppc_get_perf_ctrs_smp(void *val)
> +{
> + int cpu = smp_processor_id();
> + struct cppc_perf_fb_ctrs *fb_ctrs = val;
> +
> + cppc_get_perf_ctrs(cpu, fb_ctrs);
> +
> + udelay(2); /* 2usec delay between sampling */
> +
> + cppc_get_perf_ctrs(cpu, fb_ctrs + 1);
> +}
> +
> static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
> {
> - struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
> + struct cppc_perf_fb_ctrs fb_ctrs[2] = {0};
> struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
> struct cppc_cpudata *cpu_data = policy->driver_data;
> u64 delivered_perf;
> - int ret;
>
> cpufreq_cpu_put(policy);
>
> - ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
> - if (ret)
> - return ret;
> -
> - udelay(2); /* 2usec delay between sampling */
> -
> - ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
> - if (ret)
> - return ret;
> -
> - delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
> - &fb_ctrs_t1);
> + smp_call_function_single(cpu, cppc_get_perf_ctrs_smp, fb_ctrs, 1);
cppc_get_perf_ctrs() may call down_write(), while the callback for smp_call_function_single()
should be non-blocking, you can use smp_call_on_cpu() instead.
>
> + delivered_perf = cppc_perf_from_fbctrs(cpu_data, fb_ctrs,
> + fb_ctrs + 1);
> return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
> }
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-05-15 10:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-15 10:00 [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate Zeng Heng
2023-05-15 10:00 ` [PATCH 2/2] acpi: CPPC: read delivered_reg and reference_reg in critical section Zeng Heng
2023-05-15 10:00 ` [PATCH 0/2] drivers/cpufreq: gain accurate CPU frequency from cpufreq/scaling_cur_freq Zeng Heng
2023-05-15 10:31 ` [PATCH 1/2] cpufreq: CPPC: keep target core awake when reading its cpufreq rate liwei (GF)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).