diff options
author | Javi Merino <javi.merino@arm.com> | 2015-08-14 13:56:56 -0400 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2015-09-11 01:23:28 -0400 |
commit | 08e75e754a6d9838e490b74551d19fc04d0fd6f9 (patch) | |
tree | 71344662250f9bd22389a86e886a1aa6b67c7fed | |
parent | 9348da2f1c2ca8e064d4907cdc5b3a19477df933 (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.c | 33 | ||||
-rw-r--r-- | include/linux/devfreq.h | 15 |
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 @@ | |||
21 | static int devfreq_simple_ondemand_func(struct devfreq *df, | 21 | static 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, | |||
204 | extern void devm_devfreq_unregister_opp_notifier(struct device *dev, | 205 | extern 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 | */ | ||
212 | static 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 | |||
303 | static 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__ */ |