aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-06-03 17:11:42 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-06-03 17:11:42 -0400
commita392f7d4afb850934851fde5a8e298912650a6b8 (patch)
treeed9901ba019615f6911c0f9f1a3af180b243bc8f
parentf58c41cc0427115e3d750ec090020892acf0fb9c (diff)
parent4cf563c5d97c83d4b2fb3a778dd7d5e362cc3e34 (diff)
Merge branch 'acpi-pm'
* acpi-pm: ACPI / PM: Export rest of the subsys PM callbacks ACPI / PM: Avoid resuming devices in ACPI PM domain during system suspend ACPI / PM: Hold ACPI scan lock over the "freeze" sleep state ACPI / PM: Export acpi_target_system_state() to modules
-rw-r--r--drivers/acpi/device_pm.c46
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/acpi/sleep.c19
-rw-r--r--include/acpi/acpi_bus.h3
-rw-r--r--include/linux/acpi.h6
-rw-r--r--include/linux/suspend.h7
-rw-r--r--kernel/power/suspend.c15
7 files changed, 92 insertions, 8 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index d047739f3380..49a51277f81d 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -900,18 +900,47 @@ EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
900 */ 900 */
901int acpi_subsys_prepare(struct device *dev) 901int acpi_subsys_prepare(struct device *dev)
902{ 902{
903 /* 903 struct acpi_device *adev = ACPI_COMPANION(dev);
904 * Devices having power.ignore_children set may still be necessary for 904 u32 sys_target;
905 * suspending their children in the next phase of device suspend. 905 int ret, state;
906 */ 906
907 if (dev->power.ignore_children) 907 ret = pm_generic_prepare(dev);
908 pm_runtime_resume(dev); 908 if (ret < 0)
909 return ret;
910
911 if (!adev || !pm_runtime_suspended(dev)
912 || device_may_wakeup(dev) != !!adev->wakeup.prepare_count)
913 return 0;
914
915 sys_target = acpi_target_system_state();
916 if (sys_target == ACPI_STATE_S0)
917 return 1;
909 918
910 return pm_generic_prepare(dev); 919 if (adev->power.flags.dsw_present)
920 return 0;
921
922 ret = acpi_dev_pm_get_state(dev, adev, sys_target, NULL, &state);
923 return !ret && state == adev->power.state;
911} 924}
912EXPORT_SYMBOL_GPL(acpi_subsys_prepare); 925EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
913 926
914/** 927/**
928 * acpi_subsys_complete - Finalize device's resume during system resume.
929 * @dev: Device to handle.
930 */
931void acpi_subsys_complete(struct device *dev)
932{
933 /*
934 * If the device had been runtime-suspended before the system went into
935 * the sleep state it is going out of and it has never been resumed till
936 * now, resume it in case the firmware powered it up.
937 */
938 if (dev->power.direct_complete)
939 pm_request_resume(dev);
940}
941EXPORT_SYMBOL_GPL(acpi_subsys_complete);
942
943/**
915 * acpi_subsys_suspend - Run the device driver's suspend callback. 944 * acpi_subsys_suspend - Run the device driver's suspend callback.
916 * @dev: Device to handle. 945 * @dev: Device to handle.
917 * 946 *
@@ -923,6 +952,7 @@ int acpi_subsys_suspend(struct device *dev)
923 pm_runtime_resume(dev); 952 pm_runtime_resume(dev);
924 return pm_generic_suspend(dev); 953 return pm_generic_suspend(dev);
925} 954}
955EXPORT_SYMBOL_GPL(acpi_subsys_suspend);
926 956
927/** 957/**
928 * acpi_subsys_suspend_late - Suspend device using ACPI. 958 * acpi_subsys_suspend_late - Suspend device using ACPI.
@@ -968,6 +998,7 @@ int acpi_subsys_freeze(struct device *dev)
968 pm_runtime_resume(dev); 998 pm_runtime_resume(dev);
969 return pm_generic_freeze(dev); 999 return pm_generic_freeze(dev);
970} 1000}
1001EXPORT_SYMBOL_GPL(acpi_subsys_freeze);
971 1002
972#endif /* CONFIG_PM_SLEEP */ 1003#endif /* CONFIG_PM_SLEEP */
973 1004
@@ -979,6 +1010,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
979#endif 1010#endif
980#ifdef CONFIG_PM_SLEEP 1011#ifdef CONFIG_PM_SLEEP
981 .prepare = acpi_subsys_prepare, 1012 .prepare = acpi_subsys_prepare,
1013 .complete = acpi_subsys_complete,
982 .suspend = acpi_subsys_suspend, 1014 .suspend = acpi_subsys_suspend,
983 .suspend_late = acpi_subsys_suspend_late, 1015 .suspend_late = acpi_subsys_suspend_late,
984 .resume_early = acpi_subsys_resume_early, 1016 .resume_early = acpi_subsys_resume_early,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index db5fc6f9628e..31c99f7148d0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1551,9 +1551,13 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1551 */ 1551 */
1552 if (acpi_has_method(device->handle, "_PSC")) 1552 if (acpi_has_method(device->handle, "_PSC"))
1553 device->power.flags.explicit_get = 1; 1553 device->power.flags.explicit_get = 1;
1554
1554 if (acpi_has_method(device->handle, "_IRC")) 1555 if (acpi_has_method(device->handle, "_IRC"))
1555 device->power.flags.inrush_current = 1; 1556 device->power.flags.inrush_current = 1;
1556 1557
1558 if (acpi_has_method(device->handle, "_DSW"))
1559 device->power.flags.dsw_present = 1;
1560
1557 /* 1561 /*
1558 * Enumerate supported power management states 1562 * Enumerate supported power management states
1559 */ 1563 */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index c40fb2e81bbc..c11e3795431b 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -89,6 +89,7 @@ u32 acpi_target_system_state(void)
89{ 89{
90 return acpi_target_sleep_state; 90 return acpi_target_sleep_state;
91} 91}
92EXPORT_SYMBOL_GPL(acpi_target_system_state);
92 93
93static bool pwr_btn_event_pending; 94static bool pwr_btn_event_pending;
94 95
@@ -611,6 +612,22 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {
611 .recover = acpi_pm_finish, 612 .recover = acpi_pm_finish,
612}; 613};
613 614
615static int acpi_freeze_begin(void)
616{
617 acpi_scan_lock_acquire();
618 return 0;
619}
620
621static void acpi_freeze_end(void)
622{
623 acpi_scan_lock_release();
624}
625
626static const struct platform_freeze_ops acpi_freeze_ops = {
627 .begin = acpi_freeze_begin,
628 .end = acpi_freeze_end,
629};
630
614static void acpi_sleep_suspend_setup(void) 631static void acpi_sleep_suspend_setup(void)
615{ 632{
616 int i; 633 int i;
@@ -621,7 +638,9 @@ static void acpi_sleep_suspend_setup(void)
621 638
622 suspend_set_ops(old_suspend_ordering ? 639 suspend_set_ops(old_suspend_ordering ?
623 &acpi_suspend_ops_old : &acpi_suspend_ops); 640 &acpi_suspend_ops_old : &acpi_suspend_ops);
641 freeze_set_ops(&acpi_freeze_ops);
624} 642}
643
625#else /* !CONFIG_SUSPEND */ 644#else /* !CONFIG_SUSPEND */
626static inline void acpi_sleep_suspend_setup(void) {} 645static inline void acpi_sleep_suspend_setup(void) {}
627#endif /* !CONFIG_SUSPEND */ 646#endif /* !CONFIG_SUSPEND */
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index d2006ca31dba..fb6e00dcce74 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -261,7 +261,8 @@ struct acpi_device_power_flags {
261 u32 inrush_current:1; /* Serialize Dx->D0 */ 261 u32 inrush_current:1; /* Serialize Dx->D0 */
262 u32 power_removed:1; /* Optimize Dx->D0 */ 262 u32 power_removed:1; /* Optimize Dx->D0 */
263 u32 ignore_parent:1; /* Power is independent of parent power state */ 263 u32 ignore_parent:1; /* Power is independent of parent power state */
264 u32 reserved:27; 264 u32 dsw_present:1; /* _DSW present? */
265 u32 reserved:26;
265}; 266};
266 267
267struct acpi_device_power_state { 268struct acpi_device_power_state {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 0e2569031a6f..2ecdfcf98c0f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -555,14 +555,20 @@ static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
555int acpi_dev_suspend_late(struct device *dev); 555int acpi_dev_suspend_late(struct device *dev);
556int acpi_dev_resume_early(struct device *dev); 556int acpi_dev_resume_early(struct device *dev);
557int acpi_subsys_prepare(struct device *dev); 557int acpi_subsys_prepare(struct device *dev);
558void acpi_subsys_complete(struct device *dev);
558int acpi_subsys_suspend_late(struct device *dev); 559int acpi_subsys_suspend_late(struct device *dev);
559int acpi_subsys_resume_early(struct device *dev); 560int acpi_subsys_resume_early(struct device *dev);
561int acpi_subsys_suspend(struct device *dev);
562int acpi_subsys_freeze(struct device *dev);
560#else 563#else
561static inline int acpi_dev_suspend_late(struct device *dev) { return 0; } 564static inline int acpi_dev_suspend_late(struct device *dev) { return 0; }
562static inline int acpi_dev_resume_early(struct device *dev) { return 0; } 565static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
563static inline int acpi_subsys_prepare(struct device *dev) { return 0; } 566static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
567static inline void acpi_subsys_complete(struct device *dev) {}
564static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; } 568static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
565static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } 569static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
570static inline int acpi_subsys_suspend(struct device *dev) { return 0; }
571static inline int acpi_subsys_freeze(struct device *dev) { return 0; }
566#endif 572#endif
567 573
568#if defined(CONFIG_ACPI) && defined(CONFIG_PM) 574#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index f73cabf59012..91d66fd8dce1 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -187,6 +187,11 @@ struct platform_suspend_ops {
187 void (*recover)(void); 187 void (*recover)(void);
188}; 188};
189 189
190struct platform_freeze_ops {
191 int (*begin)(void);
192 void (*end)(void);
193};
194
190#ifdef CONFIG_SUSPEND 195#ifdef CONFIG_SUSPEND
191/** 196/**
192 * suspend_set_ops - set platform dependent suspend operations 197 * suspend_set_ops - set platform dependent suspend operations
@@ -194,6 +199,7 @@ struct platform_suspend_ops {
194 */ 199 */
195extern void suspend_set_ops(const struct platform_suspend_ops *ops); 200extern void suspend_set_ops(const struct platform_suspend_ops *ops);
196extern int suspend_valid_only_mem(suspend_state_t state); 201extern int suspend_valid_only_mem(suspend_state_t state);
202extern void freeze_set_ops(const struct platform_freeze_ops *ops);
197extern void freeze_wake(void); 203extern void freeze_wake(void);
198 204
199/** 205/**
@@ -220,6 +226,7 @@ extern int pm_suspend(suspend_state_t state);
220 226
221static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} 227static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
222static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } 228static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
229static inline void freeze_set_ops(const struct platform_freeze_ops *ops) {}
223static inline void freeze_wake(void) {} 230static inline void freeze_wake(void) {}
224#endif /* !CONFIG_SUSPEND */ 231#endif /* !CONFIG_SUSPEND */
225 232
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 338a6f147974..963e6d0f050b 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -38,6 +38,7 @@ struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = {
38}; 38};
39 39
40static const struct platform_suspend_ops *suspend_ops; 40static const struct platform_suspend_ops *suspend_ops;
41static const struct platform_freeze_ops *freeze_ops;
41 42
42static bool need_suspend_ops(suspend_state_t state) 43static bool need_suspend_ops(suspend_state_t state)
43{ 44{
@@ -47,6 +48,13 @@ static bool need_suspend_ops(suspend_state_t state)
47static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head); 48static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);
48static bool suspend_freeze_wake; 49static bool suspend_freeze_wake;
49 50
51void freeze_set_ops(const struct platform_freeze_ops *ops)
52{
53 lock_system_sleep();
54 freeze_ops = ops;
55 unlock_system_sleep();
56}
57
50static void freeze_begin(void) 58static void freeze_begin(void)
51{ 59{
52 suspend_freeze_wake = false; 60 suspend_freeze_wake = false;
@@ -291,6 +299,10 @@ int suspend_devices_and_enter(suspend_state_t state)
291 error = suspend_ops->begin(state); 299 error = suspend_ops->begin(state);
292 if (error) 300 if (error)
293 goto Close; 301 goto Close;
302 } else if (state == PM_SUSPEND_FREEZE && freeze_ops->begin) {
303 error = freeze_ops->begin();
304 if (error)
305 goto Close;
294 } 306 }
295 suspend_console(); 307 suspend_console();
296 suspend_test_start(); 308 suspend_test_start();
@@ -316,6 +328,9 @@ int suspend_devices_and_enter(suspend_state_t state)
316 Close: 328 Close:
317 if (need_suspend_ops(state) && suspend_ops->end) 329 if (need_suspend_ops(state) && suspend_ops->end)
318 suspend_ops->end(); 330 suspend_ops->end();
331 else if (state == PM_SUSPEND_FREEZE && freeze_ops->end)
332 freeze_ops->end();
333
319 trace_machine_suspend(PWR_EVENT_EXIT); 334 trace_machine_suspend(PWR_EVENT_EXIT);
320 return error; 335 return error;
321 336