aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-14 19:29:43 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-09-14 19:29:43 -0400
commit4184a8fc57a43faa2625988cc87031db77af9d98 (patch)
treee092eaeeb2ee7c88915dac17446d08c19ab0e5e7
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
parent5f25f066f75a67835abb5e400471a27abd09395b (diff)
Merge branch 'for-rafael' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq updates for v4.3 from MyungJoo Ham. * 'for-rafael' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq: PM / devfreq: Fix incorrect type issue. PM / devfreq: tegra: Update governor to use devfreq_update_stats() PM / devfreq: comments for get_dev_status usage updated PM / devfreq: drop comment about thermal setting max_freq PM / devfreq: cache the last call to get_dev_status() PM / devfreq: Drop unlikely before IS_ERR(_OR_NULL) PM / devfreq: exynos-ppmu: bit-wise operation bugfix. PM / devfreq: exynos-ppmu: Update documentation to support PPMUv2 PM / devfreq: exynos-ppmu: Add the support of PPMUv2 for Exynos5433 PM / devfreq: event: Remove incorrect property in exynos-ppmu DT binding Conflicts: drivers/devfreq/event/exynos-ppmu.c
-rw-r--r--drivers/devfreq/devfreq.c12
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c3
-rw-r--r--drivers/devfreq/governor_simpleondemand.c33
-rw-r--r--drivers/devfreq/tegra-devfreq.c8
-rw-r--r--include/linux/devfreq.h24
5 files changed, 54 insertions, 26 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index ca1b362d77e2..3927ed9fdbd5 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -53,7 +53,7 @@ static struct devfreq *find_device_devfreq(struct device *dev)
53{ 53{
54 struct devfreq *tmp_devfreq; 54 struct devfreq *tmp_devfreq;
55 55
56 if (unlikely(IS_ERR_OR_NULL(dev))) { 56 if (IS_ERR_OR_NULL(dev)) {
57 pr_err("DEVFREQ: %s: Invalid parameters\n", __func__); 57 pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
58 return ERR_PTR(-EINVAL); 58 return ERR_PTR(-EINVAL);
59 } 59 }
@@ -133,7 +133,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
133{ 133{
134 struct devfreq_governor *tmp_governor; 134 struct devfreq_governor *tmp_governor;
135 135
136 if (unlikely(IS_ERR_OR_NULL(name))) { 136 if (IS_ERR_OR_NULL(name)) {
137 pr_err("DEVFREQ: %s: Invalid parameters\n", __func__); 137 pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
138 return ERR_PTR(-EINVAL); 138 return ERR_PTR(-EINVAL);
139 } 139 }
@@ -177,10 +177,10 @@ int update_devfreq(struct devfreq *devfreq)
177 return err; 177 return err;
178 178
179 /* 179 /*
180 * Adjust the freuqency with user freq and QoS. 180 * Adjust the frequency with user freq and QoS.
181 * 181 *
182 * List from the highest proiority 182 * List from the highest priority
183 * max_freq (probably called by thermal when it's too hot) 183 * max_freq
184 * min_freq 184 * min_freq
185 */ 185 */
186 186
@@ -482,7 +482,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
482 devfreq->profile->max_state * 482 devfreq->profile->max_state *
483 devfreq->profile->max_state, 483 devfreq->profile->max_state,
484 GFP_KERNEL); 484 GFP_KERNEL);
485 devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) * 485 devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned long) *
486 devfreq->profile->max_state, 486 devfreq->profile->max_state,
487 GFP_KERNEL); 487 GFP_KERNEL);
488 devfreq->last_stat_updated = jiffies; 488 devfreq->last_stat_updated = jiffies;
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index f9901f52a225..f312485f1451 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -319,7 +319,8 @@ static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
319 case PPMU_PMNCNT3: 319 case PPMU_PMNCNT3:
320 pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH); 320 pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH);
321 pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW); 321 pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW);
322 load_count = (u64)((pmcnt_high & 0xff) << 32) + (u64)pmcnt_low; 322 load_count = ((u64)((pmcnt_high & 0xff)) << 32)
323 + (u64)pmcnt_low;
323 break; 324 break;
324 } 325 }
325 edata->load_count = load_count; 326 edata->load_count = load_count;
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/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
index 13a1a6e8108c..848b93ee930f 100644
--- a/drivers/devfreq/tegra-devfreq.c
+++ b/drivers/devfreq/tegra-devfreq.c
@@ -541,18 +541,20 @@ static struct devfreq_dev_profile tegra_devfreq_profile = {
541static int tegra_governor_get_target(struct devfreq *devfreq, 541static int tegra_governor_get_target(struct devfreq *devfreq,
542 unsigned long *freq) 542 unsigned long *freq)
543{ 543{
544 struct devfreq_dev_status stat; 544 struct devfreq_dev_status *stat;
545 struct tegra_devfreq *tegra; 545 struct tegra_devfreq *tegra;
546 struct tegra_devfreq_device *dev; 546 struct tegra_devfreq_device *dev;
547 unsigned long target_freq = 0; 547 unsigned long target_freq = 0;
548 unsigned int i; 548 unsigned int i;
549 int err; 549 int err;
550 550
551 err = devfreq->profile->get_dev_status(devfreq->dev.parent, &stat); 551 err = devfreq_update_stats(devfreq);
552 if (err) 552 if (err)
553 return err; 553 return err;
554 554
555 tegra = stat.private_data; 555 stat = &devfreq->last_status;
556
557 tegra = stat->private_data;
556 558
557 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 559 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
558 dev = &tegra->devices[i]; 560 dev = &tegra->devices[i];
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index ce447f0f1bad..68030e22af35 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -65,7 +65,10 @@ struct devfreq_dev_status {
65 * The "flags" parameter's possible values are 65 * The "flags" parameter's possible values are
66 * explained above with "DEVFREQ_FLAG_*" macros. 66 * explained above with "DEVFREQ_FLAG_*" macros.
67 * @get_dev_status: The device should provide the current performance 67 * @get_dev_status: The device should provide the current performance
68 * status to devfreq, which is used by governors. 68 * status to devfreq. Governors are recommended not to
69 * use this directly. Instead, governors are recommended
70 * to use devfreq_update_stats() along with
71 * devfreq.last_status.
69 * @get_cur_freq: The device should provide the current frequency 72 * @get_cur_freq: The device should provide the current frequency
70 * at which it is operating. 73 * at which it is operating.
71 * @exit: An optional callback that is called when devfreq 74 * @exit: An optional callback that is called when devfreq
@@ -161,6 +164,7 @@ struct devfreq {
161 struct delayed_work work; 164 struct delayed_work work;
162 165
163 unsigned long previous_freq; 166 unsigned long previous_freq;
167 struct devfreq_dev_status last_status;
164 168
165 void *data; /* private data for governors */ 169 void *data; /* private data for governors */
166 170
@@ -204,6 +208,19 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
204extern void devm_devfreq_unregister_opp_notifier(struct device *dev, 208extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
205 struct devfreq *devfreq); 209 struct devfreq *devfreq);
206 210
211/**
212 * devfreq_update_stats() - update the last_status pointer in struct devfreq
213 * @df: the devfreq instance whose status needs updating
214 *
215 * Governors are recommended to use this function along with last_status,
216 * which allows other entities to reuse the last_status without affecting
217 * the values fetched later by governors.
218 */
219static inline int devfreq_update_stats(struct devfreq *df)
220{
221 return df->profile->get_dev_status(df->dev.parent, &df->last_status);
222}
223
207#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) 224#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
208/** 225/**
209 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 226 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
@@ -289,6 +306,11 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
289 struct devfreq *devfreq) 306 struct devfreq *devfreq)
290{ 307{
291} 308}
309
310static inline int devfreq_update_stats(struct devfreq *df)
311{
312 return -EINVAL;
313}
292#endif /* CONFIG_PM_DEVFREQ */ 314#endif /* CONFIG_PM_DEVFREQ */
293 315
294#endif /* __LINUX_DEVFREQ_H__ */ 316#endif /* __LINUX_DEVFREQ_H__ */