linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).