diff options
-rw-r--r-- | drivers/base/power/domain.c | 17 |
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 | */ |
287 | static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on) | 287 | static 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 | ||