aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/domain.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 179bb269a58f..e697dec9d25b 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -284,7 +284,8 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
284 * If all of the @genpd's devices have been suspended and all of its subdomains 284 * If all of the @genpd's devices have been suspended and all of its subdomains
285 * have been powered down, remove power from @genpd. 285 * have been powered down, remove power from @genpd.
286 */ 286 */
287static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on) 287static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
288 unsigned int depth)
288{ 289{
289 struct pm_domain_data *pdd; 290 struct pm_domain_data *pdd;
290 struct gpd_link *link; 291 struct gpd_link *link;
@@ -351,7 +352,9 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on)
351 352
352 list_for_each_entry(link, &genpd->slave_links, slave_node) { 353 list_for_each_entry(link, &genpd->slave_links, slave_node) {
353 genpd_sd_counter_dec(link->master); 354 genpd_sd_counter_dec(link->master);
354 genpd_queue_power_off_work(link->master); 355 genpd_lock_nested(link->master, depth + 1);
356 genpd_power_off(link->master, false, depth + 1);
357 genpd_unlock(link->master);
355 } 358 }
356 359
357 return 0; 360 return 0;
@@ -405,7 +408,9 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
405 &genpd->slave_links, 408 &genpd->slave_links,
406 slave_node) { 409 slave_node) {
407 genpd_sd_counter_dec(link->master); 410 genpd_sd_counter_dec(link->master);
408 genpd_queue_power_off_work(link->master); 411 genpd_lock_nested(link->master, depth + 1);
412 genpd_power_off(link->master, false, depth + 1);
413 genpd_unlock(link->master);
409 } 414 }
410 415
411 return ret; 416 return ret;
@@ -462,7 +467,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
462 genpd = container_of(work, struct generic_pm_domain, power_off_work); 467 genpd = container_of(work, struct generic_pm_domain, power_off_work);
463 468
464 genpd_lock(genpd); 469 genpd_lock(genpd);
465 genpd_power_off(genpd, false); 470 genpd_power_off(genpd, false, 0);
466 genpd_unlock(genpd); 471 genpd_unlock(genpd);
467} 472}
468 473
@@ -581,7 +586,7 @@ static int genpd_runtime_suspend(struct device *dev)
581 return 0; 586 return 0;
582 587
583 genpd_lock(genpd); 588 genpd_lock(genpd);
584 genpd_power_off(genpd, true); 589 genpd_power_off(genpd, true, 0);
585 genpd_unlock(genpd); 590 genpd_unlock(genpd);
586 591
587 return 0; 592 return 0;
@@ -661,7 +666,7 @@ err_poweroff:
661 if (!pm_runtime_is_irq_safe(dev) || 666 if (!pm_runtime_is_irq_safe(dev) ||
662 (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) { 667 (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) {
663 genpd_lock(genpd); 668 genpd_lock(genpd);
664 genpd_power_off(genpd, true); 669 genpd_power_off(genpd, true, 0);
665 genpd_unlock(genpd); 670 genpd_unlock(genpd);
666 } 671 }
667 672