Re: [PATCH v2 2/2] cpufreq: tegra194: Fix unlisted boot freq warning

2020-10-12 Thread Viresh Kumar
On 12-10-20, 22:36, Sumit Gupta wrote:
> Yes, this will also work. Then we don't need the current patch.
> You want me to send a patch with change from pr_warn to pr_info?

I have sent one.

-- 
viresh


Re: [PATCH v2 2/2] cpufreq: tegra194: Fix unlisted boot freq warning

2020-10-12 Thread Sumit Gupta

Warning coming during boot because the boot freq set by bootloader
gets filtered out due to big freq steps while creating freq_table.
Fix this by setting closest higher frequency from freq_table.
Warning:
   cpufreq: cpufreq_online: CPU0: Running at unlisted freq
   cpufreq: cpufreq_online: CPU0: Unlisted initial frequency changed

These warning messages also come during hotplug online of non-boot
CPU's while exiting from 'Suspend-to-RAM'. This happens because
during exit from 'Suspend-to-RAM', some time is taken to restore
last software requested CPU frequency written in register before
entering suspend.


And who does this restoration ?


To fix this, adding online hook to wait till the
current frequency becomes equal or close to the last requested
frequency.

Fixes: df320f89359c ("cpufreq: Add Tegra194 cpufreq driver")
Signed-off-by: Sumit Gupta 
---
  drivers/cpufreq/tegra194-cpufreq.c | 86 ++
  1 file changed, 79 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/tegra194-cpufreq.c 
b/drivers/cpufreq/tegra194-cpufreq.c
index d250e49..cc28b1e3 100644
--- a/drivers/cpufreq/tegra194-cpufreq.c
+++ b/drivers/cpufreq/tegra194-cpufreq.c
@@ -7,6 +7,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -21,7 +22,6 @@
  #define KHZ 1000
  #define REF_CLK_MHZ 408 /* 408 MHz */
  #define US_DELAY500
-#define US_DELAY_MIN2
  #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ)
  #define MAX_CNT ~0U

@@ -249,17 +249,22 @@ static unsigned int tegra194_get_speed(u32 cpu)
  static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
  {
   struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
- u32 cpu;
+ u32 cpu = policy->cpu;
+ int ret;
   u32 cl;

- smp_call_function_single(policy->cpu, get_cpu_cluster, , true);
+ if (!cpu_online(cpu))


Not required to check this.


OK.


+ return -EINVAL;
+
+ ret = smp_call_function_single(cpu, get_cpu_cluster, , true);
+ if (ret) {


Same as in the other patch.


Got.


+ pr_err("cpufreq: Failed to get cluster for CPU%d\n", cpu);
+ return ret;
+ }

   if (cl >= data->num_clusters)
   return -EINVAL;

- /* boot freq */
- policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY_MIN);
-
   /* set same policy for all cpus in a cluster */
   for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++)
   cpumask_set_cpu(cpu, policy->cpus);
@@ -267,7 +272,23 @@ static int tegra194_cpufreq_init(struct cpufreq_policy 
*policy)
   policy->freq_table = data->tables[cl];
   policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY;

- return 0;
+ policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
+
+ ret = cpufreq_table_validate_and_sort(policy);
+ if (ret)
+ return ret;
+
+ /* Are we running at unknown frequency ? */
+ ret = cpufreq_frequency_table_get_index(policy, policy->cur);
+ if (ret == -EINVAL) {
+ ret = __cpufreq_driver_target(policy, policy->cur - 1,
+   CPUFREQ_RELATION_L);
+ if (ret)
+ return ret;



+ policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);


cpufreq-core will do this anyway, you don't need to do it.


Got.


+ }
+
+ return ret;
  }


I wonder if I should change the pr_warn() in cpufreq-core to pr_info()
instead, will that help you guys ? Will that still be a problem ? This
is exactly same as what we do there.


Yes, this will also work. Then we don't need the current patch.
You want me to send a patch with change from pr_warn to pr_info?


  static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy,
@@ -285,6 +306,55 @@ static int tegra194_cpufreq_set_target(struct 
cpufreq_policy *policy,
   return 0;
  }

