diff options
author | Liu, Chuansheng <chuansheng.liu@intel.com> | 2014-02-17 21:28:44 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-19 19:30:08 -0500 |
commit | 3d2699bc179a10eee7d2aa1db50f822be01636f7 (patch) | |
tree | df5a6eae5b59f5ed8e40eb650f23cc8d84a70f0b | |
parent | 6d0abeca3242a88cab8232e4acd7e2bf088f3bc2 (diff) |
PM / sleep: Two flags for async suspend_noirq and suspend_late
The patch is a helper adding two new flags for implementing
async threads for suspend_noirq and suspend_late.
Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/base/power/main.c | 24 | ||||
-rw-r--r-- | include/linux/pm.h | 2 |
2 files changed, 24 insertions, 2 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1b41fca3d65a..00c53eb8ebca 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -91,6 +91,8 @@ void device_pm_sleep_init(struct device *dev) | |||
91 | { | 91 | { |
92 | dev->power.is_prepared = false; | 92 | dev->power.is_prepared = false; |
93 | dev->power.is_suspended = false; | 93 | dev->power.is_suspended = false; |
94 | dev->power.is_noirq_suspended = false; | ||
95 | dev->power.is_late_suspended = false; | ||
94 | init_completion(&dev->power.completion); | 96 | init_completion(&dev->power.completion); |
95 | complete_all(&dev->power.completion); | 97 | complete_all(&dev->power.completion); |
96 | dev->power.wakeup = NULL; | 98 | dev->power.wakeup = NULL; |
@@ -479,6 +481,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
479 | if (dev->power.syscore) | 481 | if (dev->power.syscore) |
480 | goto Out; | 482 | goto Out; |
481 | 483 | ||
484 | if (!dev->power.is_noirq_suspended) | ||
485 | goto Out; | ||
486 | |||
482 | if (dev->pm_domain) { | 487 | if (dev->pm_domain) { |
483 | info = "noirq power domain "; | 488 | info = "noirq power domain "; |
484 | callback = pm_noirq_op(&dev->pm_domain->ops, state); | 489 | callback = pm_noirq_op(&dev->pm_domain->ops, state); |
@@ -499,6 +504,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
499 | } | 504 | } |
500 | 505 | ||
501 | error = dpm_run_callback(callback, dev, state, info); | 506 | error = dpm_run_callback(callback, dev, state, info); |
507 | dev->power.is_noirq_suspended = false; | ||
502 | 508 | ||
503 | Out: | 509 | Out: |
504 | TRACE_RESUME(error); | 510 | TRACE_RESUME(error); |
@@ -561,6 +567,9 @@ static int device_resume_early(struct device *dev, pm_message_t state) | |||
561 | if (dev->power.syscore) | 567 | if (dev->power.syscore) |
562 | goto Out; | 568 | goto Out; |
563 | 569 | ||
570 | if (!dev->power.is_late_suspended) | ||
571 | goto Out; | ||
572 | |||
564 | if (dev->pm_domain) { | 573 | if (dev->pm_domain) { |
565 | info = "early power domain "; | 574 | info = "early power domain "; |
566 | callback = pm_late_early_op(&dev->pm_domain->ops, state); | 575 | callback = pm_late_early_op(&dev->pm_domain->ops, state); |
@@ -581,6 +590,7 @@ static int device_resume_early(struct device *dev, pm_message_t state) | |||
581 | } | 590 | } |
582 | 591 | ||
583 | error = dpm_run_callback(callback, dev, state, info); | 592 | error = dpm_run_callback(callback, dev, state, info); |
593 | dev->power.is_late_suspended = false; | ||
584 | 594 | ||
585 | Out: | 595 | Out: |
586 | TRACE_RESUME(error); | 596 | TRACE_RESUME(error); |
@@ -917,6 +927,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
917 | { | 927 | { |
918 | pm_callback_t callback = NULL; | 928 | pm_callback_t callback = NULL; |
919 | char *info = NULL; | 929 | char *info = NULL; |
930 | int error; | ||
920 | 931 | ||
921 | if (dev->power.syscore) | 932 | if (dev->power.syscore) |
922 | return 0; | 933 | return 0; |
@@ -940,7 +951,11 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) | |||
940 | callback = pm_noirq_op(dev->driver->pm, state); | 951 | callback = pm_noirq_op(dev->driver->pm, state); |
941 | } | 952 | } |
942 | 953 | ||
943 | return dpm_run_callback(callback, dev, state, info); | 954 | error = dpm_run_callback(callback, dev, state, info); |
955 | if (!error) | ||
956 | dev->power.is_noirq_suspended = true; | ||
957 | |||
958 | return error; | ||
944 | } | 959 | } |
945 | 960 | ||
946 | /** | 961 | /** |
@@ -1003,6 +1018,7 @@ static int device_suspend_late(struct device *dev, pm_message_t state) | |||
1003 | { | 1018 | { |
1004 | pm_callback_t callback = NULL; | 1019 | pm_callback_t callback = NULL; |
1005 | char *info = NULL; | 1020 | char *info = NULL; |
1021 | int error; | ||
1006 | 1022 | ||
1007 | __pm_runtime_disable(dev, false); | 1023 | __pm_runtime_disable(dev, false); |
1008 | 1024 | ||
@@ -1028,7 +1044,11 @@ static int device_suspend_late(struct device *dev, pm_message_t state) | |||
1028 | callback = pm_late_early_op(dev->driver->pm, state); | 1044 | callback = pm_late_early_op(dev->driver->pm, state); |
1029 | } | 1045 | } |
1030 | 1046 | ||
1031 | return dpm_run_callback(callback, dev, state, info); | 1047 | error = dpm_run_callback(callback, dev, state, info); |
1048 | if (!error) | ||
1049 | dev->power.is_late_suspended = true; | ||
1050 | |||
1051 | return error; | ||
1032 | } | 1052 | } |
1033 | 1053 | ||
1034 | /** | 1054 | /** |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 8c6583a53a06..f23a4f1c1bfb 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -542,6 +542,8 @@ struct dev_pm_info { | |||
542 | unsigned int async_suspend:1; | 542 | unsigned int async_suspend:1; |
543 | bool is_prepared:1; /* Owned by the PM core */ | 543 | bool is_prepared:1; /* Owned by the PM core */ |
544 | bool is_suspended:1; /* Ditto */ | 544 | bool is_suspended:1; /* Ditto */ |
545 | bool is_noirq_suspended:1; | ||
546 | bool is_late_suspended:1; | ||
545 | bool ignore_children:1; | 547 | bool ignore_children:1; |
546 | bool early_init:1; /* Owned by the PM core */ | 548 | bool early_init:1; /* Owned by the PM core */ |
547 | spinlock_t lock; | 549 | spinlock_t lock; |