aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavi Merino <javi.merino@arm.com>2015-08-14 13:56:56 -0400
committerMyungJoo Ham <myungjoo.ham@samsung.com>2015-09-11 01:23:28 -0400
commit08e75e754a6d9838e490b74551d19fc04d0fd6f9 (patch)
tree71344662250f9bd22389a86e886a1aa6b67c7fed
parent9348da2f1c2ca8e064d4907cdc5b3a19477df933 (diff)
PM / devfreq: cache the last call to get_dev_status()
The return value of get_dev_status() can be reused. Cache it so that other parts of the kernel can reuse it instead of having to call the same function again. Cc: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Javi Merino <javi.merino@arm.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
-rw-r--r--drivers/devfreq/governor_simpleondemand.c33
-rw-r--r--include/linux/devfreq.h15
2 files changed, 33 insertions, 15 deletions
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index 0720ba84ca92..ae72ba5e78df 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -21,17 +21,20 @@
21static int devfreq_simple_ondemand_func(struct devfreq *df, 21static int devfreq_simple_ondemand_func(struct devfreq *df,
22 unsigned long *freq) 22 unsigned long *freq)
23{ 23{
24 struct devfreq_dev_status stat; 24 int err;
25 int err = df->profile->get_dev_status(df->dev.parent, &stat); 25 struct devfreq_dev_status *stat;
26 unsigned long long a, b; 26 unsigned long long a, b;
27 unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD; 27 unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
28 unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL; 28 unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
29 struct devfreq_simple_ondemand_data *data = df->data; 29 struct devfreq_simple_ondemand_data *data = df->data;
30 unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX; 30 unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
31 31
32 err = devfreq_update_stats(df);
32 if (err) 33 if (err)
33 return err; 34 return err;
34 35
36 stat = &df->last_status;
37
35 if (data) { 38 if (data) {
36 if (data->upthreshold) 39 if (data->upthreshold)
37 dfso_upthreshold = data->upthreshold; 40 dfso_upthreshold = data->upthreshold;
@@ -43,41 +46,41 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
43 return -EINVAL; 46 return -EINVAL;
44 47
45 /* Assume MAX if it is going to be divided by zero */ 48 /* Assume MAX if it is going to be divided by zero */
46 if (stat.total_time == 0) { 49 if (stat->total_time == 0) {
47 *freq = max; 50 *freq = max;
48 return 0; 51 return 0;
49 } 52 }
50 53
51 /* Prevent overflow */ 54 /* Prevent overflow */
52 if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) { 55 if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
53 stat.busy_time >>= 7; 56 stat->busy_time >>= 7;
54 stat.total_time >>= 7; 57 stat->total_time >>= 7;
55 } 58 }
56 59
57 /* Set MAX if it's busy enough */ 60 /* Set MAX if it's busy enough */
58 if (stat.busy_time * 100 > 61 if (stat->busy_time * 100 >
59 stat.total_time * dfso_upthreshold) { 62 stat->total_time * dfso_upthreshold) {
60 *freq = max; 63 *freq = max;
61 return 0; 64 return 0;
62 } 65 }
63 66
64 /* Set MAX if we do not know the initial frequency */ 67 /* Set MAX if we do not know the initial frequency */
65 if (stat.current_frequency == 0) { 68 if (stat->current_frequency == 0) {
66 *freq = max; 69 *freq = max;
67 return 0; 70 return 0;
68 } 71 }
69 72
70 /* Keep the current frequency */ 73 /* Keep the current frequency */
71 if (stat.busy_time * 100 > 74 if (stat->busy_time * 100 >
72 stat.total_time * (dfso_upthreshold - dfso_downdifferential)) { 75 stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
73 *freq = stat.current_frequency; 76 *freq = stat->current_frequency;
74 return 0; 77 return 0;
75 } 78 }
76 79
77 /* Set the desired frequency based on the load */ 80 /* Set the desired frequency based on the load */
78 a = stat.busy_time; 81 a = stat->busy_time;
79 a *= stat.current_frequency; 82 a *= stat->current_frequency;
80 b = div_u64(a, stat.total_time); 83 b = div_u64(a, stat->total_time);
81 b *= 100; 84 b *= 100;
82 b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2)); 85 b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
83 *freq = (unsigned long) b; 86 *freq = (unsigned long) b;
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index ce447f0f1bad..70a1c60ddda4 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -161,6 +161,7 @@ struct devfreq {
161 struct delayed_work work; 161 struct delayed_work work;
162 162
163 unsigned long previous_freq; 163 unsigned long previous_freq;
164 struct devfreq_dev_status last_status;
164 165
165 void *data; /* private data for governors */ 166 void *data; /* private data for governors */
166 167
@@ -204,6 +205,15 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
204extern void devm_devfreq_unregister_opp_notifier(struct device *dev, 205extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
205 struct devfreq *devfreq); 206 struct devfreq *devfreq);
206 207
208/**
209 * devfreq_update_stats() - update the last_status pointer in struct devfreq
210 * @df: the devfreq instance whose status needs updating
211 */
212static inline int devfreq_update_stats(struct devfreq *df)
213{
214 return df->profile->get_dev_status(df->dev.parent, &df->last_status);
215}
216
207#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) 217#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
208/** 218/**
209 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 219 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
@@ -289,6 +299,11 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
289 struct devfreq *devfreq) 299 struct devfreq *devfreq)
290{ 300{
291} 301}
302
303static inline int devfreq_update_stats(struct devfreq *df)
304{
305 return -EINVAL;
306}
292#endif /* CONFIG_PM_DEVFREQ */ 307#endif /* CONFIG_PM_DEVFREQ */
293 308
294#endif /* __LINUX_DEVFREQ_H__ */ 309#endif /* __LINUX_DEVFREQ_H__ */