diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r-- | drivers/base/power/runtime.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 60ebb04d8140..f0d863089345 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -1489,6 +1489,16 @@ int pm_runtime_force_suspend(struct device *dev) | |||
1489 | if (ret) | 1489 | if (ret) |
1490 | goto err; | 1490 | goto err; |
1491 | 1491 | ||
1492 | /* | ||
1493 | * Increase the runtime PM usage count for the device's parent, in case | ||
1494 | * when we find the device being used when system suspend was invoked. | ||
1495 | * This informs pm_runtime_force_resume() to resume the parent | ||
1496 | * immediately, which is needed to be able to resume its children, | ||
1497 | * when not deferring the resume to be managed via runtime PM. | ||
1498 | */ | ||
1499 | if (dev->parent && atomic_read(&dev->power.usage_count) > 1) | ||
1500 | pm_runtime_get_noresume(dev->parent); | ||
1501 | |||
1492 | pm_runtime_set_suspended(dev); | 1502 | pm_runtime_set_suspended(dev); |
1493 | return 0; | 1503 | return 0; |
1494 | err: | 1504 | err: |
@@ -1498,16 +1508,20 @@ err: | |||
1498 | EXPORT_SYMBOL_GPL(pm_runtime_force_suspend); | 1508 | EXPORT_SYMBOL_GPL(pm_runtime_force_suspend); |
1499 | 1509 | ||
1500 | /** | 1510 | /** |
1501 | * pm_runtime_force_resume - Force a device into resume state. | 1511 | * pm_runtime_force_resume - Force a device into resume state if needed. |
1502 | * @dev: Device to resume. | 1512 | * @dev: Device to resume. |
1503 | * | 1513 | * |
1504 | * Prior invoking this function we expect the user to have brought the device | 1514 | * Prior invoking this function we expect the user to have brought the device |
1505 | * into low power state by a call to pm_runtime_force_suspend(). Here we reverse | 1515 | * into low power state by a call to pm_runtime_force_suspend(). Here we reverse |
1506 | * those actions and brings the device into full power. We update the runtime PM | 1516 | * those actions and brings the device into full power, if it is expected to be |
1507 | * status and re-enables runtime PM. | 1517 | * used on system resume. To distinguish that, we check whether the runtime PM |
1518 | * usage count is greater than 1 (the PM core increases the usage count in the | ||
1519 | * system PM prepare phase), as that indicates a real user (such as a subsystem, | ||
1520 | * driver, userspace, etc.) is using it. If that is the case, the device is | ||
1521 | * expected to be used on system resume as well, so then we resume it. In the | ||
1522 | * other case, we defer the resume to be managed via runtime PM. | ||
1508 | * | 1523 | * |
1509 | * Typically this function may be invoked from a system resume callback to make | 1524 | * Typically this function may be invoked from a system resume callback. |
1510 | * sure the device is put into full power state. | ||
1511 | */ | 1525 | */ |
1512 | int pm_runtime_force_resume(struct device *dev) | 1526 | int pm_runtime_force_resume(struct device *dev) |
1513 | { | 1527 | { |
@@ -1524,6 +1538,17 @@ int pm_runtime_force_resume(struct device *dev) | |||
1524 | if (!pm_runtime_status_suspended(dev)) | 1538 | if (!pm_runtime_status_suspended(dev)) |
1525 | goto out; | 1539 | goto out; |
1526 | 1540 | ||
1541 | /* | ||
1542 | * Decrease the parent's runtime PM usage count, if we increased it | ||
1543 | * during system suspend in pm_runtime_force_suspend(). | ||
1544 | */ | ||
1545 | if (atomic_read(&dev->power.usage_count) > 1) { | ||
1546 | if (dev->parent) | ||
1547 | pm_runtime_put_noidle(dev->parent); | ||
1548 | } else { | ||
1549 | goto out; | ||
1550 | } | ||
1551 | |||
1527 | ret = pm_runtime_set_active(dev); | 1552 | ret = pm_runtime_set_active(dev); |
1528 | if (ret) | 1553 | if (ret) |
1529 | goto out; | 1554 | goto out; |