diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
| -rw-r--r-- | drivers/base/power/runtime.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 846d89e3d122..5a01ecef4af3 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -185,6 +185,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | dev->power.runtime_status = RPM_SUSPENDING; | 187 | dev->power.runtime_status = RPM_SUSPENDING; |
| 188 | dev->power.deferred_resume = false; | ||
| 188 | 189 | ||
| 189 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { | 190 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { |
| 190 | spin_unlock_irq(&dev->power.lock); | 191 | spin_unlock_irq(&dev->power.lock); |
| @@ -200,7 +201,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 200 | if (retval) { | 201 | if (retval) { |
| 201 | dev->power.runtime_status = RPM_ACTIVE; | 202 | dev->power.runtime_status = RPM_ACTIVE; |
| 202 | pm_runtime_cancel_pending(dev); | 203 | pm_runtime_cancel_pending(dev); |
| 203 | dev->power.deferred_resume = false; | ||
| 204 | 204 | ||
| 205 | if (retval == -EAGAIN || retval == -EBUSY) { | 205 | if (retval == -EAGAIN || retval == -EBUSY) { |
| 206 | notify = true; | 206 | notify = true; |
| @@ -217,7 +217,6 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) | |||
| 217 | wake_up_all(&dev->power.wait_queue); | 217 | wake_up_all(&dev->power.wait_queue); |
| 218 | 218 | ||
| 219 | if (dev->power.deferred_resume) { | 219 | if (dev->power.deferred_resume) { |
| 220 | dev->power.deferred_resume = false; | ||
| 221 | __pm_runtime_resume(dev, false); | 220 | __pm_runtime_resume(dev, false); |
| 222 | retval = -EAGAIN; | 221 | retval = -EAGAIN; |
| 223 | goto out; | 222 | goto out; |
| @@ -626,6 +625,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay) | |||
| 626 | goto out; | 625 | goto out; |
| 627 | 626 | ||
| 628 | dev->power.timer_expires = jiffies + msecs_to_jiffies(delay); | 627 | dev->power.timer_expires = jiffies + msecs_to_jiffies(delay); |
| 628 | if (!dev->power.timer_expires) | ||
| 629 | dev->power.timer_expires = 1; | ||
| 629 | mod_timer(&dev->power.suspend_timer, dev->power.timer_expires); | 630 | mod_timer(&dev->power.suspend_timer, dev->power.timer_expires); |
| 630 | 631 | ||
| 631 | out: | 632 | out: |
| @@ -659,13 +660,17 @@ static int __pm_request_resume(struct device *dev) | |||
| 659 | 660 | ||
| 660 | pm_runtime_deactivate_timer(dev); | 661 | pm_runtime_deactivate_timer(dev); |
| 661 | 662 | ||
| 663 | if (dev->power.runtime_status == RPM_SUSPENDING) { | ||
| 664 | dev->power.deferred_resume = true; | ||
| 665 | return retval; | ||
| 666 | } | ||
| 662 | if (dev->power.request_pending) { | 667 | if (dev->power.request_pending) { |
| 663 | /* If non-resume request is pending, we can overtake it. */ | 668 | /* If non-resume request is pending, we can overtake it. */ |
| 664 | dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME; | 669 | dev->power.request = retval ? RPM_REQ_NONE : RPM_REQ_RESUME; |
| 665 | return retval; | 670 | return retval; |
| 666 | } else if (retval) { | ||
| 667 | return retval; | ||
| 668 | } | 671 | } |
| 672 | if (retval) | ||
| 673 | return retval; | ||
| 669 | 674 | ||
| 670 | dev->power.request = RPM_REQ_RESUME; | 675 | dev->power.request = RPM_REQ_RESUME; |
| 671 | dev->power.request_pending = true; | 676 | dev->power.request_pending = true; |
| @@ -777,7 +782,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status) | |||
| 777 | } | 782 | } |
| 778 | 783 | ||
| 779 | if (parent) { | 784 | if (parent) { |
| 780 | spin_lock(&parent->power.lock); | 785 | spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING); |
| 781 | 786 | ||
| 782 | /* | 787 | /* |
| 783 | * It is invalid to put an active child under a parent that is | 788 | * It is invalid to put an active child under a parent that is |
| @@ -786,12 +791,10 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status) | |||
| 786 | */ | 791 | */ |
| 787 | if (!parent->power.disable_depth | 792 | if (!parent->power.disable_depth |
| 788 | && !parent->power.ignore_children | 793 | && !parent->power.ignore_children |
| 789 | && parent->power.runtime_status != RPM_ACTIVE) { | 794 | && parent->power.runtime_status != RPM_ACTIVE) |
| 790 | error = -EBUSY; | 795 | error = -EBUSY; |
| 791 | } else { | 796 | else if (dev->power.runtime_status == RPM_SUSPENDED) |
| 792 | if (dev->power.runtime_status == RPM_SUSPENDED) | 797 | atomic_inc(&parent->power.child_count); |
| 793 | atomic_inc(&parent->power.child_count); | ||
| 794 | } | ||
| 795 | 798 | ||
| 796 | spin_unlock(&parent->power.lock); | 799 | spin_unlock(&parent->power.lock); |
| 797 | 800 | ||
