Re: [PATCH v6 11/19] PM / devfreq: tegra30: Use CPUFreq notifier
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
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
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) +