+static int tegra194_cpufreq_online(struct cpufreq_policy *policy)
+{
+ unsigned int interm_freq, last_set_freq;
+ struct cpufreq_frequency_table *pos;
+ u64 ndiv;
+ int ret;
+
+ if (!cpu_online(policy->cpu))
+ return -EINVAL;
+
+ /* get ndiv for the last frequency request from software  */
+ ret = smp_call_function_single(policy->cpu, get_cpu_ndiv, , true);
+ if (ret) {
+ pr_err("cpufreq: Failed to get ndiv for CPU%d\n", policy->cpu);
+ return ret;
+ }
+
+ cpufreq_for_each_valid_entry(pos, policy->freq_table) {
+ if (pos->driver_data == ndiv) {
+ last_set_freq = pos->frequency;
+ break;
+ }
+ }
+
+ policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
+ interm_freq =  policy->cur;
+
+ /*
+  * It takes some time to restore the previous frequency while
+  * turning-on non-boot cores during exit from 

Re: [PATCH v2 2/2] cpufreq: tegra194: Fix unlisted boot freq warning

2020-10-12 Thread Viresh Kumar
On 08-10-20, 18:31, Sumit Gupta wrote:
> Warning coming during boot because the boot freq set by bootloader
> gets filtered out due to big freq steps while creating freq_table.
> Fix this by setting closest higher frequency from freq_table.
> Warning:
>   cpufreq: cpufreq_online: CPU0: Running at unlisted freq
>   cpufreq: cpufreq_online: CPU0: Unlisted initial frequency changed
> 
> These warning messages also come during hotplug online of non-boot
> CPU's while exiting from 'Suspend-to-RAM'. This happens because
> during exit from 'Suspend-to-RAM', some time is taken to restore
> last software requested CPU frequency written in register before
> entering suspend.

And who does this restoration ?

> To fix this, adding online hook to wait till the
> current frequency becomes equal or close to the last requested
> frequency.
> 
> Fixes: df320f89359c ("cpufreq: Add Tegra194 cpufreq driver")
> Signed-off-by: Sumit Gupta 
> ---
>  drivers/cpufreq/tegra194-cpufreq.c | 86 
> ++
>  1 file changed, 79 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/cpufreq/tegra194-cpufreq.c 
> b/drivers/cpufreq/tegra194-cpufreq.c
> index d250e49..cc28b1e3 100644
> --- a/drivers/cpufreq/tegra194-cpufreq.c
> +++ b/drivers/cpufreq/tegra194-cpufreq.c
> @@ -7,6 +7,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -21,7 +22,6 @@
>  #define KHZ 1000
>  #define REF_CLK_MHZ 408 /* 408 MHz */
>  #define US_DELAY500
> -#define US_DELAY_MIN2
>  #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ)
>  #define MAX_CNT ~0U
>  
> @@ -249,17 +249,22 @@ static unsigned int tegra194_get_speed(u32 cpu)
>  static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
>  {
>   struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
> - u32 cpu;
> + u32 cpu = policy->cpu;
> + int ret;
>   u32 cl;
>  
> - smp_call_function_single(policy->cpu, get_cpu_cluster, , true);
> + if (!cpu_online(cpu))

Not required to check this.

> + return -EINVAL;
> +
> + ret = smp_call_function_single(cpu, get_cpu_cluster, , true);
> + if (ret) {

Same as in the other patch.

> + pr_err("cpufreq: Failed to get cluster for CPU%d\n", cpu);
> + return ret;
> + }
>  
>   if (cl >= data->num_clusters)
>   return -EINVAL;
>  
> - /* boot freq */
> - policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY_MIN);
> -
>   /* set same policy for all cpus in a cluster */
>   for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++)
>   cpumask_set_cpu(cpu, policy->cpus);
> @@ -267,7 +272,23 @@ static int tegra194_cpufreq_init(struct cpufreq_policy 
> *policy)
>   policy->freq_table = data->tables[cl];
>   policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY;
>  
> - return 0;
> + policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
> +
> + ret = cpufreq_table_validate_and_sort(policy);
> + if (ret)
> + return ret;
> +
> + /* Are we running at unknown frequency ? */
> + ret = cpufreq_frequency_table_get_index(policy, policy->cur);
> + if (ret == -EINVAL) {
> + ret = __cpufreq_driver_target(policy, policy->cur - 1,
> +   CPUFREQ_RELATION_L);
> + if (ret)
> + return ret;

> + policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);

cpufreq-core will do this anyway, you don't need to do it.

> + }
> +
> + return ret;
>  }

I wonder if I should change the pr_warn() in cpufreq-core to pr_info()
instead, will that help you guys ? Will that still be a problem ? This
is exactly same as what we do there.

