Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'pm-devfreq'

* pm-devfreq:
PM / devfreq: add relation of recommended frequency.

+61 -11
+38 -4
drivers/devfreq/devfreq.c
··· 83 83 { 84 84 unsigned long freq; 85 85 int err = 0; 86 + u32 flags = 0; 86 87 87 88 if (!mutex_is_locked(&devfreq->lock)) { 88 89 WARN(true, "devfreq->lock must be locked by the caller.\n"); ··· 95 94 if (err) 96 95 return err; 97 96 98 - err = devfreq->profile->target(devfreq->dev.parent, &freq); 97 + /* 98 + * Adjust the freuqency with user freq and QoS. 99 + * 100 + * List from the highest proiority 101 + * max_freq (probably called by thermal when it's too hot) 102 + * min_freq 103 + */ 104 + 105 + if (devfreq->min_freq && freq < devfreq->min_freq) { 106 + freq = devfreq->min_freq; 107 + flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ 108 + } 109 + if (devfreq->max_freq && freq > devfreq->max_freq) { 110 + freq = devfreq->max_freq; 111 + flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ 112 + } 113 + 114 + err = devfreq->profile->target(devfreq->dev.parent, &freq, flags); 99 115 if (err) 100 116 return err; 101 117 ··· 643 625 * freq value given to target callback. 644 626 * @dev The devfreq user device. (parent of devfreq) 645 627 * @freq The frequency given to target function 628 + * @flags Flags handed from devfreq framework. 646 629 * 647 630 */ 648 - struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) 631 + struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, 632 + u32 flags) 649 633 { 650 - struct opp *opp = opp_find_freq_ceil(dev, freq); 634 + struct opp *opp; 651 635 652 - if (opp == ERR_PTR(-ENODEV)) 636 + if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) { 637 + /* The freq is an upper bound. opp should be lower */ 653 638 opp = opp_find_freq_floor(dev, freq); 639 + 640 + /* If not available, use the closest opp */ 641 + if (opp == ERR_PTR(-ENODEV)) 642 + opp = opp_find_freq_ceil(dev, freq); 643 + } else { 644 + /* The freq is an lower bound. opp should be higher */ 645 + opp = opp_find_freq_ceil(dev, freq); 646 + 647 + /* If not available, use the closest opp */ 648 + if (opp == ERR_PTR(-ENODEV)) 649 + opp = opp_find_freq_floor(dev, freq); 650 + } 651 + 654 652 return opp; 655 653 } 656 654
+10 -4
drivers/devfreq/exynos4_bus.c
··· 619 619 return err; 620 620 } 621 621 622 - static int exynos4_bus_target(struct device *dev, unsigned long *_freq) 622 + static int exynos4_bus_target(struct device *dev, unsigned long *_freq, 623 + u32 flags) 623 624 { 624 625 int err = 0; 625 - struct busfreq_data *data = dev_get_drvdata(dev); 626 - struct opp *opp = devfreq_recommended_opp(dev, _freq); 627 - unsigned long old_freq = opp_get_freq(data->curr_opp); 626 + struct platform_device *pdev = container_of(dev, struct platform_device, 627 + dev); 628 + struct busfreq_data *data = platform_get_drvdata(pdev); 629 + struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); 628 630 unsigned long freq = opp_get_freq(opp); 631 + unsigned long old_freq = opp_get_freq(data->curr_opp); 632 + 633 + if (IS_ERR(opp)) 634 + return PTR_ERR(opp); 629 635 630 636 if (old_freq == freq) 631 637 return 0;
+13 -3
include/linux/devfreq.h
··· 44 44 void *private_data; 45 45 }; 46 46 47 + /* 48 + * The resulting frequency should be at most this. (this bound is the 49 + * least upper bound; thus, the resulting freq should be lower or same) 50 + * If the flag is not set, the resulting frequency should be at most the 51 + * bound (greatest lower bound) 52 + */ 53 + #define DEVFREQ_FLAG_LEAST_UPPER_BOUND 0x1 54 + 47 55 /** 48 56 * struct devfreq_dev_profile - Devfreq's user device profile 49 57 * @initial_freq The operating frequency when devfreq_add_device() is ··· 62 54 * higher than any operable frequency, set maximum. 63 55 * Before returning, target function should set 64 56 * freq at the current frequency. 57 + * The "flags" parameter's possible values are 58 + * explained above with "DEVFREQ_FLAG_*" macros. 65 59 * @get_dev_status The device should provide the current performance 66 60 * status to devfreq, which is used by governors. 67 61 * @exit An optional callback that is called when devfreq ··· 76 66 unsigned long initial_freq; 77 67 unsigned int polling_ms; 78 68 79 - int (*target)(struct device *dev, unsigned long *freq); 69 + int (*target)(struct device *dev, unsigned long *freq, u32 flags); 80 70 int (*get_dev_status)(struct device *dev, 81 71 struct devfreq_dev_status *stat); 82 72 void (*exit)(struct device *dev); ··· 175 165 176 166 /* Helper functions for devfreq user device driver with OPP. */ 177 167 extern struct opp *devfreq_recommended_opp(struct device *dev, 178 - unsigned long *freq); 168 + unsigned long *freq, u32 flags); 179 169 extern int devfreq_register_opp_notifier(struct device *dev, 180 170 struct devfreq *devfreq); 181 171 extern int devfreq_unregister_opp_notifier(struct device *dev, ··· 226 216 } 227 217 228 218 static struct opp *devfreq_recommended_opp(struct device *dev, 229 - unsigned long *freq) 219 + unsigned long *freq, u32 flags) 230 220 { 231 221 return -EINVAL; 232 222 }