aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/domain.c101
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
154static 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
181static 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 }