aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r--drivers/base/power/runtime.c76
1 files changed, 32 insertions, 44 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 67c7938e430b..5070c4fe8542 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -13,43 +13,38 @@
13#include <trace/events/rpm.h> 13#include <trace/events/rpm.h>
14#include "power.h" 14#include "power.h"
15 15
16#define RPM_GET_CALLBACK(dev, cb) \ 16typedef int (*pm_callback_t)(struct device *);
17({ \
18 int (*__rpm_cb)(struct device *__d); \
19 \
20 if (dev->pm_domain) \
21 __rpm_cb = dev->pm_domain->ops.cb; \
22 else if (dev->type && dev->type->pm) \
23 __rpm_cb = dev->type->pm->cb; \
24 else if (dev->class && dev->class->pm) \
25 __rpm_cb = dev->class->pm->cb; \
26 else if (dev->bus && dev->bus->pm) \
27 __rpm_cb = dev->bus->pm->cb; \
28 else \
29 __rpm_cb = NULL; \
30 \
31 if (!__rpm_cb && dev->driver && dev->driver->pm) \
32 __rpm_cb = dev->driver->pm->cb; \
33 \
34 __rpm_cb; \
35})
36
37static int (*rpm_get_suspend_cb(struct device *dev))(struct device *)
38{
39 return RPM_GET_CALLBACK(dev, runtime_suspend);
40}
41 17
42static int (*rpm_get_resume_cb(struct device *dev))(struct device *) 18static pm_callback_t __rpm_get_callback(struct device *dev, size_t cb_offset)
43{ 19{
44 return RPM_GET_CALLBACK(dev, runtime_resume); 20 pm_callback_t cb;
45} 21 const struct dev_pm_ops *ops;
22
23 if (dev->pm_domain)
24 ops = &dev->pm_domain->ops;
25 else if (dev->type && dev->type->pm)
26 ops = dev->type->pm;
27 else if (dev->class && dev->class->pm)
28 ops = dev->class->pm;
29 else if (dev->bus && dev->bus->pm)
30 ops = dev->bus->pm;
31 else
32 ops = NULL;
46 33
47#ifdef CONFIG_PM_RUNTIME 34 if (ops)
48static int (*rpm_get_idle_cb(struct device *dev))(struct device *) 35 cb = *(pm_callback_t *)((void *)ops + cb_offset);
49{ 36 else
50 return RPM_GET_CALLBACK(dev, runtime_idle); 37 cb = NULL;
38
39 if (!cb && dev->driver && dev->driver->pm)
40 cb = *(pm_callback_t *)((void *)dev->driver->pm + cb_offset);
41
42 return cb;
51} 43}
52 44
45#define RPM_GET_CALLBACK(dev, callback) \
46 __rpm_get_callback(dev, offsetof(struct dev_pm_ops, callback))
47
53static int rpm_resume(struct device *dev, int rpmflags); 48static int rpm_resume(struct device *dev, int rpmflags);
54static int rpm_suspend(struct device *dev, int rpmflags); 49static int rpm_suspend(struct device *dev, int rpmflags);
55 50
@@ -347,7 +342,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
347 342
348 dev->power.idle_notification = true; 343 dev->power.idle_notification = true;
349 344
350 callback = rpm_get_idle_cb(dev); 345 callback = RPM_GET_CALLBACK(dev, runtime_idle);
351 346
352 if (callback) 347 if (callback)
353 retval = __rpm_callback(callback, dev); 348 retval = __rpm_callback(callback, dev);
@@ -517,7 +512,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
517 512
518 __update_runtime_status(dev, RPM_SUSPENDING); 513 __update_runtime_status(dev, RPM_SUSPENDING);
519 514
520 callback = rpm_get_suspend_cb(dev); 515 callback = RPM_GET_CALLBACK(dev, runtime_suspend);
521 516
522 retval = rpm_callback(callback, dev); 517 retval = rpm_callback(callback, dev);
523 if (retval) 518 if (retval)
@@ -737,7 +732,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
737 732
738 __update_runtime_status(dev, RPM_RESUMING); 733 __update_runtime_status(dev, RPM_RESUMING);
739 734
740 callback = rpm_get_resume_cb(dev); 735 callback = RPM_GET_CALLBACK(dev, runtime_resume);
741 736
742 retval = rpm_callback(callback, dev); 737 retval = rpm_callback(callback, dev);
743 if (retval) { 738 if (retval) {
@@ -1402,7 +1397,6 @@ void pm_runtime_remove(struct device *dev)
1402 if (dev->power.irq_safe && dev->parent) 1397 if (dev->power.irq_safe && dev->parent)
1403 pm_runtime_put(dev->parent); 1398 pm_runtime_put(dev->parent);
1404} 1399}
1405#endif
1406 1400
1407/** 1401/**
1408 * pm_runtime_force_suspend - Force a device into suspend state if needed. 1402 * pm_runtime_force_suspend - Force a device into suspend state if needed.
@@ -1422,16 +1416,10 @@ int pm_runtime_force_suspend(struct device *dev)
1422 int ret = 0; 1416 int ret = 0;
1423 1417
1424 pm_runtime_disable(dev); 1418 pm_runtime_disable(dev);
1425
1426 /*
1427 * Note that pm_runtime_status_suspended() returns false while
1428 * !CONFIG_PM_RUNTIME, which means the device will be put into low
1429 * power state.
1430 */
1431 if (pm_runtime_status_suspended(dev)) 1419 if (pm_runtime_status_suspended(dev))
1432 return 0; 1420 return 0;
1433 1421
1434 callback = rpm_get_suspend_cb(dev); 1422 callback = RPM_GET_CALLBACK(dev, runtime_suspend);
1435 1423
1436 if (!callback) { 1424 if (!callback) {
1437 ret = -ENOSYS; 1425 ret = -ENOSYS;
@@ -1467,7 +1455,7 @@ int pm_runtime_force_resume(struct device *dev)
1467 int (*callback)(struct device *); 1455 int (*callback)(struct device *);
1468 int ret = 0; 1456 int ret = 0;
1469 1457
1470 callback = rpm_get_resume_cb(dev); 1458 callback = RPM_GET_CALLBACK(dev, runtime_resume);
1471 1459
1472 if (!callback) { 1460 if (!callback) {
1473 ret = -ENOSYS; 1461 ret = -ENOSYS;