diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
-rw-r--r-- | drivers/base/power/runtime.c | 76 |
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) \ | 16 | typedef 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 | |||
37 | static int (*rpm_get_suspend_cb(struct device *dev))(struct device *) | ||
38 | { | ||
39 | return RPM_GET_CALLBACK(dev, runtime_suspend); | ||
40 | } | ||
41 | 17 | ||
42 | static int (*rpm_get_resume_cb(struct device *dev))(struct device *) | 18 | static 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) |
48 | static 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 | |||
53 | static int rpm_resume(struct device *dev, int rpmflags); | 48 | static int rpm_resume(struct device *dev, int rpmflags); |
54 | static int rpm_suspend(struct device *dev, int rpmflags); | 49 | static 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; |