Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 267034
b: refs/heads/master
c: ad3c36a
h: refs/heads/master
v: v3
  • Loading branch information
Rafael J. Wysocki committed Sep 27, 2011
1 parent a20dd34 commit cb12f6f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 30b1a7a32ca48fd8758f8ca44d60deebc0aa3d72
refs/heads/master: ad3c36a534bc7b945d7bffdda1c62e13bf93489a
68 changes: 46 additions & 22 deletions trunk/drivers/base/power/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,31 @@ static int rpm_check_suspend_allowed(struct device *dev)
return retval;
}

/**
* __rpm_callback - Run a given runtime PM callback for a given device.
* @cb: Runtime PM callback to run.
* @dev: Device to run the callback for.
*/
static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval;

if (dev->power.irq_safe)
spin_unlock(&dev->power.lock);
else
spin_unlock_irq(&dev->power.lock);

retval = cb(dev);

if (dev->power.irq_safe)
spin_lock(&dev->power.lock);
else
spin_lock_irq(&dev->power.lock);

return retval;
}

/**
* rpm_idle - Notify device bus type if the device can be suspended.
* @dev: Device to notify the bus type about.
Expand Down Expand Up @@ -225,19 +250,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
else
callback = NULL;

if (callback) {
if (dev->power.irq_safe)
spin_unlock(&dev->power.lock);
else
spin_unlock_irq(&dev->power.lock);

callback(dev);

if (dev->power.irq_safe)
spin_lock(&dev->power.lock);
else
spin_lock_irq(&dev->power.lock);
}
if (callback)
__rpm_callback(callback, dev);

dev->power.idle_notification = false;
wake_up_all(&dev->power.wait_queue);
Expand All @@ -252,22 +266,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
* @dev: Device to run the callback for.
*/
static int rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval;

if (!cb)
return -ENOSYS;

if (dev->power.irq_safe) {
retval = cb(dev);
} else {
spin_unlock_irq(&dev->power.lock);

retval = cb(dev);
retval = __rpm_callback(cb, dev);

spin_lock_irq(&dev->power.lock);
}
dev->power.runtime_error = retval;
return retval != -EACCES ? retval : -EIO;
}
Expand Down Expand Up @@ -347,6 +353,15 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto out;
}

if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock);

cpu_relax();

spin_lock(&dev->power.lock);
goto repeat;
}

/* Wait for the other suspend running in parallel with us. */
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,
Expand Down Expand Up @@ -496,6 +511,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
goto out;
}

if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock);

cpu_relax();

spin_lock(&dev->power.lock);
goto repeat;
}

/* Wait for the operation carried out in parallel with us. */
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,
Expand Down

0 comments on commit cb12f6f

Please sign in to comment.