aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/runtime.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index a770498a74ec..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;
@@ -328,11 +327,11 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
328 * necessary. 327 * necessary.
329 */ 328 */
330 parent = dev->parent; 329 parent = dev->parent;
331 spin_unlock_irq(&dev->power.lock); 330 spin_unlock(&dev->power.lock);
332 331
333 pm_runtime_get_noresume(parent); 332 pm_runtime_get_noresume(parent);
334 333
335 spin_lock_irq(&parent->power.lock); 334 spin_lock(&parent->power.lock);
336 /* 335 /*
337 * We can resume if the parent's run-time PM is disabled or it 336 * We can resume if the parent's run-time PM is disabled or it
338 * is set to ignore children. 337 * is set to ignore children.
@@ -343,9 +342,9 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
343 if (parent->power.runtime_status != RPM_ACTIVE) 342 if (parent->power.runtime_status != RPM_ACTIVE)
344 retval = -EBUSY; 343 retval = -EBUSY;
345 } 344 }
346 spin_unlock_irq(&parent->power.lock); 345 spin_unlock(&parent->power.lock);
347 346
348 spin_lock_irq(&dev->power.lock); 347 spin_lock(&dev->power.lock);
349 if (retval) 348 if (retval)
350 goto out; 349 goto out;
351 goto repeat; 350 goto repeat;
@@ -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_irq(&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,14 +791,12 @@ 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_irq(&parent->power.lock); 799 spin_unlock(&parent->power.lock);
797 800
798 if (error) 801 if (error)
799 goto out; 802 goto out;