diff options
-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 | } |