diff options
author | Geert Uytterhoeven <geert+renesas@glider.be> | 2014-11-10 13:39:19 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-11-13 18:07:31 -0500 |
commit | c8f0ea45169c57f36e6d8c4dcf7ccf09de7f1c2c (patch) | |
tree | e00a8b808323f4483d449a23c5b99f6e3d8ba3c2 /drivers/base/power/domain.c | |
parent | 895b31f3b6b800b8f46569391f2396b1f221c602 (diff) |
PM / Domains: Extract code to power off/on a PM domain
PM domains are powered on/off from various places. Some callers do
latency measurements, others don't. Consolidate using two helper
functions, which always measure the latencies, and update the stored
latencies when needed.
Other minor changes:
- Use pr_warn() instead of pr_warning(),
- There's no need to check genpd->name, %s handles NULL pointers fine,
- Make the warning format strings identical, to save memory.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base/power/domain.c')
-rw-r--r-- | drivers/base/power/domain.c | 101 |
1 files changed, 60 insertions, 41 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 28d6e8bf746c..1d1f5cc4293d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -151,6 +151,59 @@ static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd) | |||
151 | genpd->cpuidle_data->idle_state->exit_latency = usecs64; | 151 | genpd->cpuidle_data->idle_state->exit_latency = usecs64; |
152 | } | 152 | } |
153 | 153 | ||
154 | static int genpd_power_on(struct generic_pm_domain *genpd) | ||
155 | { | ||
156 | ktime_t time_start; | ||
157 | s64 elapsed_ns; | ||
158 | int ret; | ||
159 | |||
160 | if (!genpd->power_on) | ||
161 | return 0; | ||
162 | |||
163 | time_start = ktime_get(); | ||
164 | ret = genpd->power_on(genpd); | ||
165 | if (ret) | ||
166 | return ret; | ||
167 | |||
168 | elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); | ||
169 | if (elapsed_ns <= genpd->power_on_latency_ns) | ||
170 | return ret; | ||
171 | |||
172 | genpd->power_on_latency_ns = elapsed_ns; | ||
173 | genpd->max_off_time_changed = true; | ||
174 | genpd_recalc_cpu_exit_latency(genpd); | ||
175 | pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", | ||
176 | genpd->name, "on", elapsed_ns); | ||
177 | |||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | static int genpd_power_off(struct generic_pm_domain *genpd) | ||
182 | { | ||
183 | ktime_t time_start; | ||
184 | s64 elapsed_ns; | ||
185 | int ret; | ||
186 | |||
187 | if (!genpd->power_off) | ||
188 | return 0; | ||
189 | |||
190 | time_start = ktime_get(); | ||
191 | ret = genpd->power_off(genpd); | ||
192 | if (ret == -EBUSY) | ||
193 | return ret; | ||
194 | |||
195 | elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); | ||
196 | if (elapsed_ns <= genpd->power_off_latency_ns) | ||
197 | return ret; | ||
198 | |||
199 | genpd->power_off_latency_ns = elapsed_ns; | ||
200 | genpd->max_off_time_changed = true; | ||
201 | pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", | ||
202 | genpd->name, "off", elapsed_ns); | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
154 | /** | 207 | /** |
155 | * __pm_genpd_poweron - Restore power to a given PM domain and its masters. | 208 | * __pm_genpd_poweron - Restore power to a given PM domain and its masters. |
156 | * @genpd: PM domain to power up. | 209 | * @genpd: PM domain to power up. |
@@ -222,25 +275,9 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd) | |||
222 | } | 275 | } |
223 | } | 276 | } |
224 | 277 | ||
225 | if (genpd->power_on) { | 278 | ret = genpd_power_on(genpd); |
226 | ktime_t time_start = ktime_get(); | 279 | if (ret) |
227 | s64 elapsed_ns; | 280 | goto err; |
228 | |||
229 | ret = genpd->power_on(genpd); | ||
230 | if (ret) | ||
231 | goto err; | ||
232 | |||
233 | elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); | ||
234 | if (elapsed_ns > genpd->power_on_latency_ns) { | ||
235 | genpd->power_on_latency_ns = elapsed_ns; | ||
236 | genpd->max_off_time_changed = true; | ||
237 | genpd_recalc_cpu_exit_latency(genpd); | ||
238 | if (genpd->name) | ||
239 | pr_warning("%s: Power-on latency exceeded, " | ||
240 | "new value %lld ns\n", genpd->name, | ||
241 | elapsed_ns); | ||
242 | } | ||
243 | } | ||
244 | 281 | ||
245 | out: | 282 | out: |
246 | genpd_set_active(genpd); | 283 | genpd_set_active(genpd); |
@@ -529,16 +566,11 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) | |||
529 | } | 566 | } |
530 | 567 | ||
531 | if (genpd->power_off) { | 568 | if (genpd->power_off) { |
532 | ktime_t time_start; | ||
533 | s64 elapsed_ns; | ||
534 | |||
535 | if (atomic_read(&genpd->sd_count) > 0) { | 569 | if (atomic_read(&genpd->sd_count) > 0) { |
536 | ret = -EBUSY; | 570 | ret = -EBUSY; |
537 | goto out; | 571 | goto out; |
538 | } | 572 | } |
539 | 573 | ||
540 | time_start = ktime_get(); | ||
541 | |||
542 | /* | 574 | /* |
543 | * If sd_count > 0 at this point, one of the subdomains hasn't | 575 | * If sd_count > 0 at this point, one of the subdomains hasn't |
544 | * managed to call pm_genpd_poweron() for the master yet after | 576 | * managed to call pm_genpd_poweron() for the master yet after |
@@ -547,21 +579,11 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) | |||
547 | * the pm_genpd_poweron() restore power for us (this shouldn't | 579 | * the pm_genpd_poweron() restore power for us (this shouldn't |
548 | * happen very often). | 580 | * happen very often). |
549 | */ | 581 | */ |
550 | ret = genpd->power_off(genpd); | 582 | ret = genpd_power_off(genpd); |
551 | if (ret == -EBUSY) { | 583 | if (ret == -EBUSY) { |
552 | genpd_set_active(genpd); | 584 | genpd_set_active(genpd); |
553 | goto out; | 585 | goto out; |
554 | } | 586 | } |
555 | |||
556 | elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); | ||
557 | if (elapsed_ns > genpd->power_off_latency_ns) { | ||
558 | genpd->power_off_latency_ns = elapsed_ns; | ||
559 | genpd->max_off_time_changed = true; | ||
560 | if (genpd->name) | ||
561 | pr_warning("%s: Power-off latency exceeded, " | ||
562 | "new value %lld ns\n", genpd->name, | ||
563 | elapsed_ns); | ||
564 | } | ||
565 | } | 587 | } |
566 | 588 | ||
567 | genpd->status = GPD_STATE_POWER_OFF; | 589 | genpd->status = GPD_STATE_POWER_OFF; |
@@ -796,8 +818,7 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) | |||
796 | || atomic_read(&genpd->sd_count) > 0) | 818 | || atomic_read(&genpd->sd_count) > 0) |
797 | return; | 819 | return; |
798 | 820 | ||
799 | if (genpd->power_off) | 821 | genpd_power_off(genpd); |
800 | genpd->power_off(genpd); | ||
801 | 822 | ||
802 | genpd->status = GPD_STATE_POWER_OFF; | 823 | genpd->status = GPD_STATE_POWER_OFF; |
803 | 824 | ||
@@ -828,8 +849,7 @@ static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) | |||
828 | genpd_sd_counter_inc(link->master); | 849 | genpd_sd_counter_inc(link->master); |
829 | } | 850 | } |
830 | 851 | ||
831 | if (genpd->power_on) | 852 | genpd_power_on(genpd); |
832 | genpd->power_on(genpd); | ||
833 | 853 | ||
834 | genpd->status = GPD_STATE_ACTIVE; | 854 | genpd->status = GPD_STATE_ACTIVE; |
835 | } | 855 | } |
@@ -1251,8 +1271,7 @@ static int pm_genpd_restore_noirq(struct device *dev) | |||
1251 | * If the domain was off before the hibernation, make | 1271 | * If the domain was off before the hibernation, make |
1252 | * sure it will be off going forward. | 1272 | * sure it will be off going forward. |
1253 | */ | 1273 | */ |
1254 | if (genpd->power_off) | 1274 | genpd_power_off(genpd); |
1255 | genpd->power_off(genpd); | ||
1256 | 1275 | ||
1257 | return 0; | 1276 | return 0; |
1258 | } | 1277 | } |