Re: [PATCH v6 11/19] PM / devfreq: tegra30: Use CPUFreq notifier

2019-10-02 Thread Dmitry Osipenko
02.10.2019 03:02, Chanwoo Choi пишет:
> Hi,
> 
> On 19. 8. 12. 오전 6:23, Dmitry Osipenko wrote:
>> The CPU's client need to take into account that CPUFreq may change
>> while memory activity not, staying high. Thus an appropriate frequency
>> notifier should be used in addition to the clk-notifier.
>>
>> Signed-off-by: Dmitry Osipenko 
>> ---
>>  drivers/devfreq/tegra30-devfreq.c | 173 ++
>>  1 file changed, 153 insertions(+), 20 deletions(-)
>>
>> diff --git a/drivers/devfreq/tegra30-devfreq.c 
>> b/drivers/devfreq/tegra30-devfreq.c
>> index a2623de56d20..a260812f7744 100644
>> --- a/drivers/devfreq/tegra30-devfreq.c
>> +++ b/drivers/devfreq/tegra30-devfreq.c
>> @@ -17,6 +17,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  
>>  #include "governor.h"
>>  
>> @@ -34,6 +35,8 @@
>>  #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN  BIT(30)
>>  #define ACTMON_DEV_CTRL_ENB BIT(31)
>>  
>> +#define ACTMON_DEV_CTRL_STOP
>> 0x
>> +
>>  #define ACTMON_DEV_UPPER_WMARK  0x4
>>  #define ACTMON_DEV_LOWER_WMARK  0x8
>>  #define ACTMON_DEV_INIT_AVG 0xc
>> @@ -159,7 +162,10 @@ struct tegra_devfreq {
>>  
>>  struct clk  *emc_clock;
>>  unsigned long   max_freq;
>> -struct notifier_block   rate_change_nb;
>> +struct notifier_block   clk_rate_change_nb;
>> +
>> +struct delayed_work cpufreq_update_work;
>> +struct notifier_block   cpu_rate_change_nb;
>>  
>>  struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
>>  
>> @@ -207,10 +213,10 @@ static unsigned long do_percent(unsigned long val, 
>> unsigned int pct)
>>  return val * pct / 100;
>>  }
>>  
>> -static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra)
>> +static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
>> +unsigned int cpu_freq)
>>  {
>>  struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios;
>> -unsigned int cpu_freq = cpufreq_quick_get(0);
>>  unsigned int i;
>>  
>>  for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) {
>> @@ -244,7 +250,8 @@ tegra_actmon_account_cpu_freq(struct tegra_devfreq 
>> *tegra,
>>  return target_freq;
>>  
>>  if (dev->avg_freq > tegra_actmon_dev_avg_dependency_freq(tegra, dev))
>> -static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra);
>> +static_cpu_emc_freq = actmon_cpu_to_emc_rate(
>> +tegra, cpufreq_quick_get(0));
>>  else
>>  static_cpu_emc_freq = 0;
>>  
>> @@ -543,8 +550,8 @@ static irqreturn_t actmon_thread_isr(int irq, void *data)
>>  return handled ? IRQ_HANDLED : IRQ_NONE;
>>  }
>>  
>> -static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
>> -   unsigned long action, void *ptr)
>> +static int tegra_actmon_clk_notify_cb(struct notifier_block *nb,
>> +  unsigned long action, void *ptr)
>>  {
>>  struct clk_notifier_data *data = ptr;
>>  struct tegra_devfreq_device *dev;
>> @@ -555,7 +562,7 @@ static int tegra_actmon_rate_notify_cb(struct 
>> notifier_block *nb,
>>  if (action != POST_RATE_CHANGE)
>>  return NOTIFY_OK;
>>  
>> -tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
>> +tegra = container_of(nb, struct tegra_devfreq, clk_rate_change_nb);
>>  
>>  freq = data->new_rate / KHZ;
>>  
>> @@ -586,6 +593,94 @@ static int tegra_actmon_rate_notify_cb(struct 
>> notifier_block *nb,
>>  return NOTIFY_OK;
>>  }
>>  
>> +static void tegra_actmon_delayed_update(struct work_struct *work)
>> +{
>> +struct tegra_devfreq *tegra = container_of(work, struct tegra_devfreq,
>> +   cpufreq_update_work.work);
>> +
>> +mutex_lock(>devfreq->lock);
>> +update_devfreq(tegra->devfreq);
>> +mutex_unlock(>devfreq->lock);
>> +}
>> +
>> +static unsigned long
>> +tegra_actmon_cpufreq_contribution(struct tegra_devfreq *tegra,
>> +  unsigned int cpu_freq)
>> +{
>> +unsigned long freq, static_cpu_emc_freq;
>> +
>> +/* check whether CPU's freq is taken into account at all */
>> +freq = tegra_actmon_dev_avg_dependency_freq(tegra,
>> +>devices[MCCPU]);
>> +if (tegra->devices[MCCPU].avg_freq <= freq)
>> +return 0;
>> +
>> +static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
>> +
>> +/* compare static CPU-EMC freq with MCALL */
>> +freq = tegra->devices[MCALL].avg_freq +
>> +   tegra->devices[MCALL].boost_freq;
>> +
>> +freq = tegra_actmon_upper_freq(tegra, freq);
>> +
>> +if (freq == tegra->max_freq || freq >= 

Re: [PATCH v6 11/19] PM / devfreq: tegra30: Use CPUFreq notifier

2019-10-01 Thread Chanwoo Choi
Hi,

On 19. 8. 12. 오전 6:23, Dmitry Osipenko wrote:
> The CPU's client need to take into account that CPUFreq may change
> while memory activity not, staying high. Thus an appropriate frequency
> notifier should be used in addition to the clk-notifier.
> 
> Signed-off-by: Dmitry Osipenko 
> ---
>  drivers/devfreq/tegra30-devfreq.c | 173 ++
>  1 file changed, 153 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/devfreq/tegra30-devfreq.c 
> b/drivers/devfreq/tegra30-devfreq.c
> index a2623de56d20..a260812f7744 100644
> --- a/drivers/devfreq/tegra30-devfreq.c
> +++ b/drivers/devfreq/tegra30-devfreq.c
> @@ -17,6 +17,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include "governor.h"
>  
> @@ -34,6 +35,8 @@
>  #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN   BIT(30)
>  #define ACTMON_DEV_CTRL_ENB  BIT(31)
>  
> +#define ACTMON_DEV_CTRL_STOP 0x
> +
>  #define ACTMON_DEV_UPPER_WMARK   0x4
>  #define ACTMON_DEV_LOWER_WMARK   0x8
>  #define ACTMON_DEV_INIT_AVG  0xc
> @@ -159,7 +162,10 @@ struct tegra_devfreq {
>  
>   struct clk  *emc_clock;
>   unsigned long   max_freq;
> - struct notifier_block   rate_change_nb;
> + struct notifier_block   clk_rate_change_nb;
> +
> + struct delayed_work cpufreq_update_work;
> + struct notifier_block   cpu_rate_change_nb;
>  
>   struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
>  
> @@ -207,10 +213,10 @@ static unsigned long do_percent(unsigned long val, 
> unsigned int pct)
>   return val * pct / 100;
>  }
>  
> -static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra)
> +static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
> + unsigned int cpu_freq)
>  {
>   struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios;
> - unsigned int cpu_freq = cpufreq_quick_get(0);
>   unsigned int i;
>  
>   for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) {
> @@ -244,7 +250,8 @@ tegra_actmon_account_cpu_freq(struct tegra_devfreq *tegra,
>   return target_freq;
>  
>   if (dev->avg_freq > tegra_actmon_dev_avg_dependency_freq(tegra, dev))
> - static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra);
> + static_cpu_emc_freq = actmon_cpu_to_emc_rate(
> + tegra, cpufreq_quick_get(0));
>   else
>   static_cpu_emc_freq = 0;
>  
> @@ -543,8 +550,8 @@ static irqreturn_t actmon_thread_isr(int irq, void *data)
>   return handled ? IRQ_HANDLED : IRQ_NONE;
>  }
>  
> -static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
> -unsigned long action, void *ptr)
> +static int tegra_actmon_clk_notify_cb(struct notifier_block *nb,
> +   unsigned long action, void *ptr)
>  {
>   struct clk_notifier_data *data = ptr;
>   struct tegra_devfreq_device *dev;
> @@ -555,7 +562,7 @@ static int tegra_actmon_rate_notify_cb(struct 
> notifier_block *nb,
>   if (action != POST_RATE_CHANGE)
>   return NOTIFY_OK;
>  
> - tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
> + tegra = container_of(nb, struct tegra_devfreq, clk_rate_change_nb);
>  
>   freq = data->new_rate / KHZ;
>  
> @@ -586,6 +593,94 @@ static int tegra_actmon_rate_notify_cb(struct 
> notifier_block *nb,
>   return NOTIFY_OK;
>  }
>  
> +static void tegra_actmon_delayed_update(struct work_struct *work)
> +{
> + struct tegra_devfreq *tegra = container_of(work, struct tegra_devfreq,
> +cpufreq_update_work.work);
> +
> + mutex_lock(>devfreq->lock);
> + update_devfreq(tegra->devfreq);
> + mutex_unlock(>devfreq->lock);
> +}
> +
> +static unsigned long
> +tegra_actmon_cpufreq_contribution(struct tegra_devfreq *tegra,
> +   unsigned int cpu_freq)
> +{
> + unsigned long freq, static_cpu_emc_freq;
> +
> + /* check whether CPU's freq is taken into account at all */
> + freq = tegra_actmon_dev_avg_dependency_freq(tegra,
> + >devices[MCCPU]);
> + if (tegra->devices[MCCPU].avg_freq <= freq)
> + return 0;
> +
> + static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
> +
> + /* compare static CPU-EMC freq with MCALL */
> + freq = tegra->devices[MCALL].avg_freq +
> +tegra->devices[MCALL].boost_freq;
> +
> + freq = tegra_actmon_upper_freq(tegra, freq);
> +
> + if (freq == tegra->max_freq || freq >= static_cpu_emc_freq)
> + return 0;
> +
> + /* compare static CPU-EMC freq with MCCPU */
> + freq = 

[PATCH v6 11/19] PM / devfreq: tegra30: Use CPUFreq notifier

2019-08-11 Thread Dmitry Osipenko
The CPU's client need to take into account that CPUFreq may change
while memory activity not, staying high. Thus an appropriate frequency
notifier should be used in addition to the clk-notifier.

Signed-off-by: Dmitry Osipenko 
---
 drivers/devfreq/tegra30-devfreq.c | 173 ++
 1 file changed, 153 insertions(+), 20 deletions(-)

diff --git a/drivers/devfreq/tegra30-devfreq.c 
b/drivers/devfreq/tegra30-devfreq.c
index a2623de56d20..a260812f7744 100644
--- a/drivers/devfreq/tegra30-devfreq.c
+++ b/drivers/devfreq/tegra30-devfreq.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "governor.h"
 
@@ -34,6 +35,8 @@
 #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30)
 #define ACTMON_DEV_CTRL_ENBBIT(31)
 
+#define ACTMON_DEV_CTRL_STOP   0x
+
 #define ACTMON_DEV_UPPER_WMARK 0x4
 #define ACTMON_DEV_LOWER_WMARK 0x8
 #define ACTMON_DEV_INIT_AVG0xc
@@ -159,7 +162,10 @@ struct tegra_devfreq {
 
struct clk  *emc_clock;
unsigned long   max_freq;
-   struct notifier_block   rate_change_nb;
+   struct notifier_block   clk_rate_change_nb;
+
+   struct delayed_work cpufreq_update_work;
+   struct notifier_block   cpu_rate_change_nb;
 
struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
 
@@ -207,10 +213,10 @@ static unsigned long do_percent(unsigned long val, 
unsigned int pct)
return val * pct / 100;
 }
 
-static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra)
+static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
+   unsigned int cpu_freq)
 {
struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios;
-   unsigned int cpu_freq = cpufreq_quick_get(0);
unsigned int i;
 
for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) {
@@ -244,7 +250,8 @@ tegra_actmon_account_cpu_freq(struct tegra_devfreq *tegra,
return target_freq;
 
if (dev->avg_freq > tegra_actmon_dev_avg_dependency_freq(tegra, dev))
-   static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra);
+   static_cpu_emc_freq = actmon_cpu_to_emc_rate(
+   tegra, cpufreq_quick_get(0));
else
static_cpu_emc_freq = 0;
 
@@ -543,8 +550,8 @@ static irqreturn_t actmon_thread_isr(int irq, void *data)
return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
-  unsigned long action, void *ptr)
+static int tegra_actmon_clk_notify_cb(struct notifier_block *nb,
+ unsigned long action, void *ptr)
 {
struct clk_notifier_data *data = ptr;
struct tegra_devfreq_device *dev;
@@ -555,7 +562,7 @@ static int tegra_actmon_rate_notify_cb(struct 
notifier_block *nb,
if (action != POST_RATE_CHANGE)
return NOTIFY_OK;
 
-   tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
+   tegra = container_of(nb, struct tegra_devfreq, clk_rate_change_nb);
 
freq = data->new_rate / KHZ;
 
@@ -586,6 +593,94 @@ static int tegra_actmon_rate_notify_cb(struct 
notifier_block *nb,
return NOTIFY_OK;
 }
 
+static void tegra_actmon_delayed_update(struct work_struct *work)
+{
+   struct tegra_devfreq *tegra = container_of(work, struct tegra_devfreq,
+  cpufreq_update_work.work);
+
+   mutex_lock(>devfreq->lock);
+   update_devfreq(tegra->devfreq);
+   mutex_unlock(>devfreq->lock);
+}
+
+static unsigned long
+tegra_actmon_cpufreq_contribution(struct tegra_devfreq *tegra,
+ unsigned int cpu_freq)
+{
+   unsigned long freq, static_cpu_emc_freq;
+
+   /* check whether CPU's freq is taken into account at all */
+   freq = tegra_actmon_dev_avg_dependency_freq(tegra,
+   >devices[MCCPU]);
+   if (tegra->devices[MCCPU].avg_freq <= freq)
+   return 0;
+
+   static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
+
+   /* compare static CPU-EMC freq with MCALL */
+   freq = tegra->devices[MCALL].avg_freq +
+  tegra->devices[MCALL].boost_freq;
+
+   freq = tegra_actmon_upper_freq(tegra, freq);
+
+   if (freq == tegra->max_freq || freq >= static_cpu_emc_freq)
+   return 0;
+
+   /* compare static CPU-EMC freq with MCCPU */
+   freq = tegra->devices[MCCPU].avg_freq +
+  tegra->devices[MCCPU].boost_freq;
+
+   freq = tegra_actmon_upper_freq(tegra, freq);
+
+   if (freq == tegra->max_freq || freq >= static_cpu_emc_freq)
+