Loading drivers/devfreq/devfreq.c +38 −4 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,7 @@ int update_devfreq(struct devfreq *devfreq) { { unsigned long freq; unsigned long freq; int err = 0; int err = 0; u32 flags = 0; if (!mutex_is_locked(&devfreq->lock)) { if (!mutex_is_locked(&devfreq->lock)) { WARN(true, "devfreq->lock must be locked by the caller.\n"); WARN(true, "devfreq->lock must be locked by the caller.\n"); Loading @@ -94,7 +95,24 @@ int update_devfreq(struct devfreq *devfreq) if (err) if (err) return err; return err; err = devfreq->profile->target(devfreq->dev.parent, &freq); /* * Adjust the freuqency with user freq and QoS. * * List from the highest proiority * max_freq (probably called by thermal when it's too hot) * min_freq */ if (devfreq->min_freq && freq < devfreq->min_freq) { freq = devfreq->min_freq; flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ } if (devfreq->max_freq && freq > devfreq->max_freq) { freq = devfreq->max_freq; flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ } err = devfreq->profile->target(devfreq->dev.parent, &freq, flags); if (err) if (err) return err; return err; Loading Loading @@ -625,14 +643,30 @@ module_exit(devfreq_exit); * freq value given to target callback. * freq value given to target callback. * @dev The devfreq user device. (parent of devfreq) * @dev The devfreq user device. (parent of devfreq) * @freq The frequency given to target function * @freq The frequency given to target function * @flags Flags handed from devfreq framework. * * */ */ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) { { struct opp *opp = opp_find_freq_ceil(dev, freq); struct opp *opp; if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { /* The freq is an upper bound. opp should be lower */ opp = opp_find_freq_floor(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ENODEV)) opp = opp_find_freq_ceil(dev, freq); } else { /* The freq is an lower bound. opp should be higher */ opp = opp_find_freq_ceil(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ENODEV)) if (opp == ERR_PTR(-ENODEV)) opp = opp_find_freq_floor(dev, freq); opp = opp_find_freq_floor(dev, freq); } return opp; return opp; } } Loading drivers/devfreq/exynos4_bus.c +10 −4 Original line number Original line Diff line number Diff line Loading @@ -619,13 +619,19 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, return err; 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 flags) { { int err = 0; int err = 0; struct busfreq_data *data = dev_get_drvdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, struct opp *opp = devfreq_recommended_opp(dev, _freq); dev); unsigned long old_freq = opp_get_freq(data->curr_opp); struct busfreq_data *data = platform_get_drvdata(pdev); struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); unsigned long freq = opp_get_freq(opp); 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) if (old_freq == freq) return 0; return 0; Loading include/linux/devfreq.h +13 −3 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,14 @@ struct devfreq_dev_status { void *private_data; void *private_data; }; }; /* * The resulting frequency should be at most this. (this bound is the * least upper bound; thus, the resulting freq should be lower or same) * If the flag is not set, the resulting frequency should be at most the * bound (greatest lower bound) */ #define DEVFREQ_FLAG_LEAST_UPPER_BOUND 0x1 /** /** * struct devfreq_dev_profile - Devfreq's user device profile * struct devfreq_dev_profile - Devfreq's user device profile * @initial_freq The operating frequency when devfreq_add_device() is * @initial_freq The operating frequency when devfreq_add_device() is Loading @@ -54,6 +62,8 @@ struct devfreq_dev_status { * higher than any operable frequency, set maximum. * higher than any operable frequency, set maximum. * Before returning, target function should set * Before returning, target function should set * freq at the current frequency. * freq at the current frequency. * The "flags" parameter's possible values are * explained above with "DEVFREQ_FLAG_*" macros. * @get_dev_status The device should provide the current performance * @get_dev_status The device should provide the current performance * status to devfreq, which is used by governors. * status to devfreq, which is used by governors. * @exit An optional callback that is called when devfreq * @exit An optional callback that is called when devfreq Loading @@ -66,7 +76,7 @@ struct devfreq_dev_profile { unsigned long initial_freq; unsigned long initial_freq; unsigned int polling_ms; unsigned int polling_ms; int (*target)(struct device *dev, unsigned long *freq); int (*target)(struct device *dev, unsigned long *freq, u32 flags); int (*get_dev_status)(struct device *dev, int (*get_dev_status)(struct device *dev, struct devfreq_dev_status *stat); struct devfreq_dev_status *stat); void (*exit)(struct device *dev); void (*exit)(struct device *dev); Loading Loading @@ -165,7 +175,7 @@ extern int devfreq_remove_device(struct devfreq *devfreq); /* Helper functions for devfreq user device driver with OPP. */ /* Helper functions for devfreq user device driver with OPP. */ extern struct opp *devfreq_recommended_opp(struct device *dev, extern struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq); unsigned long *freq, u32 flags); extern int devfreq_register_opp_notifier(struct device *dev, extern int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq); struct devfreq *devfreq); extern int devfreq_unregister_opp_notifier(struct device *dev, extern int devfreq_unregister_opp_notifier(struct device *dev, Loading Loading @@ -216,7 +226,7 @@ static int devfreq_remove_device(struct devfreq *devfreq) } } static struct opp *devfreq_recommended_opp(struct device *dev, static struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) unsigned long *freq, u32 flags) { { return -EINVAL; return -EINVAL; } } Loading Loading
drivers/devfreq/devfreq.c +38 −4 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,7 @@ int update_devfreq(struct devfreq *devfreq) { { unsigned long freq; unsigned long freq; int err = 0; int err = 0; u32 flags = 0; if (!mutex_is_locked(&devfreq->lock)) { if (!mutex_is_locked(&devfreq->lock)) { WARN(true, "devfreq->lock must be locked by the caller.\n"); WARN(true, "devfreq->lock must be locked by the caller.\n"); Loading @@ -94,7 +95,24 @@ int update_devfreq(struct devfreq *devfreq) if (err) if (err) return err; return err; err = devfreq->profile->target(devfreq->dev.parent, &freq); /* * Adjust the freuqency with user freq and QoS. * * List from the highest proiority * max_freq (probably called by thermal when it's too hot) * min_freq */ if (devfreq->min_freq && freq < devfreq->min_freq) { freq = devfreq->min_freq; flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ } if (devfreq->max_freq && freq > devfreq->max_freq) { freq = devfreq->max_freq; flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ } err = devfreq->profile->target(devfreq->dev.parent, &freq, flags); if (err) if (err) return err; return err; Loading Loading @@ -625,14 +643,30 @@ module_exit(devfreq_exit); * freq value given to target callback. * freq value given to target callback. * @dev The devfreq user device. (parent of devfreq) * @dev The devfreq user device. (parent of devfreq) * @freq The frequency given to target function * @freq The frequency given to target function * @flags Flags handed from devfreq framework. * * */ */ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) { { struct opp *opp = opp_find_freq_ceil(dev, freq); struct opp *opp; if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { /* The freq is an upper bound. opp should be lower */ opp = opp_find_freq_floor(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ENODEV)) opp = opp_find_freq_ceil(dev, freq); } else { /* The freq is an lower bound. opp should be higher */ opp = opp_find_freq_ceil(dev, freq); /* If not available, use the closest opp */ if (opp == ERR_PTR(-ENODEV)) if (opp == ERR_PTR(-ENODEV)) opp = opp_find_freq_floor(dev, freq); opp = opp_find_freq_floor(dev, freq); } return opp; return opp; } } Loading
drivers/devfreq/exynos4_bus.c +10 −4 Original line number Original line Diff line number Diff line Loading @@ -619,13 +619,19 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, return err; 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 flags) { { int err = 0; int err = 0; struct busfreq_data *data = dev_get_drvdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, struct opp *opp = devfreq_recommended_opp(dev, _freq); dev); unsigned long old_freq = opp_get_freq(data->curr_opp); struct busfreq_data *data = platform_get_drvdata(pdev); struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); unsigned long freq = opp_get_freq(opp); 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) if (old_freq == freq) return 0; return 0; Loading
include/linux/devfreq.h +13 −3 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,14 @@ struct devfreq_dev_status { void *private_data; void *private_data; }; }; /* * The resulting frequency should be at most this. (this bound is the * least upper bound; thus, the resulting freq should be lower or same) * If the flag is not set, the resulting frequency should be at most the * bound (greatest lower bound) */ #define DEVFREQ_FLAG_LEAST_UPPER_BOUND 0x1 /** /** * struct devfreq_dev_profile - Devfreq's user device profile * struct devfreq_dev_profile - Devfreq's user device profile * @initial_freq The operating frequency when devfreq_add_device() is * @initial_freq The operating frequency when devfreq_add_device() is Loading @@ -54,6 +62,8 @@ struct devfreq_dev_status { * higher than any operable frequency, set maximum. * higher than any operable frequency, set maximum. * Before returning, target function should set * Before returning, target function should set * freq at the current frequency. * freq at the current frequency. * The "flags" parameter's possible values are * explained above with "DEVFREQ_FLAG_*" macros. * @get_dev_status The device should provide the current performance * @get_dev_status The device should provide the current performance * status to devfreq, which is used by governors. * status to devfreq, which is used by governors. * @exit An optional callback that is called when devfreq * @exit An optional callback that is called when devfreq Loading @@ -66,7 +76,7 @@ struct devfreq_dev_profile { unsigned long initial_freq; unsigned long initial_freq; unsigned int polling_ms; unsigned int polling_ms; int (*target)(struct device *dev, unsigned long *freq); int (*target)(struct device *dev, unsigned long *freq, u32 flags); int (*get_dev_status)(struct device *dev, int (*get_dev_status)(struct device *dev, struct devfreq_dev_status *stat); struct devfreq_dev_status *stat); void (*exit)(struct device *dev); void (*exit)(struct device *dev); Loading Loading @@ -165,7 +175,7 @@ extern int devfreq_remove_device(struct devfreq *devfreq); /* Helper functions for devfreq user device driver with OPP. */ /* Helper functions for devfreq user device driver with OPP. */ extern struct opp *devfreq_recommended_opp(struct device *dev, extern struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq); unsigned long *freq, u32 flags); extern int devfreq_register_opp_notifier(struct device *dev, extern int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq); struct devfreq *devfreq); extern int devfreq_unregister_opp_notifier(struct device *dev, extern int devfreq_unregister_opp_notifier(struct device *dev, Loading Loading @@ -216,7 +226,7 @@ static int devfreq_remove_device(struct devfreq *devfreq) } } static struct opp *devfreq_recommended_opp(struct device *dev, static struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) unsigned long *freq, u32 flags) { { return -EINVAL; return -EINVAL; } } Loading