Message ID | 1305100723-29161-2-git-send-email-myungjoo.ham@samsung.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
On Wednesday, May 11, 2011, MyungJoo Ham wrote: > Three CPUFREQ-like governors are provided as examples. > > powersave: use the lowest frequency possible. The user (device) should > set the polling_ms as 0 because polling is useless for this governor. > > performance: use the highest freqeuncy possible. The user (device) > should set the polling_ms as 0 because polling is useless for this > governor. > > simple_ondemand: simplified version of CPUFREQ's ONDEMAND governor. > > When a user updates OPP entries (enable/disable/add), OPP framework > automatically notifies DEVFREQ to update operating frequency > accordingly. Thus, DEVFREQ users (device drivers) do not need to update > DEVFREQ manually with OPP entry updates or set polling_ms for powersave > , performance, or any other "static" governors. Well, do you expect anyone to actually use them? If not, it would make more sense to put them into a doc. Thanks, Rafael > Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> > --- > drivers/base/power/devfreq.c | 69 ++++++++++++++++++++++++++++++++++++++++++ > include/linux/devfreq.h | 5 +++ > 2 files changed, 74 insertions(+), 0 deletions(-) > > diff --git a/drivers/base/power/devfreq.c b/drivers/base/power/devfreq.c > index 8e2e45b..251d761 100644 > --- a/drivers/base/power/devfreq.c > +++ b/drivers/base/power/devfreq.c > @@ -351,3 +351,72 @@ static int __init devfreq_init(void) > return 0; > } > late_initcall(devfreq_init); > + > +static int devfreq_powersave_func(struct devfreq *df, > + unsigned long *freq) > +{ > + *freq = 0; /* devfreq_do will run "ceiling" to 0 */ > + return 0; > +} > + > +struct devfreq_governor devfreq_powersave = { > + .get_target_freq = devfreq_powersave_func, > +}; > + > +static int devfreq_performance_func(struct devfreq *df, > + unsigned long *freq) > +{ > + *freq = UINT_MAX; /* devfreq_do will run "floor" */ > + return 0; > +} > + > +struct devfreq_governor devfreq_performance = { > + .get_target_freq = devfreq_performance_func, > +}; > + > +/* Constants for DevFreq-Simple-Ondemand (DFSO) */ > +#define DFSO_UPTHRESHOLD (90) > +#define DFSO_DOWNDIFFERENCTIAL (5) > +static int devfreq_simple_ondemand_func(struct devfreq *df, > + unsigned long *freq) > +{ > + struct devfreq_dev_status stat; > + int err = df->profile->get_dev_status(df->dev, &stat); > + unsigned long long a, b; > + > + if (err) > + return err; > + > + /* Set MAX if it's busy enough */ > + if (stat.busy_time * 100 > > + stat.total_time * DFSO_UPTHRESHOLD) { > + *freq = UINT_MAX; > + return 0; > + } > + > + /* Set MAX if we do not know the initial frequency */ > + if (stat.current_frequency == 0) { > + *freq = UINT_MAX; > + return 0; > + } > + > + /* Keep the current frequency */ > + if (stat.busy_time * 100 > > + stat.total_time * (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL)) { > + *freq = stat.current_frequency; > + return 0; > + } > + > + /* Set the desired frequency based on the load */ > + a = (unsigned long long) stat.busy_time * stat.current_frequency; > + b = div_u64(a, stat.total_time); > + b *= 100; > + b = div_u64(b, (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL / 2)); > + *freq = (unsigned long) b; > + > + return 0; > +} > + > +struct devfreq_governor devfreq_simple_ondemand = { > + .get_target_freq = devfreq_simple_ondemand_func, > +}; > diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h > index d08e9f5..ec41ba6 100644 > --- a/include/linux/devfreq.h > +++ b/include/linux/devfreq.h > @@ -81,6 +81,11 @@ extern int devfreq_add_device(struct device *dev, > extern int devfreq_remove_device(struct device *dev); > extern int devfreq_update(struct device *dev, bool may_not_exist); > extern int devfreq_tickle_device(struct device *dev, unsigned long duration_ms); > + > +extern struct devfreq_governor devfreq_powersave; > +extern struct devfreq_governor devfreq_performance; > +extern struct devfreq_governor devfreq_simple_ondemand; > + > #else /* !CONFIG_PM_DEVFREQ */ > static int devfreq_add_device(struct device *dev, > struct devfreq_dev_profile *profile, >
2011/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > On Wednesday, May 11, 2011, MyungJoo Ham wrote: >> Three CPUFREQ-like governors are provided as examples. >> >> powersave: use the lowest frequency possible. The user (device) should >> set the polling_ms as 0 because polling is useless for this governor. >> >> performance: use the highest freqeuncy possible. The user (device) >> should set the polling_ms as 0 because polling is useless for this >> governor. >> >> simple_ondemand: simplified version of CPUFREQ's ONDEMAND governor. >> >> When a user updates OPP entries (enable/disable/add), OPP framework >> automatically notifies DEVFREQ to update operating frequency >> accordingly. Thus, DEVFREQ users (device drivers) do not need to update >> DEVFREQ manually with OPP entry updates or set polling_ms for powersave >> , performance, or any other "static" governors. > > Well, do you expect anyone to actually use them? If not, it would make > more sense to put them into a doc. According to our experiences of DVFS(although this "DEVFREQ" is not applied to them, yet) in memory-bus and GPU, I expect most DEVFREQ users might use "simple_ondemand" and expect "powersave" and "performance" will probably mostly used while testing and debugging. ("userspace"-like governor would be also useful for that purpose, but I'd add it later) Cheers! - MyungJoo > > Thanks, > Rafael > > >> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> >> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> >> --- >> drivers/base/power/devfreq.c | 69 ++++++++++++++++++++++++++++++++++++++++++ >> include/linux/devfreq.h | 5 +++ >> 2 files changed, 74 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/base/power/devfreq.c b/drivers/base/power/devfreq.c >> index 8e2e45b..251d761 100644 >> --- a/drivers/base/power/devfreq.c >> +++ b/drivers/base/power/devfreq.c >> @@ -351,3 +351,72 @@ static int __init devfreq_init(void) >> return 0; >> } >> late_initcall(devfreq_init); >> + >> +static int devfreq_powersave_func(struct devfreq *df, >> + unsigned long *freq) >> +{ >> + *freq = 0; /* devfreq_do will run "ceiling" to 0 */ >> + return 0; >> +} >> + >> +struct devfreq_governor devfreq_powersave = { >> + .get_target_freq = devfreq_powersave_func, >> +}; >> + >> +static int devfreq_performance_func(struct devfreq *df, >> + unsigned long *freq) >> +{ >> + *freq = UINT_MAX; /* devfreq_do will run "floor" */ >> + return 0; >> +} >> + >> +struct devfreq_governor devfreq_performance = { >> + .get_target_freq = devfreq_performance_func, >> +}; >> + >> +/* Constants for DevFreq-Simple-Ondemand (DFSO) */ >> +#define DFSO_UPTHRESHOLD (90) >> +#define DFSO_DOWNDIFFERENCTIAL (5) >> +static int devfreq_simple_ondemand_func(struct devfreq *df, >> + unsigned long *freq) >> +{ >> + struct devfreq_dev_status stat; >> + int err = df->profile->get_dev_status(df->dev, &stat); >> + unsigned long long a, b; >> + >> + if (err) >> + return err; >> + >> + /* Set MAX if it's busy enough */ >> + if (stat.busy_time * 100 > >> + stat.total_time * DFSO_UPTHRESHOLD) { >> + *freq = UINT_MAX; >> + return 0; >> + } >> + >> + /* Set MAX if we do not know the initial frequency */ >> + if (stat.current_frequency == 0) { >> + *freq = UINT_MAX; >> + return 0; >> + } >> + >> + /* Keep the current frequency */ >> + if (stat.busy_time * 100 > >> + stat.total_time * (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL)) { >> + *freq = stat.current_frequency; >> + return 0; >> + } >> + >> + /* Set the desired frequency based on the load */ >> + a = (unsigned long long) stat.busy_time * stat.current_frequency; >> + b = div_u64(a, stat.total_time); >> + b *= 100; >> + b = div_u64(b, (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL / 2)); >> + *freq = (unsigned long) b; >> + >> + return 0; >> +} >> + >> +struct devfreq_governor devfreq_simple_ondemand = { >> + .get_target_freq = devfreq_simple_ondemand_func, >> +}; >> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h >> index d08e9f5..ec41ba6 100644 >> --- a/include/linux/devfreq.h >> +++ b/include/linux/devfreq.h >> @@ -81,6 +81,11 @@ extern int devfreq_add_device(struct device *dev, >> extern int devfreq_remove_device(struct device *dev); >> extern int devfreq_update(struct device *dev, bool may_not_exist); >> extern int devfreq_tickle_device(struct device *dev, unsigned long duration_ms); >> + >> +extern struct devfreq_governor devfreq_powersave; >> +extern struct devfreq_governor devfreq_performance; >> +extern struct devfreq_governor devfreq_simple_ondemand; >> + >> #else /* !CONFIG_PM_DEVFREQ */ >> static int devfreq_add_device(struct device *dev, >> struct devfreq_dev_profile *profile, >> > >
On Wednesday, May 18, 2011, MyungJoo Ham wrote: > 2011/5/18 Rafael J. Wysocki <rjw@sisk.pl>: > > On Wednesday, May 11, 2011, MyungJoo Ham wrote: > >> Three CPUFREQ-like governors are provided as examples. > >> > >> powersave: use the lowest frequency possible. The user (device) should > >> set the polling_ms as 0 because polling is useless for this governor. > >> > >> performance: use the highest freqeuncy possible. The user (device) > >> should set the polling_ms as 0 because polling is useless for this > >> governor. > >> > >> simple_ondemand: simplified version of CPUFREQ's ONDEMAND governor. > >> > >> When a user updates OPP entries (enable/disable/add), OPP framework > >> automatically notifies DEVFREQ to update operating frequency > >> accordingly. Thus, DEVFREQ users (device drivers) do not need to update > >> DEVFREQ manually with OPP entry updates or set polling_ms for powersave > >> , performance, or any other "static" governors. > > > > Well, do you expect anyone to actually use them? If not, it would make > > more sense to put them into a doc. > > According to our experiences of DVFS(although this "DEVFREQ" is not > applied to them, yet) in memory-bus and GPU, > I expect most DEVFREQ users might use "simple_ondemand" and > expect "powersave" and "performance" will probably mostly used while > testing and debugging. > ("userspace"-like governor would be also useful for that purpose, but > I'd add it later) It would be good to have at least one in-tree user for each of them (not necessarily from the start, but at one point in the future at least). So if you have any _specific_ users in mind, please let me know. Thanks, Rafael
On Thu, May 19, 2011 at 4:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote: > On Wednesday, May 18, 2011, MyungJoo Ham wrote: >> 2011/5/18 Rafael J. Wysocki <rjw@sisk.pl>: >> > On Wednesday, May 11, 2011, MyungJoo Ham wrote: >> >> Three CPUFREQ-like governors are provided as examples. >> >> >> >> powersave: use the lowest frequency possible. The user (device) should >> >> set the polling_ms as 0 because polling is useless for this governor. >> >> >> >> performance: use the highest freqeuncy possible. The user (device) >> >> should set the polling_ms as 0 because polling is useless for this >> >> governor. >> >> >> >> simple_ondemand: simplified version of CPUFREQ's ONDEMAND governor. >> >> >> >> When a user updates OPP entries (enable/disable/add), OPP framework >> >> automatically notifies DEVFREQ to update operating frequency >> >> accordingly. Thus, DEVFREQ users (device drivers) do not need to update >> >> DEVFREQ manually with OPP entry updates or set polling_ms for powersave >> >> , performance, or any other "static" governors. >> > >> > Well, do you expect anyone to actually use them? If not, it would make >> > more sense to put them into a doc. >> >> According to our experiences of DVFS(although this "DEVFREQ" is not >> applied to them, yet) in memory-bus and GPU, >> I expect most DEVFREQ users might use "simple_ondemand" and >> expect "powersave" and "performance" will probably mostly used while >> testing and debugging. >> ("userspace"-like governor would be also useful for that purpose, but >> I'd add it later) > > It would be good to have at least one in-tree user for each of them > (not necessarily from the start, but at one point in the future at least). > > So if you have any _specific_ users in mind, please let me know. For Exynos4, the DRAM bus, which is included in cpufreq and altered along with CPU, but would be better to alter independently, and the G3D core (MALI) are the candidate. In our kernel hacks, the DRAM bus frequency varies independently from CPU with DRAM usage monitoring and I think it can be easily modified to use DEVFREQ; thus, I'm going to "translate" this to DEVFREQ next time. For MALI, I don't know whether there is non-copyrighted driver or now, but they do support DVFS and are using DVFS with some PITA driver support. These two (EXYNOS4 DRAM bus and MALI) are the specific users in mind for now. Probably, out-of-SoC devices such as WiFi, BT, and others may be the candidate as well. > > Thanks, > Rafael >
diff --git a/drivers/base/power/devfreq.c b/drivers/base/power/devfreq.c index 8e2e45b..251d761 100644 --- a/drivers/base/power/devfreq.c +++ b/drivers/base/power/devfreq.c @@ -351,3 +351,72 @@ static int __init devfreq_init(void) return 0; } late_initcall(devfreq_init); + +static int devfreq_powersave_func(struct devfreq *df, + unsigned long *freq) +{ + *freq = 0; /* devfreq_do will run "ceiling" to 0 */ + return 0; +} + +struct devfreq_governor devfreq_powersave = { + .get_target_freq = devfreq_powersave_func, +}; + +static int devfreq_performance_func(struct devfreq *df, + unsigned long *freq) +{ + *freq = UINT_MAX; /* devfreq_do will run "floor" */ + return 0; +} + +struct devfreq_governor devfreq_performance = { + .get_target_freq = devfreq_performance_func, +}; + +/* Constants for DevFreq-Simple-Ondemand (DFSO) */ +#define DFSO_UPTHRESHOLD (90) +#define DFSO_DOWNDIFFERENCTIAL (5) +static int devfreq_simple_ondemand_func(struct devfreq *df, + unsigned long *freq) +{ + struct devfreq_dev_status stat; + int err = df->profile->get_dev_status(df->dev, &stat); + unsigned long long a, b; + + if (err) + return err; + + /* Set MAX if it's busy enough */ + if (stat.busy_time * 100 > + stat.total_time * DFSO_UPTHRESHOLD) { + *freq = UINT_MAX; + return 0; + } + + /* Set MAX if we do not know the initial frequency */ + if (stat.current_frequency == 0) { + *freq = UINT_MAX; + return 0; + } + + /* Keep the current frequency */ + if (stat.busy_time * 100 > + stat.total_time * (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL)) { + *freq = stat.current_frequency; + return 0; + } + + /* Set the desired frequency based on the load */ + a = (unsigned long long) stat.busy_time * stat.current_frequency; + b = div_u64(a, stat.total_time); + b *= 100; + b = div_u64(b, (DFSO_UPTHRESHOLD - DFSO_DOWNDIFFERENCTIAL / 2)); + *freq = (unsigned long) b; + + return 0; +} + +struct devfreq_governor devfreq_simple_ondemand = { + .get_target_freq = devfreq_simple_ondemand_func, +}; diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index d08e9f5..ec41ba6 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -81,6 +81,11 @@ extern int devfreq_add_device(struct device *dev, extern int devfreq_remove_device(struct device *dev); extern int devfreq_update(struct device *dev, bool may_not_exist); extern int devfreq_tickle_device(struct device *dev, unsigned long duration_ms); + +extern struct devfreq_governor devfreq_powersave; +extern struct devfreq_governor devfreq_performance; +extern struct devfreq_governor devfreq_simple_ondemand; + #else /* !CONFIG_PM_DEVFREQ */ static int devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile,