Messages in this thread | | | Date | Fri, 9 Mar 2012 16:09:58 +0900 | Subject | Re: [PATCH] PM / devfreq: add relation of recommended frequency. | From | MyungJoo Ham <> |
| |
On Thu, Mar 8, 2012 at 2:45 AM, Turquette, Mike <mturquette@ti.com> wrote: > On Thu, Feb 9, 2012 at 11:19 PM, MyungJoo Ham <myungjoo.ham@samsung.com> wrote: >> The semantics of "target frequency" given to devfreq driver from >> devfreq framework has always been interpretted as "at least" or GLB >> (greatest lower bound). However, the framework might want the >> device driver to limit its max frequency (LUB: least upper bound), >> especially if it is given by thermal framework (it's too hot). >> >> Thus, the target fuction should have another parameter to express >> whether the framework wants GLB or LUB. And, the additional parameter, >> "u32 options", does it. > > Nitpick: changelog still refers to "options" but code reads "flags". > > Regards, > Mike >
Thanks. That is updated in the git.infradead.org repository to be requested to pull. http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/devfreq-for-next
As soon as infradead server gets synched, you can see the commit message updated.
Cheers! MyungJoo.
>> >> With the update, devfreq_recommended_opp() is also updated. >> >> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> >> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> >> --- >> drivers/devfreq/devfreq.c | 44 ++++++++++++++++++++++++++++++---------- >> drivers/devfreq/exynos4_bus.c | 16 +++++++++++--- >> include/linux/devfreq.h | 18 ++++++++++++++-- >> 3 files changed, 60 insertions(+), 18 deletions(-) >> >> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c >> index a33fc6c..83392a6 100644 >> --- a/drivers/devfreq/devfreq.c >> +++ b/drivers/devfreq/devfreq.c >> @@ -84,6 +84,7 @@ int update_devfreq(struct devfreq *devfreq) >> { >> unsigned long freq; >> int err = 0; >> + u32 options = 0; >> >> if (!mutex_is_locked(&devfreq->lock)) { >> WARN(true, "devfreq->lock must be locked by the caller.\n"); >> @@ -104,18 +105,23 @@ int update_devfreq(struct devfreq *devfreq) >> * qos_min_freq >> */ >> >> - if (devfreq->qos_min_freq && freq < devfreq->qos_min_freq) >> + if (devfreq->qos_min_freq && freq < devfreq->qos_min_freq) { >> freq = devfreq->qos_min_freq; >> - if (devfreq->max_freq && freq > devfreq->max_freq) >> + options &= ~(1 << 0); >> + options |= DEVFREQ_OPTION_FREQ_LUB; >> + } >> + if (devfreq->max_freq && freq > devfreq->max_freq) { >> freq = devfreq->max_freq; >> - if (devfreq->min_freq && freq < devfreq->min_freq) >> + options &= ~(1 << 0); >> + options |= DEVFREQ_OPTION_FREQ_GLB; >> + } >> + if (devfreq->min_freq && freq < devfreq->min_freq) { >> freq = devfreq->min_freq; >> + options &= ~(1 << 0); >> + options |= DEVFREQ_OPTION_FREQ_LUB; >> + } >> >> - /* >> - * TODO in the devfreq-next: >> - * add relation or use rance (freq_min, freq_max) >> - */ >> - err = devfreq->profile->target(devfreq->dev.parent, &freq); >> + err = devfreq->profile->target(devfreq->dev.parent, &freq, options); >> if (err) >> return err; >> >> @@ -771,14 +777,30 @@ module_exit(devfreq_exit); >> * freq value given to target callback. >> * @dev The devfreq user device. (parent of devfreq) >> * @freq The frequency given to target function >> + * @floor false: find LUB first and use GLB if LUB not available. >> + * true: find GLB first and use LUB if GLB not available. >> + * >> + * LUB: least upper bound (at least this freq or above, but the least) >> + * GLB: greatest lower bound (at most this freq or below, but the most) >> * >> */ >> -struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) >> +struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, >> + bool floor) >> { >> - struct opp *opp = opp_find_freq_ceil(dev, freq); >> + struct opp *opp; >> >> - if (opp == ERR_PTR(-ENODEV)) >> + if (floor) { >> opp = opp_find_freq_floor(dev, freq); >> + >> + if (opp == ERR_PTR(-ENODEV)) >> + opp = opp_find_freq_ceil(dev, freq); >> + } else { >> + opp = opp_find_freq_ceil(dev, freq); >> + >> + if (opp == ERR_PTR(-ENODEV)) >> + opp = opp_find_freq_floor(dev, freq); >> + } >> + >> return opp; >> } >> >> diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c >> index 590d686..c0a78da 100644 >> --- a/drivers/devfreq/exynos4_bus.c >> +++ b/drivers/devfreq/exynos4_bus.c >> @@ -619,13 +619,21 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, >> return err; >> } >> >> -static int exynos4_bus_target(struct device *dev, unsigned long *_freq) >> +static int exynos4_bus_target(struct device *dev, unsigned long *_freq, >> + u32 options) >> { >> int err = 0; >> - struct busfreq_data *data = dev_get_drvdata(dev); >> - struct opp *opp = devfreq_recommended_opp(dev, _freq); >> - unsigned long old_freq = opp_get_freq(data->curr_opp); >> + unsigned long def = *_freq; >> + struct platform_device *pdev = container_of(dev, struct platform_device, >> + dev); >> + struct busfreq_data *data = platform_get_drvdata(pdev); >> + struct opp *opp = devfreq_recommended_opp(dev, _freq, options & >> + DEVFREQ_OPTION_FREQ_GLB); >> unsigned long freq = opp_get_freq(opp); >> + unsigned long old_freq = opp_get_freq(data->curr_opp); >> + >> + if (IS_ERR(opp)) >> + return PTR_ERR(opp); >> >> if (old_freq == freq) >> return 0; >> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h >> index b853379..1aff012 100644 >> --- a/include/linux/devfreq.h >> +++ b/include/linux/devfreq.h >> @@ -59,6 +59,16 @@ struct devfreq_pm_qos_table { >> s32 qos_value; >> }; >> >> +/* >> + * target callback, which is to provide additional information to the >> + * devfreq driver. >> + */ >> + >> +/* The resulting frequency should be at least this. (least upper bound) */ >> +#define DEVFREQ_OPTION_FREQ_LUB 0x0 >> +/* The resulting frequency should be at most this. (greatest lower bound) */ >> +#define DEVFREQ_OPTION_FREQ_GLB 0x1 >> + >> /** >> * struct devfreq_dev_profile - Devfreq's user device profile >> * @initial_freq The operating frequency when devfreq_add_device() is >> @@ -76,6 +86,8 @@ struct devfreq_pm_qos_table { >> * higher than any operable frequency, set maximum. >> * Before returning, target function should set >> * freq at the current frequency. >> + * The "option" parameter's possible values are >> + * explained above with "DEVFREQ_OPTION_*" macros. >> * @get_dev_status The device should provide the current performance >> * status to devfreq, which is used by governors. >> * @exit An optional callback that is called when devfreq >> @@ -95,7 +107,7 @@ struct devfreq_dev_profile { >> bool qos_use_max; >> struct devfreq_pm_qos_table *qos_list; >> >> - int (*target)(struct device *dev, unsigned long *freq); >> + int (*target)(struct device *dev, unsigned long *freq, u32 options); >> int (*get_dev_status)(struct device *dev, >> struct devfreq_dev_status *stat); >> void (*exit)(struct device *dev); >> @@ -198,7 +210,7 @@ extern int devfreq_remove_device(struct devfreq *devfreq); >> >> /* Helper functions for devfreq user device driver with OPP. */ >> extern struct opp *devfreq_recommended_opp(struct device *dev, >> - unsigned long *freq); >> + unsigned long *freq, bool floor); >> extern int devfreq_register_opp_notifier(struct device *dev, >> struct devfreq *devfreq); >> extern int devfreq_unregister_opp_notifier(struct device *dev, >> @@ -253,7 +265,7 @@ static int devfreq_remove_device(struct devfreq *devfreq) >> } >> >> static struct opp *devfreq_recommended_opp(struct device *dev, >> - unsigned long *freq) >> + unsigned long *freq, bool floor) >> { >> return -EINVAL; >> } >> -- >> 1.7.4.1 >>
-- MyungJoo Ham, Ph.D. Mobile Software Platform Lab, DMC Business, Samsung Electronics -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |