diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/power/domain.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 339eb2d9bdda..c2468a7e5b21 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -309,7 +309,8 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) | |||
309 | 309 | ||
310 | not_suspended = 0; | 310 | not_suspended = 0; |
311 | list_for_each_entry(pdd, &genpd->dev_list, list_node) | 311 | list_for_each_entry(pdd, &genpd->dev_list, list_node) |
312 | if (pdd->dev->driver && !pm_runtime_suspended(pdd->dev)) | 312 | if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev) |
313 | || pdd->dev->power.irq_safe)) | ||
313 | not_suspended++; | 314 | not_suspended++; |
314 | 315 | ||
315 | if (not_suspended > genpd->in_progress) | 316 | if (not_suspended > genpd->in_progress) |
@@ -417,12 +418,21 @@ static int pm_genpd_runtime_suspend(struct device *dev) | |||
417 | if (IS_ERR(genpd)) | 418 | if (IS_ERR(genpd)) |
418 | return -EINVAL; | 419 | return -EINVAL; |
419 | 420 | ||
421 | might_sleep_if(!genpd->dev_irq_safe); | ||
422 | |||
420 | if (genpd->stop_device) { | 423 | if (genpd->stop_device) { |
421 | int ret = genpd->stop_device(dev); | 424 | int ret = genpd->stop_device(dev); |
422 | if (ret) | 425 | if (ret) |
423 | return ret; | 426 | return ret; |
424 | } | 427 | } |
425 | 428 | ||
429 | /* | ||
430 | * If power.irq_safe is set, this routine will be run with interrupts | ||
431 | * off, so it can't use mutexes. | ||
432 | */ | ||
433 | if (dev->power.irq_safe) | ||
434 | return 0; | ||
435 | |||
426 | mutex_lock(&genpd->lock); | 436 | mutex_lock(&genpd->lock); |
427 | genpd->in_progress++; | 437 | genpd->in_progress++; |
428 | pm_genpd_poweroff(genpd); | 438 | pm_genpd_poweroff(genpd); |
@@ -452,6 +462,12 @@ static int pm_genpd_runtime_resume(struct device *dev) | |||
452 | if (IS_ERR(genpd)) | 462 | if (IS_ERR(genpd)) |
453 | return -EINVAL; | 463 | return -EINVAL; |
454 | 464 | ||
465 | might_sleep_if(!genpd->dev_irq_safe); | ||
466 | |||
467 | /* If power.irq_safe, the PM domain is never powered off. */ | ||
468 | if (dev->power.irq_safe) | ||
469 | goto out; | ||
470 | |||
455 | mutex_lock(&genpd->lock); | 471 | mutex_lock(&genpd->lock); |
456 | ret = __pm_genpd_poweron(genpd); | 472 | ret = __pm_genpd_poweron(genpd); |
457 | if (ret) { | 473 | if (ret) { |
@@ -483,6 +499,7 @@ static int pm_genpd_runtime_resume(struct device *dev) | |||
483 | wake_up_all(&genpd->status_wait_queue); | 499 | wake_up_all(&genpd->status_wait_queue); |
484 | mutex_unlock(&genpd->lock); | 500 | mutex_unlock(&genpd->lock); |
485 | 501 | ||
502 | out: | ||
486 | if (genpd->start_device) | 503 | if (genpd->start_device) |
487 | genpd->start_device(dev); | 504 | genpd->start_device(dev); |
488 | 505 | ||