>  static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy,
> @@ -285,6 +306,55 @@ static int tegra194_cpufreq_set_target(struct 
> cpufreq_policy *policy,
>   return 0;
>  }
>  
> +static int tegra194_cpufreq_online(struct cpufreq_policy *policy)
> +{
> + unsigned int interm_freq, last_set_freq;
> + struct cpufreq_frequency_table *pos;
> + u64 ndiv;
> + int ret;
> +
> + if (!cpu_online(policy->cpu))
> + return -EINVAL;
> +
> + /* get ndiv for the last frequency request from software  */
> + ret = smp_call_function_single(policy->cpu, get_cpu_ndiv, , true);
> + if (ret) {
> + pr_err("cpufreq: Failed to get ndiv for CPU%d\n", policy->cpu);
> + return ret;
> + }
> +
> + cpufreq_for_each_valid_entry(pos, policy->freq_table) {
> + if (pos->driver_data == ndiv) {
> + last_set_freq = pos->frequency;
> + break;
> + }
> + }
> +
> + policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
> + interm_freq =  policy->cur;
> +
> + /*
> +  * It takes 

[PATCH v2 2/2] cpufreq: tegra194: Fix unlisted boot freq warning

2020-10-08 Thread Sumit Gupta
Warning coming during boot because the boot freq set by bootloader
gets filtered out due to big freq steps while creating freq_table.
Fix this by setting closest higher frequency from freq_table.
Warning:
  cpufreq: cpufreq_online: CPU0: Running at unlisted freq
  cpufreq: cpufreq_online: CPU0: Unlisted initial frequency changed

These warning messages also come during hotplug online of non-boot
CPU's while exiting from 'Suspend-to-RAM'. This happens because
during exit from 'Suspend-to-RAM', some time is taken to restore
last software requested CPU frequency written in register before
entering suspend. To fix this, adding online hook to wait till the
current frequency becomes equal or close to the last requested
frequency.

Fixes: df320f89359c ("cpufreq: Add Tegra194 cpufreq driver")
Signed-off-by: Sumit Gupta 
---
 drivers/cpufreq/tegra194-cpufreq.c | 86 ++
 1 file changed, 79 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/tegra194-cpufreq.c 
b/drivers/cpufreq/tegra194-cpufreq.c
index d250e49..cc28b1e3 100644
--- a/drivers/cpufreq/tegra194-cpufreq.c
+++ b/drivers/cpufreq/tegra194-cpufreq.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -21,7 +22,6 @@
 #define KHZ 1000
 #define REF_CLK_MHZ 408 /* 408 MHz */
 #define US_DELAY500
-#define US_DELAY_MIN2
 #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ)
 #define MAX_CNT ~0U
 
@@ -249,17 +249,22 @@ static unsigned int tegra194_get_speed(u32 cpu)
 static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
 {
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
-   u32 cpu;
+   u32 cpu = policy->cpu;
+   int ret;
u32 cl;
 
-   smp_call_function_single(policy->cpu, get_cpu_cluster, , true);
+   if (!cpu_online(cpu))
+   return -EINVAL;
+
+   ret = smp_call_function_single(cpu, get_cpu_cluster, , true);
+   if (ret) {
+   pr_err("cpufreq: Failed to get cluster for CPU%d\n", cpu);
+   return ret;
+   }
 
if (cl >= data->num_clusters)
return -EINVAL;
 
-   /* boot freq */
-   policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY_MIN);
-
/* set same policy for all cpus in a cluster */
for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++)
cpumask_set_cpu(cpu, policy->cpus);
@@ -267,7 +272,23 @@ static int tegra194_cpufreq_init(struct cpufreq_policy 
*policy)
policy->freq_table = data->tables[cl];
policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY;
 
-   return 0;
+   policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
+
+   ret = cpufreq_table_validate_and_sort(policy);
+   if (ret)
+   return ret;
+
+   /* Are we running at unknown frequency ? */
+   ret = cpufreq_frequency_table_get_index(policy, policy->cur);
+   if (ret == -EINVAL) {
+   ret = __cpufreq_driver_target(policy, policy->cur - 1,
+ CPUFREQ_RELATION_L);
+   if (ret)
+   return ret;
+   policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
+   }
+
+   return ret;
 }
 
 static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy,
@@ -285,6 +306,55 @@ static int tegra194_cpufreq_set_target(struct 
cpufreq_policy *policy,
return 0;
 }
 
+static int tegra194_cpufreq_online(struct cpufreq_policy *policy)
+{
+   unsigned int interm_freq, last_set_freq;
+   struct cpufreq_frequency_table *pos;
+   u64 ndiv;
+   int ret;
+
+   if (!cpu_online(policy->cpu))
+   return -EINVAL;
+
+   /* get ndiv for the last frequency request from software  */
+   ret = smp_call_function_single(policy->cpu, get_cpu_ndiv, , true);
+   if (ret) {
+   pr_err("cpufreq: Failed to get ndiv for CPU%d\n", policy->cpu);
+   return ret;
+   }
+
+   cpufreq_for_each_valid_entry(pos, policy->freq_table) {
+   if (pos->driver_data == ndiv) {
+   last_set_freq = pos->frequency;
+   break;
+   }
+   }
+
+   policy->cur = tegra194_get_speed_common(policy->cpu, US_DELAY);
+   interm_freq =  policy->cur;
+
+   /*
+* It takes some time to restore the previous frequency while
+* turning-on non-boot cores during exit from SC7(Suspend-to-RAM).
+* So, wait till it reaches the previous value and timeout if the
+* time taken to reach requested freq is >100ms
+*/
+   ret = read_poll_timeout(tegra194_get_speed_common, policy->cur,
+   abs(policy->cur - last_set_freq) <= 115200, 0,
+   100 * USEC_PER_MSEC, false, policy->cpu,
+