diff options
40 files changed, 691 insertions, 421 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power index 7628cd1bc36a..8ffbc25376a0 100644 --- a/Documentation/ABI/testing/sysfs-devices-power +++ b/Documentation/ABI/testing/sysfs-devices-power | |||
@@ -29,9 +29,8 @@ Description: | |||
29 | "disabled" to it. | 29 | "disabled" to it. |
30 | 30 | ||
31 | For the devices that are not capable of generating system wakeup | 31 | For the devices that are not capable of generating system wakeup |
32 | events this file contains "\n". In that cases the user space | 32 | events this file is not present. In that case the device cannot |
33 | cannot modify the contents of this file and the device cannot be | 33 | be enabled to wake up the system from sleep states. |
34 | enabled to wake up the system. | ||
35 | 34 | ||
36 | What: /sys/devices/.../power/control | 35 | What: /sys/devices/.../power/control |
37 | Date: January 2009 | 36 | Date: January 2009 |
@@ -85,7 +84,7 @@ Description: | |||
85 | The /sys/devices/.../wakeup_count attribute contains the number | 84 | The /sys/devices/.../wakeup_count attribute contains the number |
86 | of signaled wakeup events associated with the device. This | 85 | of signaled wakeup events associated with the device. This |
87 | attribute is read-only. If the device is not enabled to wake up | 86 | attribute is read-only. If the device is not enabled to wake up |
88 | the system from sleep states, this attribute is empty. | 87 | the system from sleep states, this attribute is not present. |
89 | 88 | ||
90 | What: /sys/devices/.../power/wakeup_active_count | 89 | What: /sys/devices/.../power/wakeup_active_count |
91 | Date: September 2010 | 90 | Date: September 2010 |
@@ -95,7 +94,7 @@ Description: | |||
95 | number of times the processing of wakeup events associated with | 94 | number of times the processing of wakeup events associated with |
96 | the device was completed (at the kernel level). This attribute | 95 | the device was completed (at the kernel level). This attribute |
97 | is read-only. If the device is not enabled to wake up the | 96 | is read-only. If the device is not enabled to wake up the |
98 | system from sleep states, this attribute is empty. | 97 | system from sleep states, this attribute is not present. |
99 | 98 | ||
100 | What: /sys/devices/.../power/wakeup_hit_count | 99 | What: /sys/devices/.../power/wakeup_hit_count |
101 | Date: September 2010 | 100 | Date: September 2010 |
@@ -105,7 +104,8 @@ Description: | |||
105 | number of times the processing of a wakeup event associated with | 104 | number of times the processing of a wakeup event associated with |
106 | the device might prevent the system from entering a sleep state. | 105 | the device might prevent the system from entering a sleep state. |
107 | This attribute is read-only. If the device is not enabled to | 106 | This attribute is read-only. If the device is not enabled to |
108 | wake up the system from sleep states, this attribute is empty. | 107 | wake up the system from sleep states, this attribute is not |
108 | present. | ||
109 | 109 | ||
110 | What: /sys/devices/.../power/wakeup_active | 110 | What: /sys/devices/.../power/wakeup_active |
111 | Date: September 2010 | 111 | Date: September 2010 |
@@ -115,7 +115,7 @@ Description: | |||
115 | or 0, depending on whether or not a wakeup event associated with | 115 | or 0, depending on whether or not a wakeup event associated with |
116 | the device is being processed (1). This attribute is read-only. | 116 | the device is being processed (1). This attribute is read-only. |
117 | If the device is not enabled to wake up the system from sleep | 117 | If the device is not enabled to wake up the system from sleep |
118 | states, this attribute is empty. | 118 | states, this attribute is not present. |
119 | 119 | ||
120 | What: /sys/devices/.../power/wakeup_total_time_ms | 120 | What: /sys/devices/.../power/wakeup_total_time_ms |
121 | Date: September 2010 | 121 | Date: September 2010 |
@@ -125,7 +125,7 @@ Description: | |||
125 | the total time of processing wakeup events associated with the | 125 | the total time of processing wakeup events associated with the |
126 | device, in milliseconds. This attribute is read-only. If the | 126 | device, in milliseconds. This attribute is read-only. If the |
127 | device is not enabled to wake up the system from sleep states, | 127 | device is not enabled to wake up the system from sleep states, |
128 | this attribute is empty. | 128 | this attribute is not present. |
129 | 129 | ||
130 | What: /sys/devices/.../power/wakeup_max_time_ms | 130 | What: /sys/devices/.../power/wakeup_max_time_ms |
131 | Date: September 2010 | 131 | Date: September 2010 |
@@ -135,7 +135,7 @@ Description: | |||
135 | the maximum time of processing a single wakeup event associated | 135 | the maximum time of processing a single wakeup event associated |
136 | with the device, in milliseconds. This attribute is read-only. | 136 | with the device, in milliseconds. This attribute is read-only. |
137 | If the device is not enabled to wake up the system from sleep | 137 | If the device is not enabled to wake up the system from sleep |
138 | states, this attribute is empty. | 138 | states, this attribute is not present. |
139 | 139 | ||
140 | What: /sys/devices/.../power/wakeup_last_time_ms | 140 | What: /sys/devices/.../power/wakeup_last_time_ms |
141 | Date: September 2010 | 141 | Date: September 2010 |
@@ -146,7 +146,7 @@ Description: | |||
146 | signaling the last wakeup event associated with the device, in | 146 | signaling the last wakeup event associated with the device, in |
147 | milliseconds. This attribute is read-only. If the device is | 147 | milliseconds. This attribute is read-only. If the device is |
148 | not enabled to wake up the system from sleep states, this | 148 | not enabled to wake up the system from sleep states, this |
149 | attribute is empty. | 149 | attribute is not present. |
150 | 150 | ||
151 | What: /sys/devices/.../power/autosuspend_delay_ms | 151 | What: /sys/devices/.../power/autosuspend_delay_ms |
152 | Date: September 2010 | 152 | Date: September 2010 |
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 57080cd74575..f023ba6bba62 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | Device Power Management | 1 | Device Power Management |
2 | 2 | ||
3 | Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | 3 | Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. |
4 | Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu> | 4 | Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu> |
5 | 5 | ||
6 | 6 | ||
@@ -159,18 +159,18 @@ matter, and the kernel is responsible for keeping track of it. By contrast, | |||
159 | whether or not a wakeup-capable device should issue wakeup events is a policy | 159 | whether or not a wakeup-capable device should issue wakeup events is a policy |
160 | decision, and it is managed by user space through a sysfs attribute: the | 160 | decision, and it is managed by user space through a sysfs attribute: the |
161 | power/wakeup file. User space can write the strings "enabled" or "disabled" to | 161 | power/wakeup file. User space can write the strings "enabled" or "disabled" to |
162 | set or clear the should_wakeup flag, respectively. Reads from the file will | 162 | set or clear the "should_wakeup" flag, respectively. This file is only present |
163 | return the corresponding string if can_wakeup is true, but if can_wakeup is | 163 | for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set) |
164 | false then reads will return an empty string, to indicate that the device | 164 | and is created (or removed) by device_set_wakeup_capable(). Reads from the |
165 | doesn't support wakeup events. (But even though the file appears empty, writes | 165 | file will return the corresponding string. |
166 | will still affect the should_wakeup flag.) | ||
167 | 166 | ||
168 | The device_may_wakeup() routine returns true only if both flags are set. | 167 | The device_may_wakeup() routine returns true only if both flags are set. |
169 | Drivers should check this routine when putting devices in a low-power state | 168 | This information is used by subsystems, like the PCI bus type code, to see |
170 | during a system sleep transition, to see whether or not to enable the devices' | 169 | whether or not to enable the devices' wakeup mechanisms. If device wakeup |
171 | wakeup mechanisms. However for runtime power management, wakeup events should | 170 | mechanisms are enabled or disabled directly by drivers, they also should use |
172 | be enabled whenever the device and driver both support them, regardless of the | 171 | device_may_wakeup() to decide what to do during a system sleep transition. |
173 | should_wakeup flag. | 172 | However for runtime power management, wakeup events should be enabled whenever |
173 | the device and driver both support them, regardless of the should_wakeup flag. | ||
174 | 174 | ||
175 | 175 | ||
176 | /sys/devices/.../power/control files | 176 | /sys/devices/.../power/control files |
@@ -249,23 +249,18 @@ various phases always run after tasks have been frozen and before they are | |||
249 | unfrozen. Furthermore, the *_noirq phases run at a time when IRQ handlers have | 249 | unfrozen. Furthermore, the *_noirq phases run at a time when IRQ handlers have |
250 | been disabled (except for those marked with the IRQ_WAKEUP flag). | 250 | been disabled (except for those marked with the IRQ_WAKEUP flag). |
251 | 251 | ||
252 | Most phases use bus, type, and class callbacks (that is, methods defined in | 252 | All phases use bus, type, or class callbacks (that is, methods defined in |
253 | dev->bus->pm, dev->type->pm, and dev->class->pm). The prepare and complete | 253 | dev->bus->pm, dev->type->pm, or dev->class->pm). These callbacks are mutually |
254 | phases are exceptions; they use only bus callbacks. When multiple callbacks | 254 | exclusive, so if the device type provides a struct dev_pm_ops object pointed to |
255 | are used in a phase, they are invoked in the order: <class, type, bus> during | 255 | by its pm field (i.e. both dev->type and dev->type->pm are defined), the |
256 | power-down transitions and in the opposite order during power-up transitions. | 256 | callbacks included in that object (i.e. dev->type->pm) will be used. Otherwise, |
257 | For example, during the suspend phase the PM core invokes | 257 | if the class provides a struct dev_pm_ops object pointed to by its pm field |
258 | 258 | (i.e. both dev->class and dev->class->pm are defined), the PM core will use the | |
259 | dev->class->pm.suspend(dev); | 259 | callbacks from that object (i.e. dev->class->pm). Finally, if the pm fields of |
260 | dev->type->pm.suspend(dev); | 260 | both the device type and class objects are NULL (or those objects do not exist), |
261 | dev->bus->pm.suspend(dev); | 261 | the callbacks provided by the bus (that is, the callbacks from dev->bus->pm) |
262 | 262 | will be used (this allows device types to override callbacks provided by bus | |
263 | before moving on to the next device, whereas during the resume phase the core | 263 | types or classes if necessary). |
264 | invokes | ||
265 | |||
266 | dev->bus->pm.resume(dev); | ||
267 | dev->type->pm.resume(dev); | ||
268 | dev->class->pm.resume(dev); | ||
269 | 264 | ||
270 | These callbacks may in turn invoke device- or driver-specific methods stored in | 265 | These callbacks may in turn invoke device- or driver-specific methods stored in |
271 | dev->driver->pm, but they don't have to. | 266 | dev->driver->pm, but they don't have to. |
@@ -507,6 +502,49 @@ routines. Nevertheless, different callback pointers are used in case there is a | |||
507 | situation where it actually matters. | 502 | situation where it actually matters. |
508 | 503 | ||
509 | 504 | ||
505 | Device Power Domains | ||
506 | -------------------- | ||
507 | Sometimes devices share reference clocks or other power resources. In those | ||
508 | cases it generally is not possible to put devices into low-power states | ||
509 | individually. Instead, a set of devices sharing a power resource can be put | ||
510 | into a low-power state together at the same time by turning off the shared | ||
511 | power resource. Of course, they also need to be put into the full-power state | ||
512 | together, by turning the shared power resource on. A set of devices with this | ||
513 | property is often referred to as a power domain. | ||
514 | |||
515 | Support for power domains is provided through the pwr_domain field of struct | ||
516 | device. This field is a pointer to an object of type struct dev_power_domain, | ||
517 | defined in include/linux/pm.h, providing a set of power management callbacks | ||
518 | analogous to the subsystem-level and device driver callbacks that are executed | ||
519 | for the given device during all power transitions, in addition to the respective | ||
520 | subsystem-level callbacks. Specifically, the power domain "suspend" callbacks | ||
521 | (i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are | ||
522 | executed after the analogous subsystem-level callbacks, while the power domain | ||
523 | "resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore, | ||
524 | etc.) are executed before the analogous subsystem-level callbacks. Error codes | ||
525 | returned by the "suspend" and "resume" power domain callbacks are ignored. | ||
526 | |||
527 | Power domain ->runtime_idle() callback is executed before the subsystem-level | ||
528 | ->runtime_idle() callback and the result returned by it is not ignored. Namely, | ||
529 | if it returns error code, the subsystem-level ->runtime_idle() callback will not | ||
530 | be called and the helper function rpm_idle() executing it will return error | ||
531 | code. This mechanism is intended to help platforms where saving device state | ||
532 | is a time consuming operation and should only be carried out if all devices | ||
533 | in the power domain are idle, before turning off the shared power resource(s). | ||
534 | Namely, the power domain ->runtime_idle() callback may return error code until | ||
535 | the pm_runtime_idle() helper (or its asychronous version) has been called for | ||
536 | all devices in the power domain (it is recommended that the returned error code | ||
537 | be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle() | ||
538 | callback from being run prematurely. | ||
539 | |||
540 | The support for device power domains is only relevant to platforms needing to | ||
541 | use the same subsystem-level (e.g. platform bus type) and device driver power | ||
542 | management callbacks in many different power domain configurations and wanting | ||
543 | to avoid incorporating the support for power domains into the subsystem-level | ||
544 | callbacks. The other platforms need not implement it or take it into account | ||
545 | in any way. | ||
546 | |||
547 | |||
510 | System Devices | 548 | System Devices |
511 | -------------- | 549 | -------------- |
512 | System devices (sysdevs) follow a slightly different API, which can be found in | 550 | System devices (sysdevs) follow a slightly different API, which can be found in |
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index ffe55ffa540a..654097b130b4 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | Run-time Power Management Framework for I/O Devices | 1 | Run-time Power Management Framework for I/O Devices |
2 | 2 | ||
3 | (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | 3 | (C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. |
4 | (C) 2010 Alan Stern <stern@rowland.harvard.edu> | 4 | (C) 2010 Alan Stern <stern@rowland.harvard.edu> |
5 | 5 | ||
6 | 1. Introduction | 6 | 1. Introduction |
@@ -44,11 +44,12 @@ struct dev_pm_ops { | |||
44 | }; | 44 | }; |
45 | 45 | ||
46 | The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are | 46 | The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are |
47 | executed by the PM core for either the bus type, or device type (if the bus | 47 | executed by the PM core for either the device type, or the class (if the device |
48 | type's callback is not defined), or device class (if the bus type's and device | 48 | type's struct dev_pm_ops object does not exist), or the bus type (if the |
49 | type's callbacks are not defined) of given device. The bus type, device type | 49 | device type's and class' struct dev_pm_ops objects do not exist) of the given |
50 | and device class callbacks are referred to as subsystem-level callbacks in what | 50 | device (this allows device types to override callbacks provided by bus types or |
51 | follows. | 51 | classes if necessary). The bus type, device type and class callbacks are |
52 | referred to as subsystem-level callbacks in what follows. | ||
52 | 53 | ||
53 | By default, the callbacks are always invoked in process context with interrupts | 54 | By default, the callbacks are always invoked in process context with interrupts |
54 | enabled. However, subsystems can use the pm_runtime_irq_safe() helper function | 55 | enabled. However, subsystems can use the pm_runtime_irq_safe() helper function |
diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt index 34800cc521bf..4416b28630df 100644 --- a/Documentation/power/states.txt +++ b/Documentation/power/states.txt | |||
@@ -62,12 +62,12 @@ setup via another operating system for it to use. Despite the | |||
62 | inconvenience, this method requires minimal work by the kernel, since | 62 | inconvenience, this method requires minimal work by the kernel, since |
63 | the firmware will also handle restoring memory contents on resume. | 63 | the firmware will also handle restoring memory contents on resume. |
64 | 64 | ||
65 | For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap | 65 | For suspend-to-disk, a mechanism called 'swsusp' (Swap Suspend) is used |
66 | Suspend) is used to write memory contents to free swap space. | 66 | to write memory contents to free swap space. swsusp has some restrictive |
67 | swsusp has some restrictive requirements, but should work in most | 67 | requirements, but should work in most cases. Some, albeit outdated, |
68 | cases. Some, albeit outdated, documentation can be found in | 68 | documentation can be found in Documentation/power/swsusp.txt. |
69 | Documentation/power/swsusp.txt. Alternatively, userspace can do most | 69 | Alternatively, userspace can do most of the actual suspend to disk work, |
70 | of the actual suspend to disk work, see userland-swsusp.txt. | 70 | see userland-swsusp.txt. |
71 | 71 | ||
72 | Once memory state is written to disk, the system may either enter a | 72 | Once memory state is written to disk, the system may either enter a |
73 | low-power state (like ACPI S4), or it may simply power down. Powering | 73 | low-power state (like ACPI S4), or it may simply power down. Powering |
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 0e4f24c2a746..15f47f741983 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
@@ -227,6 +227,7 @@ | |||
227 | #include <linux/suspend.h> | 227 | #include <linux/suspend.h> |
228 | #include <linux/kthread.h> | 228 | #include <linux/kthread.h> |
229 | #include <linux/jiffies.h> | 229 | #include <linux/jiffies.h> |
230 | #include <linux/acpi.h> | ||
230 | 231 | ||
231 | #include <asm/system.h> | 232 | #include <asm/system.h> |
232 | #include <asm/uaccess.h> | 233 | #include <asm/uaccess.h> |
@@ -2331,12 +2332,11 @@ static int __init apm_init(void) | |||
2331 | apm_info.disabled = 1; | 2332 | apm_info.disabled = 1; |
2332 | return -ENODEV; | 2333 | return -ENODEV; |
2333 | } | 2334 | } |
2334 | if (pm_flags & PM_ACPI) { | 2335 | if (!acpi_disabled) { |
2335 | printk(KERN_NOTICE "apm: overridden by ACPI.\n"); | 2336 | printk(KERN_NOTICE "apm: overridden by ACPI.\n"); |
2336 | apm_info.disabled = 1; | 2337 | apm_info.disabled = 1; |
2337 | return -ENODEV; | 2338 | return -ENODEV; |
2338 | } | 2339 | } |
2339 | pm_flags |= PM_APM; | ||
2340 | 2340 | ||
2341 | /* | 2341 | /* |
2342 | * Set up the long jump entry point to the APM BIOS, which is called | 2342 | * Set up the long jump entry point to the APM BIOS, which is called |
@@ -2428,7 +2428,6 @@ static void __exit apm_exit(void) | |||
2428 | kthread_stop(kapmd_task); | 2428 | kthread_stop(kapmd_task); |
2429 | kapmd_task = NULL; | 2429 | kapmd_task = NULL; |
2430 | } | 2430 | } |
2431 | pm_flags &= ~PM_APM; | ||
2432 | } | 2431 | } |
2433 | 2432 | ||
2434 | module_init(apm_init); | 2433 | module_init(apm_init); |
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index e4343fe488ed..1c7121ba18ff 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig | |||
@@ -38,7 +38,7 @@ config XEN_MAX_DOMAIN_MEMORY | |||
38 | 38 | ||
39 | config XEN_SAVE_RESTORE | 39 | config XEN_SAVE_RESTORE |
40 | bool | 40 | bool |
41 | depends on XEN && PM | 41 | depends on XEN |
42 | default y | 42 | default y |
43 | 43 | ||
44 | config XEN_DEBUG_FS | 44 | config XEN_DEBUG_FS |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 2aa042a5da6d..3a17ca5fff6f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -7,7 +7,6 @@ menuconfig ACPI | |||
7 | depends on !IA64_HP_SIM | 7 | depends on !IA64_HP_SIM |
8 | depends on IA64 || X86 | 8 | depends on IA64 || X86 |
9 | depends on PCI | 9 | depends on PCI |
10 | depends on PM | ||
11 | select PNP | 10 | select PNP |
12 | default y | 11 | default y |
13 | help | 12 | help |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7ced61f39492..9749980ca6ca 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <acpi/acpi_bus.h> | 40 | #include <acpi/acpi_bus.h> |
41 | #include <acpi/acpi_drivers.h> | 41 | #include <acpi/acpi_drivers.h> |
42 | #include <linux/dmi.h> | 42 | #include <linux/dmi.h> |
43 | #include <linux/suspend.h> | ||
43 | 44 | ||
44 | #include "internal.h" | 45 | #include "internal.h" |
45 | 46 | ||
@@ -1006,8 +1007,7 @@ struct kobject *acpi_kobj; | |||
1006 | 1007 | ||
1007 | static int __init acpi_init(void) | 1008 | static int __init acpi_init(void) |
1008 | { | 1009 | { |
1009 | int result = 0; | 1010 | int result; |
1010 | |||
1011 | 1011 | ||
1012 | if (acpi_disabled) { | 1012 | if (acpi_disabled) { |
1013 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); | 1013 | printk(KERN_INFO PREFIX "Interpreter disabled.\n"); |
@@ -1022,29 +1022,18 @@ static int __init acpi_init(void) | |||
1022 | 1022 | ||
1023 | init_acpi_device_notify(); | 1023 | init_acpi_device_notify(); |
1024 | result = acpi_bus_init(); | 1024 | result = acpi_bus_init(); |
1025 | 1025 | if (result) { | |
1026 | if (!result) { | ||
1027 | pci_mmcfg_late_init(); | ||
1028 | if (!(pm_flags & PM_APM)) | ||
1029 | pm_flags |= PM_ACPI; | ||
1030 | else { | ||
1031 | printk(KERN_INFO PREFIX | ||
1032 | "APM is already active, exiting\n"); | ||
1033 | disable_acpi(); | ||
1034 | result = -ENODEV; | ||
1035 | } | ||
1036 | } else | ||
1037 | disable_acpi(); | 1026 | disable_acpi(); |
1038 | |||
1039 | if (acpi_disabled) | ||
1040 | return result; | 1027 | return result; |
1028 | } | ||
1041 | 1029 | ||
1030 | pci_mmcfg_late_init(); | ||
1042 | acpi_scan_init(); | 1031 | acpi_scan_init(); |
1043 | acpi_ec_init(); | 1032 | acpi_ec_init(); |
1044 | acpi_debugfs_init(); | 1033 | acpi_debugfs_init(); |
1045 | acpi_sleep_proc_init(); | 1034 | acpi_sleep_proc_init(); |
1046 | acpi_wakeup_device_init(); | 1035 | acpi_wakeup_device_init(); |
1047 | return result; | 1036 | return 0; |
1048 | } | 1037 | } |
1049 | 1038 | ||
1050 | subsys_initcall(acpi_init); | 1039 | subsys_initcall(acpi_init); |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d6a8cd14de2e..8ea092fad3f6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -585,7 +585,7 @@ int acpi_suspend(u32 acpi_state) | |||
585 | return -EINVAL; | 585 | return -EINVAL; |
586 | } | 586 | } |
587 | 587 | ||
588 | #ifdef CONFIG_PM_OPS | 588 | #ifdef CONFIG_PM |
589 | /** | 589 | /** |
590 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device | 590 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device |
591 | * in the system sleep state given by %acpi_target_sleep_state | 591 | * in the system sleep state given by %acpi_target_sleep_state |
@@ -671,7 +671,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
671 | *d_min_p = d_min; | 671 | *d_min_p = d_min; |
672 | return d_max; | 672 | return d_max; |
673 | } | 673 | } |
674 | #endif /* CONFIG_PM_OPS */ | 674 | #endif /* CONFIG_PM */ |
675 | 675 | ||
676 | #ifdef CONFIG_PM_SLEEP | 676 | #ifdef CONFIG_PM_SLEEP |
677 | /** | 677 | /** |
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 5f51c3b4451e..4c5701c15f53 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # Makefile for the Linux device tree | 1 | # Makefile for the Linux device tree |
2 | 2 | ||
3 | obj-y := core.o sys.o bus.o dd.o \ | 3 | obj-y := core.o sys.o bus.o dd.o syscore.o \ |
4 | driver.o class.o platform.o \ | 4 | driver.o class.o platform.o \ |
5 | cpu.o firmware.o init.o map.o devres.o \ | 5 | cpu.o firmware.o init.o map.o devres.o \ |
6 | attribute_container.o transport_class.o | 6 | attribute_container.o transport_class.o |
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index abe46edfe5b4..118c1b92a511 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -1,7 +1,6 @@ | |||
1 | obj-$(CONFIG_PM) += sysfs.o | 1 | obj-$(CONFIG_PM) += sysfs.o generic_ops.o |
2 | obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o |
3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o | 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o |
4 | obj-$(CONFIG_PM_OPS) += generic_ops.o | ||
5 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o | 4 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
6 | obj-$(CONFIG_PM_OPP) += opp.o | 5 | obj-$(CONFIG_PM_OPP) += opp.o |
7 | 6 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 83404973f97a..052dc53eef38 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -423,26 +423,22 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
423 | TRACE_DEVICE(dev); | 423 | TRACE_DEVICE(dev); |
424 | TRACE_RESUME(0); | 424 | TRACE_RESUME(0); |
425 | 425 | ||
426 | if (dev->bus && dev->bus->pm) { | 426 | if (dev->pwr_domain) { |
427 | pm_dev_dbg(dev, state, "EARLY "); | 427 | pm_dev_dbg(dev, state, "EARLY power domain "); |
428 | error = pm_noirq_op(dev, dev->bus->pm, state); | 428 | pm_noirq_op(dev, &dev->pwr_domain->ops, state); |
429 | if (error) | ||
430 | goto End; | ||
431 | } | 429 | } |
432 | 430 | ||
433 | if (dev->type && dev->type->pm) { | 431 | if (dev->type && dev->type->pm) { |
434 | pm_dev_dbg(dev, state, "EARLY type "); | 432 | pm_dev_dbg(dev, state, "EARLY type "); |
435 | error = pm_noirq_op(dev, dev->type->pm, state); | 433 | error = pm_noirq_op(dev, dev->type->pm, state); |
436 | if (error) | 434 | } else if (dev->class && dev->class->pm) { |
437 | goto End; | ||
438 | } | ||
439 | |||
440 | if (dev->class && dev->class->pm) { | ||
441 | pm_dev_dbg(dev, state, "EARLY class "); | 435 | pm_dev_dbg(dev, state, "EARLY class "); |
442 | error = pm_noirq_op(dev, dev->class->pm, state); | 436 | error = pm_noirq_op(dev, dev->class->pm, state); |
437 | } else if (dev->bus && dev->bus->pm) { | ||
438 | pm_dev_dbg(dev, state, "EARLY "); | ||
439 | error = pm_noirq_op(dev, dev->bus->pm, state); | ||
443 | } | 440 | } |
444 | 441 | ||
445 | End: | ||
446 | TRACE_RESUME(error); | 442 | TRACE_RESUME(error); |
447 | return error; | 443 | return error; |
448 | } | 444 | } |
@@ -518,36 +514,39 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
518 | 514 | ||
519 | dev->power.in_suspend = false; | 515 | dev->power.in_suspend = false; |
520 | 516 | ||
521 | if (dev->bus) { | 517 | if (dev->pwr_domain) { |
522 | if (dev->bus->pm) { | 518 | pm_dev_dbg(dev, state, "power domain "); |
523 | pm_dev_dbg(dev, state, ""); | 519 | pm_op(dev, &dev->pwr_domain->ops, state); |
524 | error = pm_op(dev, dev->bus->pm, state); | ||
525 | } else if (dev->bus->resume) { | ||
526 | pm_dev_dbg(dev, state, "legacy "); | ||
527 | error = legacy_resume(dev, dev->bus->resume); | ||
528 | } | ||
529 | if (error) | ||
530 | goto End; | ||
531 | } | 520 | } |
532 | 521 | ||
533 | if (dev->type) { | 522 | if (dev->type && dev->type->pm) { |
534 | if (dev->type->pm) { | 523 | pm_dev_dbg(dev, state, "type "); |
535 | pm_dev_dbg(dev, state, "type "); | 524 | error = pm_op(dev, dev->type->pm, state); |
536 | error = pm_op(dev, dev->type->pm, state); | 525 | goto End; |
537 | } | ||
538 | if (error) | ||
539 | goto End; | ||
540 | } | 526 | } |
541 | 527 | ||
542 | if (dev->class) { | 528 | if (dev->class) { |
543 | if (dev->class->pm) { | 529 | if (dev->class->pm) { |
544 | pm_dev_dbg(dev, state, "class "); | 530 | pm_dev_dbg(dev, state, "class "); |
545 | error = pm_op(dev, dev->class->pm, state); | 531 | error = pm_op(dev, dev->class->pm, state); |
532 | goto End; | ||
546 | } else if (dev->class->resume) { | 533 | } else if (dev->class->resume) { |
547 | pm_dev_dbg(dev, state, "legacy class "); | 534 | pm_dev_dbg(dev, state, "legacy class "); |
548 | error = legacy_resume(dev, dev->class->resume); | 535 | error = legacy_resume(dev, dev->class->resume); |
536 | goto End; | ||
549 | } | 537 | } |
550 | } | 538 | } |
539 | |||
540 | if (dev->bus) { | ||
541 | if (dev->bus->pm) { | ||
542 | pm_dev_dbg(dev, state, ""); | ||
543 | error = pm_op(dev, dev->bus->pm, state); | ||
544 | } else if (dev->bus->resume) { | ||
545 | pm_dev_dbg(dev, state, "legacy "); | ||
546 | error = legacy_resume(dev, dev->bus->resume); | ||
547 | } | ||
548 | } | ||
549 | |||
551 | End: | 550 | End: |
552 | device_unlock(dev); | 551 | device_unlock(dev); |
553 | complete_all(&dev->power.completion); | 552 | complete_all(&dev->power.completion); |
@@ -629,19 +628,23 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
629 | { | 628 | { |
630 | device_lock(dev); | 629 | device_lock(dev); |
631 | 630 | ||
632 | if (dev->class && dev->class->pm && dev->class->pm->complete) { | 631 | if (dev->pwr_domain && dev->pwr_domain->ops.complete) { |
633 | pm_dev_dbg(dev, state, "completing class "); | 632 | pm_dev_dbg(dev, state, "completing power domain "); |
634 | dev->class->pm->complete(dev); | 633 | dev->pwr_domain->ops.complete(dev); |
635 | } | 634 | } |
636 | 635 | ||
637 | if (dev->type && dev->type->pm && dev->type->pm->complete) { | 636 | if (dev->type && dev->type->pm) { |
638 | pm_dev_dbg(dev, state, "completing type "); | 637 | pm_dev_dbg(dev, state, "completing type "); |
639 | dev->type->pm->complete(dev); | 638 | if (dev->type->pm->complete) |
640 | } | 639 | dev->type->pm->complete(dev); |
641 | 640 | } else if (dev->class && dev->class->pm) { | |
642 | if (dev->bus && dev->bus->pm && dev->bus->pm->complete) { | 641 | pm_dev_dbg(dev, state, "completing class "); |
642 | if (dev->class->pm->complete) | ||
643 | dev->class->pm->complete(dev); | ||
644 | } else if (dev->bus && dev->bus->pm) { | ||
643 | pm_dev_dbg(dev, state, "completing "); | 645 | pm_dev_dbg(dev, state, "completing "); |
644 | dev->bus->pm->complete(dev); | 646 | if (dev->bus->pm->complete) |
647 | dev->bus->pm->complete(dev); | ||
645 | } | 648 | } |
646 | 649 | ||
647 | device_unlock(dev); | 650 | device_unlock(dev); |
@@ -669,7 +672,6 @@ static void dpm_complete(pm_message_t state) | |||
669 | mutex_unlock(&dpm_list_mtx); | 672 | mutex_unlock(&dpm_list_mtx); |
670 | 673 | ||
671 | device_complete(dev, state); | 674 | device_complete(dev, state); |
672 | pm_runtime_put_sync(dev); | ||
673 | 675 | ||
674 | mutex_lock(&dpm_list_mtx); | 676 | mutex_lock(&dpm_list_mtx); |
675 | put_device(dev); | 677 | put_device(dev); |
@@ -727,29 +729,31 @@ static pm_message_t resume_event(pm_message_t sleep_state) | |||
727 | */ | 729 | */ |
728 | static int device_suspend_noirq(struct device *dev, pm_message_t state) | 730 | static int device_suspend_noirq(struct device *dev, pm_message_t state) |
729 | { | 731 | { |
730 | int error = 0; | 732 | int error; |
731 | |||
732 | if (dev->class && dev->class->pm) { | ||
733 | pm_dev_dbg(dev, state, "LATE class "); | ||
734 | error = pm_noirq_op(dev, dev->class->pm, state); | ||
735 | if (error) | ||
736 | goto End; | ||
737 | } | ||
738 | 733 | ||
739 | if (dev->type && dev->type->pm) { | 734 | if (dev->type && dev->type->pm) { |
740 | pm_dev_dbg(dev, state, "LATE type "); | 735 | pm_dev_dbg(dev, state, "LATE type "); |
741 | error = pm_noirq_op(dev, dev->type->pm, state); | 736 | error = pm_noirq_op(dev, dev->type->pm, state); |
742 | if (error) | 737 | if (error) |
743 | goto End; | 738 | return error; |
744 | } | 739 | } else if (dev->class && dev->class->pm) { |
745 | 740 | pm_dev_dbg(dev, state, "LATE class "); | |
746 | if (dev->bus && dev->bus->pm) { | 741 | error = pm_noirq_op(dev, dev->class->pm, state); |
742 | if (error) | ||
743 | return error; | ||
744 | } else if (dev->bus && dev->bus->pm) { | ||
747 | pm_dev_dbg(dev, state, "LATE "); | 745 | pm_dev_dbg(dev, state, "LATE "); |
748 | error = pm_noirq_op(dev, dev->bus->pm, state); | 746 | error = pm_noirq_op(dev, dev->bus->pm, state); |
747 | if (error) | ||
748 | return error; | ||
749 | } | 749 | } |
750 | 750 | ||
751 | End: | 751 | if (dev->pwr_domain) { |
752 | return error; | 752 | pm_dev_dbg(dev, state, "LATE power domain "); |
753 | pm_noirq_op(dev, &dev->pwr_domain->ops, state); | ||
754 | } | ||
755 | |||
756 | return 0; | ||
753 | } | 757 | } |
754 | 758 | ||
755 | /** | 759 | /** |
@@ -836,25 +840,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
836 | goto End; | 840 | goto End; |
837 | } | 841 | } |
838 | 842 | ||
843 | if (dev->type && dev->type->pm) { | ||
844 | pm_dev_dbg(dev, state, "type "); | ||
845 | error = pm_op(dev, dev->type->pm, state); | ||
846 | goto Domain; | ||
847 | } | ||
848 | |||
839 | if (dev->class) { | 849 | if (dev->class) { |
840 | if (dev->class->pm) { | 850 | if (dev->class->pm) { |
841 | pm_dev_dbg(dev, state, "class "); | 851 | pm_dev_dbg(dev, state, "class "); |
842 | error = pm_op(dev, dev->class->pm, state); | 852 | error = pm_op(dev, dev->class->pm, state); |
853 | goto Domain; | ||
843 | } else if (dev->class->suspend) { | 854 | } else if (dev->class->suspend) { |
844 | pm_dev_dbg(dev, state, "legacy class "); | 855 | pm_dev_dbg(dev, state, "legacy class "); |
845 | error = legacy_suspend(dev, state, dev->class->suspend); | 856 | error = legacy_suspend(dev, state, dev->class->suspend); |
857 | goto Domain; | ||
846 | } | 858 | } |
847 | if (error) | ||
848 | goto End; | ||
849 | } | ||
850 | |||
851 | if (dev->type) { | ||
852 | if (dev->type->pm) { | ||
853 | pm_dev_dbg(dev, state, "type "); | ||
854 | error = pm_op(dev, dev->type->pm, state); | ||
855 | } | ||
856 | if (error) | ||
857 | goto End; | ||
858 | } | 859 | } |
859 | 860 | ||
860 | if (dev->bus) { | 861 | if (dev->bus) { |
@@ -867,6 +868,12 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
867 | } | 868 | } |
868 | } | 869 | } |
869 | 870 | ||
871 | Domain: | ||
872 | if (!error && dev->pwr_domain) { | ||
873 | pm_dev_dbg(dev, state, "power domain "); | ||
874 | pm_op(dev, &dev->pwr_domain->ops, state); | ||
875 | } | ||
876 | |||
870 | End: | 877 | End: |
871 | device_unlock(dev); | 878 | device_unlock(dev); |
872 | complete_all(&dev->power.completion); | 879 | complete_all(&dev->power.completion); |
@@ -957,27 +964,34 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
957 | 964 | ||
958 | device_lock(dev); | 965 | device_lock(dev); |
959 | 966 | ||
960 | if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { | 967 | if (dev->type && dev->type->pm) { |
968 | pm_dev_dbg(dev, state, "preparing type "); | ||
969 | if (dev->type->pm->prepare) | ||
970 | error = dev->type->pm->prepare(dev); | ||
971 | suspend_report_result(dev->type->pm->prepare, error); | ||
972 | if (error) | ||
973 | goto End; | ||
974 | } else if (dev->class && dev->class->pm) { | ||
975 | pm_dev_dbg(dev, state, "preparing class "); | ||
976 | if (dev->class->pm->prepare) | ||
977 | error = dev->class->pm->prepare(dev); | ||
978 | suspend_report_result(dev->class->pm->prepare, error); | ||
979 | if (error) | ||
980 | goto End; | ||
981 | } else if (dev->bus && dev->bus->pm) { | ||
961 | pm_dev_dbg(dev, state, "preparing "); | 982 | pm_dev_dbg(dev, state, "preparing "); |
962 | error = dev->bus->pm->prepare(dev); | 983 | if (dev->bus->pm->prepare) |
984 | error = dev->bus->pm->prepare(dev); | ||
963 | suspend_report_result(dev->bus->pm->prepare, error); | 985 | suspend_report_result(dev->bus->pm->prepare, error); |
964 | if (error) | 986 | if (error) |
965 | goto End; | 987 | goto End; |
966 | } | 988 | } |
967 | 989 | ||
968 | if (dev->type && dev->type->pm && dev->type->pm->prepare) { | 990 | if (dev->pwr_domain && dev->pwr_domain->ops.prepare) { |
969 | pm_dev_dbg(dev, state, "preparing type "); | 991 | pm_dev_dbg(dev, state, "preparing power domain "); |
970 | error = dev->type->pm->prepare(dev); | 992 | dev->pwr_domain->ops.prepare(dev); |
971 | suspend_report_result(dev->type->pm->prepare, error); | ||
972 | if (error) | ||
973 | goto End; | ||
974 | } | 993 | } |
975 | 994 | ||
976 | if (dev->class && dev->class->pm && dev->class->pm->prepare) { | ||
977 | pm_dev_dbg(dev, state, "preparing class "); | ||
978 | error = dev->class->pm->prepare(dev); | ||
979 | suspend_report_result(dev->class->pm->prepare, error); | ||
980 | } | ||
981 | End: | 995 | End: |
982 | device_unlock(dev); | 996 | device_unlock(dev); |
983 | 997 | ||
@@ -1005,12 +1019,9 @@ static int dpm_prepare(pm_message_t state) | |||
1005 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) | 1019 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) |
1006 | pm_wakeup_event(dev, 0); | 1020 | pm_wakeup_event(dev, 0); |
1007 | 1021 | ||
1008 | if (pm_wakeup_pending()) { | 1022 | pm_runtime_put_sync(dev); |
1009 | pm_runtime_put_sync(dev); | 1023 | error = pm_wakeup_pending() ? |
1010 | error = -EBUSY; | 1024 | -EBUSY : device_prepare(dev, state); |
1011 | } else { | ||
1012 | error = device_prepare(dev, state); | ||
1013 | } | ||
1014 | 1025 | ||
1015 | mutex_lock(&dpm_list_mtx); | 1026 | mutex_lock(&dpm_list_mtx); |
1016 | if (error) { | 1027 | if (error) { |
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index 2bb9b4cf59d7..56a6899f5e9e 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c | |||
@@ -222,7 +222,7 @@ int opp_get_opp_count(struct device *dev) | |||
222 | * opp_find_freq_exact() - search for an exact frequency | 222 | * opp_find_freq_exact() - search for an exact frequency |
223 | * @dev: device for which we do this operation | 223 | * @dev: device for which we do this operation |
224 | * @freq: frequency to search for | 224 | * @freq: frequency to search for |
225 | * @is_available: true/false - match for available opp | 225 | * @available: true/false - match for available opp |
226 | * | 226 | * |
227 | * Searches for exact match in the opp list and returns pointer to the matching | 227 | * Searches for exact match in the opp list and returns pointer to the matching |
228 | * opp if found, else returns ERR_PTR in case of error and should be handled | 228 | * opp if found, else returns ERR_PTR in case of error and should be handled |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 698dde742587..f2a25f18fde7 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -58,19 +58,18 @@ static inline void device_pm_move_last(struct device *dev) {} | |||
58 | * sysfs.c | 58 | * sysfs.c |
59 | */ | 59 | */ |
60 | 60 | ||
61 | extern int dpm_sysfs_add(struct device *); | 61 | extern int dpm_sysfs_add(struct device *dev); |
62 | extern void dpm_sysfs_remove(struct device *); | 62 | extern void dpm_sysfs_remove(struct device *dev); |
63 | extern void rpm_sysfs_remove(struct device *); | 63 | extern void rpm_sysfs_remove(struct device *dev); |
64 | extern int wakeup_sysfs_add(struct device *dev); | ||
65 | extern void wakeup_sysfs_remove(struct device *dev); | ||
64 | 66 | ||
65 | #else /* CONFIG_PM */ | 67 | #else /* CONFIG_PM */ |
66 | 68 | ||
67 | static inline int dpm_sysfs_add(struct device *dev) | 69 | static inline int dpm_sysfs_add(struct device *dev) { return 0; } |
68 | { | 70 | static inline void dpm_sysfs_remove(struct device *dev) {} |
69 | return 0; | 71 | static inline void rpm_sysfs_remove(struct device *dev) {} |
70 | } | 72 | static inline int wakeup_sysfs_add(struct device *dev) { return 0; } |
71 | 73 | static inline void wakeup_sysfs_remove(struct device *dev) {} | |
72 | static inline void dpm_sysfs_remove(struct device *dev) | ||
73 | { | ||
74 | } | ||
75 | 74 | ||
76 | #endif | 75 | #endif |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 42615b419dfb..54597c859ecb 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -168,6 +168,7 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
168 | static int rpm_idle(struct device *dev, int rpmflags) | 168 | static int rpm_idle(struct device *dev, int rpmflags) |
169 | { | 169 | { |
170 | int (*callback)(struct device *); | 170 | int (*callback)(struct device *); |
171 | int (*domain_callback)(struct device *); | ||
171 | int retval; | 172 | int retval; |
172 | 173 | ||
173 | retval = rpm_check_suspend_allowed(dev); | 174 | retval = rpm_check_suspend_allowed(dev); |
@@ -213,19 +214,28 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
213 | 214 | ||
214 | dev->power.idle_notification = true; | 215 | dev->power.idle_notification = true; |
215 | 216 | ||
216 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) | 217 | if (dev->type && dev->type->pm) |
217 | callback = dev->bus->pm->runtime_idle; | ||
218 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) | ||
219 | callback = dev->type->pm->runtime_idle; | 218 | callback = dev->type->pm->runtime_idle; |
220 | else if (dev->class && dev->class->pm) | 219 | else if (dev->class && dev->class->pm) |
221 | callback = dev->class->pm->runtime_idle; | 220 | callback = dev->class->pm->runtime_idle; |
221 | else if (dev->bus && dev->bus->pm) | ||
222 | callback = dev->bus->pm->runtime_idle; | ||
222 | else | 223 | else |
223 | callback = NULL; | 224 | callback = NULL; |
224 | 225 | ||
225 | if (callback) { | 226 | if (dev->pwr_domain) |
227 | domain_callback = dev->pwr_domain->ops.runtime_idle; | ||
228 | else | ||
229 | domain_callback = NULL; | ||
230 | |||
231 | if (callback || domain_callback) { | ||
226 | spin_unlock_irq(&dev->power.lock); | 232 | spin_unlock_irq(&dev->power.lock); |
227 | 233 | ||
228 | callback(dev); | 234 | if (domain_callback) |
235 | retval = domain_callback(dev); | ||
236 | |||
237 | if (!retval && callback) | ||
238 | callback(dev); | ||
229 | 239 | ||
230 | spin_lock_irq(&dev->power.lock); | 240 | spin_lock_irq(&dev->power.lock); |
231 | } | 241 | } |
@@ -372,12 +382,12 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
372 | 382 | ||
373 | __update_runtime_status(dev, RPM_SUSPENDING); | 383 | __update_runtime_status(dev, RPM_SUSPENDING); |
374 | 384 | ||
375 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) | 385 | if (dev->type && dev->type->pm) |
376 | callback = dev->bus->pm->runtime_suspend; | ||
377 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend) | ||
378 | callback = dev->type->pm->runtime_suspend; | 386 | callback = dev->type->pm->runtime_suspend; |
379 | else if (dev->class && dev->class->pm) | 387 | else if (dev->class && dev->class->pm) |
380 | callback = dev->class->pm->runtime_suspend; | 388 | callback = dev->class->pm->runtime_suspend; |
389 | else if (dev->bus && dev->bus->pm) | ||
390 | callback = dev->bus->pm->runtime_suspend; | ||
381 | else | 391 | else |
382 | callback = NULL; | 392 | callback = NULL; |
383 | 393 | ||
@@ -390,6 +400,8 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
390 | else | 400 | else |
391 | pm_runtime_cancel_pending(dev); | 401 | pm_runtime_cancel_pending(dev); |
392 | } else { | 402 | } else { |
403 | if (dev->pwr_domain) | ||
404 | rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev); | ||
393 | no_callback: | 405 | no_callback: |
394 | __update_runtime_status(dev, RPM_SUSPENDED); | 406 | __update_runtime_status(dev, RPM_SUSPENDED); |
395 | pm_runtime_deactivate_timer(dev); | 407 | pm_runtime_deactivate_timer(dev); |
@@ -569,12 +581,15 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
569 | 581 | ||
570 | __update_runtime_status(dev, RPM_RESUMING); | 582 | __update_runtime_status(dev, RPM_RESUMING); |
571 | 583 | ||
572 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) | 584 | if (dev->pwr_domain) |
573 | callback = dev->bus->pm->runtime_resume; | 585 | rpm_callback(dev->pwr_domain->ops.runtime_resume, dev); |
574 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) | 586 | |
587 | if (dev->type && dev->type->pm) | ||
575 | callback = dev->type->pm->runtime_resume; | 588 | callback = dev->type->pm->runtime_resume; |
576 | else if (dev->class && dev->class->pm) | 589 | else if (dev->class && dev->class->pm) |
577 | callback = dev->class->pm->runtime_resume; | 590 | callback = dev->class->pm->runtime_resume; |
591 | else if (dev->bus && dev->bus->pm) | ||
592 | callback = dev->bus->pm->runtime_resume; | ||
578 | else | 593 | else |
579 | callback = NULL; | 594 | callback = NULL; |
580 | 595 | ||
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 0b1e46bf3e56..fff49bee781d 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -431,26 +431,18 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr, | |||
431 | static DEVICE_ATTR(async, 0644, async_show, async_store); | 431 | static DEVICE_ATTR(async, 0644, async_show, async_store); |
432 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ | 432 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ |
433 | 433 | ||
434 | static struct attribute * power_attrs[] = { | 434 | static struct attribute *power_attrs[] = { |
435 | &dev_attr_wakeup.attr, | ||
436 | #ifdef CONFIG_PM_SLEEP | ||
437 | &dev_attr_wakeup_count.attr, | ||
438 | &dev_attr_wakeup_active_count.attr, | ||
439 | &dev_attr_wakeup_hit_count.attr, | ||
440 | &dev_attr_wakeup_active.attr, | ||
441 | &dev_attr_wakeup_total_time_ms.attr, | ||
442 | &dev_attr_wakeup_max_time_ms.attr, | ||
443 | &dev_attr_wakeup_last_time_ms.attr, | ||
444 | #endif | ||
445 | #ifdef CONFIG_PM_ADVANCED_DEBUG | 435 | #ifdef CONFIG_PM_ADVANCED_DEBUG |
436 | #ifdef CONFIG_PM_SLEEP | ||
446 | &dev_attr_async.attr, | 437 | &dev_attr_async.attr, |
438 | #endif | ||
447 | #ifdef CONFIG_PM_RUNTIME | 439 | #ifdef CONFIG_PM_RUNTIME |
448 | &dev_attr_runtime_status.attr, | 440 | &dev_attr_runtime_status.attr, |
449 | &dev_attr_runtime_usage.attr, | 441 | &dev_attr_runtime_usage.attr, |
450 | &dev_attr_runtime_active_kids.attr, | 442 | &dev_attr_runtime_active_kids.attr, |
451 | &dev_attr_runtime_enabled.attr, | 443 | &dev_attr_runtime_enabled.attr, |
452 | #endif | 444 | #endif |
453 | #endif | 445 | #endif /* CONFIG_PM_ADVANCED_DEBUG */ |
454 | NULL, | 446 | NULL, |
455 | }; | 447 | }; |
456 | static struct attribute_group pm_attr_group = { | 448 | static struct attribute_group pm_attr_group = { |
@@ -458,9 +450,26 @@ static struct attribute_group pm_attr_group = { | |||
458 | .attrs = power_attrs, | 450 | .attrs = power_attrs, |
459 | }; | 451 | }; |
460 | 452 | ||
461 | #ifdef CONFIG_PM_RUNTIME | 453 | static struct attribute *wakeup_attrs[] = { |
454 | #ifdef CONFIG_PM_SLEEP | ||
455 | &dev_attr_wakeup.attr, | ||
456 | &dev_attr_wakeup_count.attr, | ||
457 | &dev_attr_wakeup_active_count.attr, | ||
458 | &dev_attr_wakeup_hit_count.attr, | ||
459 | &dev_attr_wakeup_active.attr, | ||
460 | &dev_attr_wakeup_total_time_ms.attr, | ||
461 | &dev_attr_wakeup_max_time_ms.attr, | ||
462 | &dev_attr_wakeup_last_time_ms.attr, | ||
463 | #endif | ||
464 | NULL, | ||
465 | }; | ||
466 | static struct attribute_group pm_wakeup_attr_group = { | ||
467 | .name = power_group_name, | ||
468 | .attrs = wakeup_attrs, | ||
469 | }; | ||
462 | 470 | ||
463 | static struct attribute *runtime_attrs[] = { | 471 | static struct attribute *runtime_attrs[] = { |
472 | #ifdef CONFIG_PM_RUNTIME | ||
464 | #ifndef CONFIG_PM_ADVANCED_DEBUG | 473 | #ifndef CONFIG_PM_ADVANCED_DEBUG |
465 | &dev_attr_runtime_status.attr, | 474 | &dev_attr_runtime_status.attr, |
466 | #endif | 475 | #endif |
@@ -468,6 +477,7 @@ static struct attribute *runtime_attrs[] = { | |||
468 | &dev_attr_runtime_suspended_time.attr, | 477 | &dev_attr_runtime_suspended_time.attr, |
469 | &dev_attr_runtime_active_time.attr, | 478 | &dev_attr_runtime_active_time.attr, |
470 | &dev_attr_autosuspend_delay_ms.attr, | 479 | &dev_attr_autosuspend_delay_ms.attr, |
480 | #endif /* CONFIG_PM_RUNTIME */ | ||
471 | NULL, | 481 | NULL, |
472 | }; | 482 | }; |
473 | static struct attribute_group pm_runtime_attr_group = { | 483 | static struct attribute_group pm_runtime_attr_group = { |
@@ -480,35 +490,49 @@ int dpm_sysfs_add(struct device *dev) | |||
480 | int rc; | 490 | int rc; |
481 | 491 | ||
482 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); | 492 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); |
483 | if (rc == 0 && !dev->power.no_callbacks) { | 493 | if (rc) |
494 | return rc; | ||
495 | |||
496 | if (pm_runtime_callbacks_present(dev)) { | ||
484 | rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); | 497 | rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group); |
485 | if (rc) | 498 | if (rc) |
486 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 499 | goto err_out; |
500 | } | ||
501 | |||
502 | if (device_can_wakeup(dev)) { | ||
503 | rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); | ||
504 | if (rc) { | ||
505 | if (pm_runtime_callbacks_present(dev)) | ||
506 | sysfs_unmerge_group(&dev->kobj, | ||
507 | &pm_runtime_attr_group); | ||
508 | goto err_out; | ||
509 | } | ||
487 | } | 510 | } |
511 | return 0; | ||
512 | |||
513 | err_out: | ||
514 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
488 | return rc; | 515 | return rc; |
489 | } | 516 | } |
490 | 517 | ||
491 | void rpm_sysfs_remove(struct device *dev) | 518 | int wakeup_sysfs_add(struct device *dev) |
492 | { | 519 | { |
493 | sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); | 520 | return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); |
494 | } | 521 | } |
495 | 522 | ||
496 | void dpm_sysfs_remove(struct device *dev) | 523 | void wakeup_sysfs_remove(struct device *dev) |
497 | { | 524 | { |
498 | rpm_sysfs_remove(dev); | 525 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); |
499 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | ||
500 | } | 526 | } |
501 | 527 | ||
502 | #else /* CONFIG_PM_RUNTIME */ | 528 | void rpm_sysfs_remove(struct device *dev) |
503 | |||
504 | int dpm_sysfs_add(struct device * dev) | ||
505 | { | 529 | { |
506 | return sysfs_create_group(&dev->kobj, &pm_attr_group); | 530 | sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group); |
507 | } | 531 | } |
508 | 532 | ||
509 | void dpm_sysfs_remove(struct device * dev) | 533 | void dpm_sysfs_remove(struct device *dev) |
510 | { | 534 | { |
535 | rpm_sysfs_remove(dev); | ||
536 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); | ||
511 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 537 | sysfs_remove_group(&dev->kobj, &pm_attr_group); |
512 | } | 538 | } |
513 | |||
514 | #endif | ||
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index 9f4258df4cfd..c80e138b62fe 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void) | |||
112 | unsigned int val; | 112 | unsigned int val; |
113 | 113 | ||
114 | get_rtc_time(&time); | 114 | get_rtc_time(&time); |
115 | printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", | 115 | pr_info("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", |
116 | time.tm_hour, time.tm_min, time.tm_sec, | 116 | time.tm_hour, time.tm_min, time.tm_sec, |
117 | time.tm_mon + 1, time.tm_mday, time.tm_year % 100); | 117 | time.tm_mon + 1, time.tm_mday, time.tm_year % 100); |
118 | val = time.tm_year; /* 100 years */ | 118 | val = time.tm_year; /* 100 years */ |
@@ -179,7 +179,7 @@ static int show_file_hash(unsigned int value) | |||
179 | unsigned int hash = hash_string(lineno, file, FILEHASH); | 179 | unsigned int hash = hash_string(lineno, file, FILEHASH); |
180 | if (hash != value) | 180 | if (hash != value) |
181 | continue; | 181 | continue; |
182 | printk(" hash matches %s:%u\n", file, lineno); | 182 | pr_info(" hash matches %s:%u\n", file, lineno); |
183 | match++; | 183 | match++; |
184 | } | 184 | } |
185 | return match; | 185 | return match; |
@@ -255,7 +255,7 @@ static int late_resume_init(void) | |||
255 | val = val / FILEHASH; | 255 | val = val / FILEHASH; |
256 | dev = val /* % DEVHASH */; | 256 | dev = val /* % DEVHASH */; |
257 | 257 | ||
258 | printk(" Magic number: %d:%d:%d\n", user, file, dev); | 258 | pr_info(" Magic number: %d:%d:%d\n", user, file, dev); |
259 | show_file_hash(file); | 259 | show_file_hash(file); |
260 | show_dev_hash(dev); | 260 | show_dev_hash(dev); |
261 | return 0; | 261 | return 0; |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 8ec406d8f548..4573c83df6dd 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
@@ -24,12 +24,26 @@ | |||
24 | */ | 24 | */ |
25 | bool events_check_enabled; | 25 | bool events_check_enabled; |
26 | 26 | ||
27 | /* The counter of registered wakeup events. */ | 27 | /* |
28 | static atomic_t event_count = ATOMIC_INIT(0); | 28 | * Combined counters of registered wakeup events and wakeup events in progress. |
29 | /* A preserved old value of event_count. */ | 29 | * They need to be modified together atomically, so it's better to use one |
30 | * atomic variable to hold them both. | ||
31 | */ | ||
32 | static atomic_t combined_event_count = ATOMIC_INIT(0); | ||
33 | |||
34 | #define IN_PROGRESS_BITS (sizeof(int) * 4) | ||
35 | #define MAX_IN_PROGRESS ((1 << IN_PROGRESS_BITS) - 1) | ||
36 | |||
37 | static void split_counters(unsigned int *cnt, unsigned int *inpr) | ||
38 | { | ||
39 | unsigned int comb = atomic_read(&combined_event_count); | ||
40 | |||
41 | *cnt = (comb >> IN_PROGRESS_BITS); | ||
42 | *inpr = comb & MAX_IN_PROGRESS; | ||
43 | } | ||
44 | |||
45 | /* A preserved old value of the events counter. */ | ||
30 | static unsigned int saved_count; | 46 | static unsigned int saved_count; |
31 | /* The counter of wakeup events being processed. */ | ||
32 | static atomic_t events_in_progress = ATOMIC_INIT(0); | ||
33 | 47 | ||
34 | static DEFINE_SPINLOCK(events_lock); | 48 | static DEFINE_SPINLOCK(events_lock); |
35 | 49 | ||
@@ -228,6 +242,35 @@ int device_wakeup_disable(struct device *dev) | |||
228 | EXPORT_SYMBOL_GPL(device_wakeup_disable); | 242 | EXPORT_SYMBOL_GPL(device_wakeup_disable); |
229 | 243 | ||
230 | /** | 244 | /** |
245 | * device_set_wakeup_capable - Set/reset device wakeup capability flag. | ||
246 | * @dev: Device to handle. | ||
247 | * @capable: Whether or not @dev is capable of waking up the system from sleep. | ||
248 | * | ||
249 | * If @capable is set, set the @dev's power.can_wakeup flag and add its | ||
250 | * wakeup-related attributes to sysfs. Otherwise, unset the @dev's | ||
251 | * power.can_wakeup flag and remove its wakeup-related attributes from sysfs. | ||
252 | * | ||
253 | * This function may sleep and it can't be called from any context where | ||
254 | * sleeping is not allowed. | ||
255 | */ | ||
256 | void device_set_wakeup_capable(struct device *dev, bool capable) | ||
257 | { | ||
258 | if (!!dev->power.can_wakeup == !!capable) | ||
259 | return; | ||
260 | |||
261 | if (device_is_registered(dev)) { | ||
262 | if (capable) { | ||
263 | if (wakeup_sysfs_add(dev)) | ||
264 | return; | ||
265 | } else { | ||
266 | wakeup_sysfs_remove(dev); | ||
267 | } | ||
268 | } | ||
269 | dev->power.can_wakeup = capable; | ||
270 | } | ||
271 | EXPORT_SYMBOL_GPL(device_set_wakeup_capable); | ||
272 | |||
273 | /** | ||
231 | * device_init_wakeup - Device wakeup initialization. | 274 | * device_init_wakeup - Device wakeup initialization. |
232 | * @dev: Device to handle. | 275 | * @dev: Device to handle. |
233 | * @enable: Whether or not to enable @dev as a wakeup device. | 276 | * @enable: Whether or not to enable @dev as a wakeup device. |
@@ -307,7 +350,8 @@ static void wakeup_source_activate(struct wakeup_source *ws) | |||
307 | ws->timer_expires = jiffies; | 350 | ws->timer_expires = jiffies; |
308 | ws->last_time = ktime_get(); | 351 | ws->last_time = ktime_get(); |
309 | 352 | ||
310 | atomic_inc(&events_in_progress); | 353 | /* Increment the counter of events in progress. */ |
354 | atomic_inc(&combined_event_count); | ||
311 | } | 355 | } |
312 | 356 | ||
313 | /** | 357 | /** |
@@ -394,14 +438,10 @@ static void wakeup_source_deactivate(struct wakeup_source *ws) | |||
394 | del_timer(&ws->timer); | 438 | del_timer(&ws->timer); |
395 | 439 | ||
396 | /* | 440 | /* |
397 | * event_count has to be incremented before events_in_progress is | 441 | * Increment the counter of registered wakeup events and decrement the |
398 | * modified, so that the callers of pm_check_wakeup_events() and | 442 | * couter of wakeup events in progress simultaneously. |
399 | * pm_save_wakeup_count() don't see the old value of event_count and | ||
400 | * events_in_progress equal to zero at the same time. | ||
401 | */ | 443 | */ |
402 | atomic_inc(&event_count); | 444 | atomic_add(MAX_IN_PROGRESS, &combined_event_count); |
403 | smp_mb__before_atomic_dec(); | ||
404 | atomic_dec(&events_in_progress); | ||
405 | } | 445 | } |
406 | 446 | ||
407 | /** | 447 | /** |
@@ -556,8 +596,10 @@ bool pm_wakeup_pending(void) | |||
556 | 596 | ||
557 | spin_lock_irqsave(&events_lock, flags); | 597 | spin_lock_irqsave(&events_lock, flags); |
558 | if (events_check_enabled) { | 598 | if (events_check_enabled) { |
559 | ret = ((unsigned int)atomic_read(&event_count) != saved_count) | 599 | unsigned int cnt, inpr; |
560 | || atomic_read(&events_in_progress); | 600 | |
601 | split_counters(&cnt, &inpr); | ||
602 | ret = (cnt != saved_count || inpr > 0); | ||
561 | events_check_enabled = !ret; | 603 | events_check_enabled = !ret; |
562 | } | 604 | } |
563 | spin_unlock_irqrestore(&events_lock, flags); | 605 | spin_unlock_irqrestore(&events_lock, flags); |
@@ -573,25 +615,25 @@ bool pm_wakeup_pending(void) | |||
573 | * Store the number of registered wakeup events at the address in @count. Block | 615 | * Store the number of registered wakeup events at the address in @count. Block |
574 | * if the current number of wakeup events being processed is nonzero. | 616 | * if the current number of wakeup events being processed is nonzero. |
575 | * | 617 | * |
576 | * Return false if the wait for the number of wakeup events being processed to | 618 | * Return 'false' if the wait for the number of wakeup events being processed to |
577 | * drop down to zero has been interrupted by a signal (and the current number | 619 | * drop down to zero has been interrupted by a signal (and the current number |
578 | * of wakeup events being processed is still nonzero). Otherwise return true. | 620 | * of wakeup events being processed is still nonzero). Otherwise return 'true'. |
579 | */ | 621 | */ |
580 | bool pm_get_wakeup_count(unsigned int *count) | 622 | bool pm_get_wakeup_count(unsigned int *count) |
581 | { | 623 | { |
582 | bool ret; | 624 | unsigned int cnt, inpr; |
583 | |||
584 | if (capable(CAP_SYS_ADMIN)) | ||
585 | events_check_enabled = false; | ||
586 | 625 | ||
587 | while (atomic_read(&events_in_progress) && !signal_pending(current)) { | 626 | for (;;) { |
627 | split_counters(&cnt, &inpr); | ||
628 | if (inpr == 0 || signal_pending(current)) | ||
629 | break; | ||
588 | pm_wakeup_update_hit_counts(); | 630 | pm_wakeup_update_hit_counts(); |
589 | schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); | 631 | schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT)); |
590 | } | 632 | } |
591 | 633 | ||
592 | ret = !atomic_read(&events_in_progress); | 634 | split_counters(&cnt, &inpr); |
593 | *count = atomic_read(&event_count); | 635 | *count = cnt; |
594 | return ret; | 636 | return !inpr; |
595 | } | 637 | } |
596 | 638 | ||
597 | /** | 639 | /** |
@@ -600,24 +642,25 @@ bool pm_get_wakeup_count(unsigned int *count) | |||
600 | * | 642 | * |
601 | * If @count is equal to the current number of registered wakeup events and the | 643 | * If @count is equal to the current number of registered wakeup events and the |
602 | * current number of wakeup events being processed is zero, store @count as the | 644 | * current number of wakeup events being processed is zero, store @count as the |
603 | * old number of registered wakeup events to be used by pm_check_wakeup_events() | 645 | * old number of registered wakeup events for pm_check_wakeup_events(), enable |
604 | * and return true. Otherwise return false. | 646 | * wakeup events detection and return 'true'. Otherwise disable wakeup events |
647 | * detection and return 'false'. | ||
605 | */ | 648 | */ |
606 | bool pm_save_wakeup_count(unsigned int count) | 649 | bool pm_save_wakeup_count(unsigned int count) |
607 | { | 650 | { |
608 | bool ret = false; | 651 | unsigned int cnt, inpr; |
609 | 652 | ||
653 | events_check_enabled = false; | ||
610 | spin_lock_irq(&events_lock); | 654 | spin_lock_irq(&events_lock); |
611 | if (count == (unsigned int)atomic_read(&event_count) | 655 | split_counters(&cnt, &inpr); |
612 | && !atomic_read(&events_in_progress)) { | 656 | if (cnt == count && inpr == 0) { |
613 | saved_count = count; | 657 | saved_count = count; |
614 | events_check_enabled = true; | 658 | events_check_enabled = true; |
615 | ret = true; | ||
616 | } | 659 | } |
617 | spin_unlock_irq(&events_lock); | 660 | spin_unlock_irq(&events_lock); |
618 | if (!ret) | 661 | if (!events_check_enabled) |
619 | pm_wakeup_update_hit_counts(); | 662 | pm_wakeup_update_hit_counts(); |
620 | return ret; | 663 | return events_check_enabled; |
621 | } | 664 | } |
622 | 665 | ||
623 | static struct dentry *wakeup_sources_stats_dentry; | 666 | static struct dentry *wakeup_sources_stats_dentry; |
diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c new file mode 100644 index 000000000000..90af2943f9e4 --- /dev/null +++ b/drivers/base/syscore.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * syscore.c - Execution of system core operations. | ||
3 | * | ||
4 | * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/syscore_ops.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | static LIST_HEAD(syscore_ops_list); | ||
14 | static DEFINE_MUTEX(syscore_ops_lock); | ||
15 | |||
16 | /** | ||
17 | * register_syscore_ops - Register a set of system core operations. | ||
18 | * @ops: System core operations to register. | ||
19 | */ | ||
20 | void register_syscore_ops(struct syscore_ops *ops) | ||
21 | { | ||
22 | mutex_lock(&syscore_ops_lock); | ||
23 | list_add_tail(&ops->node, &syscore_ops_list); | ||
24 | mutex_unlock(&syscore_ops_lock); | ||
25 | } | ||
26 | EXPORT_SYMBOL_GPL(register_syscore_ops); | ||
27 | |||
28 | /** | ||
29 | * unregister_syscore_ops - Unregister a set of system core operations. | ||
30 | * @ops: System core operations to unregister. | ||
31 | */ | ||
32 | void unregister_syscore_ops(struct syscore_ops *ops) | ||
33 | { | ||
34 | mutex_lock(&syscore_ops_lock); | ||
35 | list_del(&ops->node); | ||
36 | mutex_unlock(&syscore_ops_lock); | ||
37 | } | ||
38 | EXPORT_SYMBOL_GPL(unregister_syscore_ops); | ||
39 | |||
40 | #ifdef CONFIG_PM_SLEEP | ||
41 | /** | ||
42 | * syscore_suspend - Execute all the registered system core suspend callbacks. | ||
43 | * | ||
44 | * This function is executed with one CPU on-line and disabled interrupts. | ||
45 | */ | ||
46 | int syscore_suspend(void) | ||
47 | { | ||
48 | struct syscore_ops *ops; | ||
49 | int ret = 0; | ||
50 | |||
51 | WARN_ONCE(!irqs_disabled(), | ||
52 | "Interrupts enabled before system core suspend.\n"); | ||
53 | |||
54 | list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
55 | if (ops->suspend) { | ||
56 | if (initcall_debug) | ||
57 | pr_info("PM: Calling %pF\n", ops->suspend); | ||
58 | ret = ops->suspend(); | ||
59 | if (ret) | ||
60 | goto err_out; | ||
61 | WARN_ONCE(!irqs_disabled(), | ||
62 | "Interrupts enabled after %pF\n", ops->suspend); | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | |||
67 | err_out: | ||
68 | pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); | ||
69 | |||
70 | list_for_each_entry_continue(ops, &syscore_ops_list, node) | ||
71 | if (ops->resume) | ||
72 | ops->resume(); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * syscore_resume - Execute all the registered system core resume callbacks. | ||
79 | * | ||
80 | * This function is executed with one CPU on-line and disabled interrupts. | ||
81 | */ | ||
82 | void syscore_resume(void) | ||
83 | { | ||
84 | struct syscore_ops *ops; | ||
85 | |||
86 | WARN_ONCE(!irqs_disabled(), | ||
87 | "Interrupts enabled before system core resume.\n"); | ||
88 | |||
89 | list_for_each_entry(ops, &syscore_ops_list, node) | ||
90 | if (ops->resume) { | ||
91 | if (initcall_debug) | ||
92 | pr_info("PM: Calling %pF\n", ops->resume); | ||
93 | ops->resume(); | ||
94 | WARN_ONCE(!irqs_disabled(), | ||
95 | "Interrupts enabled after %pF\n", ops->resume); | ||
96 | } | ||
97 | } | ||
98 | #endif /* CONFIG_PM_SLEEP */ | ||
99 | |||
100 | /** | ||
101 | * syscore_shutdown - Execute all the registered system core shutdown callbacks. | ||
102 | */ | ||
103 | void syscore_shutdown(void) | ||
104 | { | ||
105 | struct syscore_ops *ops; | ||
106 | |||
107 | mutex_lock(&syscore_ops_lock); | ||
108 | |||
109 | list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
110 | if (ops->shutdown) { | ||
111 | if (initcall_debug) | ||
112 | pr_info("PM: Calling %pF\n", ops->shutdown); | ||
113 | ops->shutdown(); | ||
114 | } | ||
115 | |||
116 | mutex_unlock(&syscore_ops_lock); | ||
117 | } | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2e5022849f18..6d513a383340 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -5338,7 +5338,7 @@ void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | |||
5338 | __e1000e_disable_aspm(pdev, state); | 5338 | __e1000e_disable_aspm(pdev, state); |
5339 | } | 5339 | } |
5340 | 5340 | ||
5341 | #ifdef CONFIG_PM_OPS | 5341 | #ifdef CONFIG_PM |
5342 | static bool e1000e_pm_ready(struct e1000_adapter *adapter) | 5342 | static bool e1000e_pm_ready(struct e1000_adapter *adapter) |
5343 | { | 5343 | { |
5344 | return !!adapter->tx_ring->buffer_info; | 5344 | return !!adapter->tx_ring->buffer_info; |
@@ -5489,7 +5489,7 @@ static int e1000_runtime_resume(struct device *dev) | |||
5489 | return __e1000_resume(pdev); | 5489 | return __e1000_resume(pdev); |
5490 | } | 5490 | } |
5491 | #endif /* CONFIG_PM_RUNTIME */ | 5491 | #endif /* CONFIG_PM_RUNTIME */ |
5492 | #endif /* CONFIG_PM_OPS */ | 5492 | #endif /* CONFIG_PM */ |
5493 | 5493 | ||
5494 | static void e1000_shutdown(struct pci_dev *pdev) | 5494 | static void e1000_shutdown(struct pci_dev *pdev) |
5495 | { | 5495 | { |
@@ -6196,7 +6196,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { | |||
6196 | }; | 6196 | }; |
6197 | MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); | 6197 | MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); |
6198 | 6198 | ||
6199 | #ifdef CONFIG_PM_OPS | 6199 | #ifdef CONFIG_PM |
6200 | static const struct dev_pm_ops e1000_pm_ops = { | 6200 | static const struct dev_pm_ops e1000_pm_ops = { |
6201 | SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) | 6201 | SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) |
6202 | SET_RUNTIME_PM_OPS(e1000_runtime_suspend, | 6202 | SET_RUNTIME_PM_OPS(e1000_runtime_suspend, |
@@ -6210,7 +6210,7 @@ static struct pci_driver e1000_driver = { | |||
6210 | .id_table = e1000_pci_tbl, | 6210 | .id_table = e1000_pci_tbl, |
6211 | .probe = e1000_probe, | 6211 | .probe = e1000_probe, |
6212 | .remove = __devexit_p(e1000_remove), | 6212 | .remove = __devexit_p(e1000_remove), |
6213 | #ifdef CONFIG_PM_OPS | 6213 | #ifdef CONFIG_PM |
6214 | .driver.pm = &e1000_pm_ops, | 6214 | .driver.pm = &e1000_pm_ops, |
6215 | #endif | 6215 | #endif |
6216 | .shutdown = e1000_shutdown, | 6216 | .shutdown = e1000_shutdown, |
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index b99e90aca37d..8c66e22c3a0a 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c | |||
@@ -2446,7 +2446,7 @@ static struct pci_driver pch_gbe_pcidev = { | |||
2446 | .id_table = pch_gbe_pcidev_id, | 2446 | .id_table = pch_gbe_pcidev_id, |
2447 | .probe = pch_gbe_probe, | 2447 | .probe = pch_gbe_probe, |
2448 | .remove = pch_gbe_remove, | 2448 | .remove = pch_gbe_remove, |
2449 | #ifdef CONFIG_PM_OPS | 2449 | #ifdef CONFIG_PM |
2450 | .driver.pm = &pch_gbe_pm_ops, | 2450 | .driver.pm = &pch_gbe_pm_ops, |
2451 | #endif | 2451 | #endif |
2452 | .shutdown = pch_gbe_shutdown, | 2452 | .shutdown = pch_gbe_shutdown, |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 88246dd46452..d86ea8b01137 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -431,7 +431,7 @@ static void pci_device_shutdown(struct device *dev) | |||
431 | pci_msix_shutdown(pci_dev); | 431 | pci_msix_shutdown(pci_dev); |
432 | } | 432 | } |
433 | 433 | ||
434 | #ifdef CONFIG_PM_OPS | 434 | #ifdef CONFIG_PM |
435 | 435 | ||
436 | /* Auxiliary functions used for system resume and run-time resume. */ | 436 | /* Auxiliary functions used for system resume and run-time resume. */ |
437 | 437 | ||
@@ -1059,7 +1059,7 @@ static int pci_pm_runtime_idle(struct device *dev) | |||
1059 | 1059 | ||
1060 | #endif /* !CONFIG_PM_RUNTIME */ | 1060 | #endif /* !CONFIG_PM_RUNTIME */ |
1061 | 1061 | ||
1062 | #ifdef CONFIG_PM_OPS | 1062 | #ifdef CONFIG_PM |
1063 | 1063 | ||
1064 | const struct dev_pm_ops pci_dev_pm_ops = { | 1064 | const struct dev_pm_ops pci_dev_pm_ops = { |
1065 | .prepare = pci_pm_prepare, | 1065 | .prepare = pci_pm_prepare, |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2e9a87e8e7d8..ef6de669424b 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -165,7 +165,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o | |||
165 | scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o | 165 | scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o |
166 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o | 166 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o |
167 | scsi_mod-y += scsi_trace.o | 167 | scsi_mod-y += scsi_trace.o |
168 | scsi_mod-$(CONFIG_PM_OPS) += scsi_pm.o | 168 | scsi_mod-$(CONFIG_PM) += scsi_pm.o |
169 | 169 | ||
170 | scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o | 170 | scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o |
171 | 171 | ||
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index b4056d14f812..342ee1a9c41d 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -146,7 +146,7 @@ static inline void scsi_netlink_exit(void) {} | |||
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | /* scsi_pm.c */ | 148 | /* scsi_pm.c */ |
149 | #ifdef CONFIG_PM_OPS | 149 | #ifdef CONFIG_PM |
150 | extern const struct dev_pm_ops scsi_bus_pm_ops; | 150 | extern const struct dev_pm_ops scsi_bus_pm_ops; |
151 | #endif | 151 | #endif |
152 | #ifdef CONFIG_PM_RUNTIME | 152 | #ifdef CONFIG_PM_RUNTIME |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 490ce213204e..e44ff64233fd 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -383,7 +383,7 @@ struct bus_type scsi_bus_type = { | |||
383 | .name = "scsi", | 383 | .name = "scsi", |
384 | .match = scsi_bus_match, | 384 | .match = scsi_bus_match, |
385 | .uevent = scsi_bus_uevent, | 385 | .uevent = scsi_bus_uevent, |
386 | #ifdef CONFIG_PM_OPS | 386 | #ifdef CONFIG_PM |
387 | .pm = &scsi_bus_pm_ops, | 387 | .pm = &scsi_bus_pm_ops, |
388 | #endif | 388 | #endif |
389 | }; | 389 | }; |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index f71e8e307e0f..64a035ba2eab 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -335,7 +335,7 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) | |||
335 | } | 335 | } |
336 | EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); | 336 | EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); |
337 | 337 | ||
338 | #ifdef CONFIG_PM_OPS | 338 | #ifdef CONFIG_PM |
339 | 339 | ||
340 | #ifdef CONFIG_PPC_PMAC | 340 | #ifdef CONFIG_PPC_PMAC |
341 | static void powermac_set_asic(struct pci_dev *pci_dev, int enable) | 341 | static void powermac_set_asic(struct pci_dev *pci_dev, int enable) |
@@ -580,4 +580,4 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = { | |||
580 | }; | 580 | }; |
581 | EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); | 581 | EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); |
582 | 582 | ||
583 | #endif /* CONFIG_PM_OPS */ | 583 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0f299b7aad60..19d3435e6140 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1465,6 +1465,7 @@ void usb_set_device_state(struct usb_device *udev, | |||
1465 | enum usb_device_state new_state) | 1465 | enum usb_device_state new_state) |
1466 | { | 1466 | { |
1467 | unsigned long flags; | 1467 | unsigned long flags; |
1468 | int wakeup = -1; | ||
1468 | 1469 | ||
1469 | spin_lock_irqsave(&device_state_lock, flags); | 1470 | spin_lock_irqsave(&device_state_lock, flags); |
1470 | if (udev->state == USB_STATE_NOTATTACHED) | 1471 | if (udev->state == USB_STATE_NOTATTACHED) |
@@ -1479,11 +1480,10 @@ void usb_set_device_state(struct usb_device *udev, | |||
1479 | || new_state == USB_STATE_SUSPENDED) | 1480 | || new_state == USB_STATE_SUSPENDED) |
1480 | ; /* No change to wakeup settings */ | 1481 | ; /* No change to wakeup settings */ |
1481 | else if (new_state == USB_STATE_CONFIGURED) | 1482 | else if (new_state == USB_STATE_CONFIGURED) |
1482 | device_set_wakeup_capable(&udev->dev, | 1483 | wakeup = udev->actconfig->desc.bmAttributes |
1483 | (udev->actconfig->desc.bmAttributes | 1484 | & USB_CONFIG_ATT_WAKEUP; |
1484 | & USB_CONFIG_ATT_WAKEUP)); | ||
1485 | else | 1485 | else |
1486 | device_set_wakeup_capable(&udev->dev, 0); | 1486 | wakeup = 0; |
1487 | } | 1487 | } |
1488 | if (udev->state == USB_STATE_SUSPENDED && | 1488 | if (udev->state == USB_STATE_SUSPENDED && |
1489 | new_state != USB_STATE_SUSPENDED) | 1489 | new_state != USB_STATE_SUSPENDED) |
@@ -1495,6 +1495,8 @@ void usb_set_device_state(struct usb_device *udev, | |||
1495 | } else | 1495 | } else |
1496 | recursively_mark_NOTATTACHED(udev); | 1496 | recursively_mark_NOTATTACHED(udev); |
1497 | spin_unlock_irqrestore(&device_state_lock, flags); | 1497 | spin_unlock_irqrestore(&device_state_lock, flags); |
1498 | if (wakeup >= 0) | ||
1499 | device_set_wakeup_capable(&udev->dev, wakeup); | ||
1498 | } | 1500 | } |
1499 | EXPORT_SYMBOL_GPL(usb_set_device_state); | 1501 | EXPORT_SYMBOL_GPL(usb_set_device_state); |
1500 | 1502 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 78ca429929f7..ff103ba96b78 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -381,7 +381,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); | |||
381 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); | 381 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); |
382 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | 382 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); |
383 | 383 | ||
384 | #ifdef CONFIG_PM_OPS | 384 | #ifdef CONFIG_PM |
385 | int acpi_pm_device_sleep_state(struct device *, int *); | 385 | int acpi_pm_device_sleep_state(struct device *, int *); |
386 | #else | 386 | #else |
387 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p) | 387 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p) |
diff --git a/include/linux/device.h b/include/linux/device.h index ca5d25225aab..dba775a68752 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -420,6 +420,7 @@ struct device { | |||
420 | void *platform_data; /* Platform specific data, device | 420 | void *platform_data; /* Platform specific data, device |
421 | core doesn't touch it */ | 421 | core doesn't touch it */ |
422 | struct dev_pm_info power; | 422 | struct dev_pm_info power; |
423 | struct dev_power_domain *pwr_domain; | ||
423 | 424 | ||
424 | #ifdef CONFIG_NUMA | 425 | #ifdef CONFIG_NUMA |
425 | int numa_node; /* NUMA node this device is close to */ | 426 | int numa_node; /* NUMA node this device is close to */ |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 21415cc91cbb..6618216bb973 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -267,7 +267,7 @@ const struct dev_pm_ops name = { \ | |||
267 | * callbacks provided by device drivers supporting both the system sleep PM and | 267 | * callbacks provided by device drivers supporting both the system sleep PM and |
268 | * runtime PM, make the pm member point to generic_subsys_pm_ops. | 268 | * runtime PM, make the pm member point to generic_subsys_pm_ops. |
269 | */ | 269 | */ |
270 | #ifdef CONFIG_PM_OPS | 270 | #ifdef CONFIG_PM |
271 | extern struct dev_pm_ops generic_subsys_pm_ops; | 271 | extern struct dev_pm_ops generic_subsys_pm_ops; |
272 | #define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops) | 272 | #define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops) |
273 | #else | 273 | #else |
@@ -465,6 +465,14 @@ struct dev_pm_info { | |||
465 | 465 | ||
466 | extern void update_pm_runtime_accounting(struct device *dev); | 466 | extern void update_pm_runtime_accounting(struct device *dev); |
467 | 467 | ||
468 | /* | ||
469 | * Power domains provide callbacks that are executed during system suspend, | ||
470 | * hibernation, system resume and during runtime PM transitions along with | ||
471 | * subsystem-level and driver-level callbacks. | ||
472 | */ | ||
473 | struct dev_power_domain { | ||
474 | struct dev_pm_ops ops; | ||
475 | }; | ||
468 | 476 | ||
469 | /* | 477 | /* |
470 | * The PM_EVENT_ messages are also used by drivers implementing the legacy | 478 | * The PM_EVENT_ messages are also used by drivers implementing the legacy |
@@ -565,15 +573,6 @@ enum dpm_order { | |||
565 | DPM_ORDER_DEV_LAST, | 573 | DPM_ORDER_DEV_LAST, |
566 | }; | 574 | }; |
567 | 575 | ||
568 | /* | ||
569 | * Global Power Management flags | ||
570 | * Used to keep APM and ACPI from both being active | ||
571 | */ | ||
572 | extern unsigned int pm_flags; | ||
573 | |||
574 | #define PM_APM 1 | ||
575 | #define PM_ACPI 2 | ||
576 | |||
577 | extern int pm_generic_suspend(struct device *dev); | 576 | extern int pm_generic_suspend(struct device *dev); |
578 | extern int pm_generic_resume(struct device *dev); | 577 | extern int pm_generic_resume(struct device *dev); |
579 | extern int pm_generic_freeze(struct device *dev); | 578 | extern int pm_generic_freeze(struct device *dev); |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index d34f067e2a7f..8de9aa6e7def 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -87,6 +87,11 @@ static inline bool pm_runtime_enabled(struct device *dev) | |||
87 | return !dev->power.disable_depth; | 87 | return !dev->power.disable_depth; |
88 | } | 88 | } |
89 | 89 | ||
90 | static inline bool pm_runtime_callbacks_present(struct device *dev) | ||
91 | { | ||
92 | return !dev->power.no_callbacks; | ||
93 | } | ||
94 | |||
90 | static inline void pm_runtime_mark_last_busy(struct device *dev) | 95 | static inline void pm_runtime_mark_last_busy(struct device *dev) |
91 | { | 96 | { |
92 | ACCESS_ONCE(dev->power.last_busy) = jiffies; | 97 | ACCESS_ONCE(dev->power.last_busy) = jiffies; |
@@ -133,6 +138,7 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } | |||
133 | static inline void pm_runtime_no_callbacks(struct device *dev) {} | 138 | static inline void pm_runtime_no_callbacks(struct device *dev) {} |
134 | static inline void pm_runtime_irq_safe(struct device *dev) {} | 139 | static inline void pm_runtime_irq_safe(struct device *dev) {} |
135 | 140 | ||
141 | static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } | ||
136 | static inline void pm_runtime_mark_last_busy(struct device *dev) {} | 142 | static inline void pm_runtime_mark_last_busy(struct device *dev) {} |
137 | static inline void __pm_runtime_use_autosuspend(struct device *dev, | 143 | static inline void __pm_runtime_use_autosuspend(struct device *dev, |
138 | bool use) {} | 144 | bool use) {} |
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 03a67db03d01..a32da962d693 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h | |||
@@ -62,18 +62,11 @@ struct wakeup_source { | |||
62 | * Changes to device_may_wakeup take effect on the next pm state change. | 62 | * Changes to device_may_wakeup take effect on the next pm state change. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | static inline void device_set_wakeup_capable(struct device *dev, bool capable) | ||
66 | { | ||
67 | dev->power.can_wakeup = capable; | ||
68 | } | ||
69 | |||
70 | static inline bool device_can_wakeup(struct device *dev) | 65 | static inline bool device_can_wakeup(struct device *dev) |
71 | { | 66 | { |
72 | return dev->power.can_wakeup; | 67 | return dev->power.can_wakeup; |
73 | } | 68 | } |
74 | 69 | ||
75 | |||
76 | |||
77 | static inline bool device_may_wakeup(struct device *dev) | 70 | static inline bool device_may_wakeup(struct device *dev) |
78 | { | 71 | { |
79 | return dev->power.can_wakeup && !!dev->power.wakeup; | 72 | return dev->power.can_wakeup && !!dev->power.wakeup; |
@@ -88,6 +81,7 @@ extern struct wakeup_source *wakeup_source_register(const char *name); | |||
88 | extern void wakeup_source_unregister(struct wakeup_source *ws); | 81 | extern void wakeup_source_unregister(struct wakeup_source *ws); |
89 | extern int device_wakeup_enable(struct device *dev); | 82 | extern int device_wakeup_enable(struct device *dev); |
90 | extern int device_wakeup_disable(struct device *dev); | 83 | extern int device_wakeup_disable(struct device *dev); |
84 | extern void device_set_wakeup_capable(struct device *dev, bool capable); | ||
91 | extern int device_init_wakeup(struct device *dev, bool val); | 85 | extern int device_init_wakeup(struct device *dev, bool val); |
92 | extern int device_set_wakeup_enable(struct device *dev, bool enable); | 86 | extern int device_set_wakeup_enable(struct device *dev, bool enable); |
93 | extern void __pm_stay_awake(struct wakeup_source *ws); | 87 | extern void __pm_stay_awake(struct wakeup_source *ws); |
diff --git a/include/linux/syscore_ops.h b/include/linux/syscore_ops.h new file mode 100644 index 000000000000..27b3b0bc41a9 --- /dev/null +++ b/include/linux/syscore_ops.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * syscore_ops.h - System core operations. | ||
3 | * | ||
4 | * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #ifndef _LINUX_SYSCORE_OPS_H | ||
10 | #define _LINUX_SYSCORE_OPS_H | ||
11 | |||
12 | #include <linux/list.h> | ||
13 | |||
14 | struct syscore_ops { | ||
15 | struct list_head node; | ||
16 | int (*suspend)(void); | ||
17 | void (*resume)(void); | ||
18 | void (*shutdown)(void); | ||
19 | }; | ||
20 | |||
21 | extern void register_syscore_ops(struct syscore_ops *ops); | ||
22 | extern void unregister_syscore_ops(struct syscore_ops *ops); | ||
23 | #ifdef CONFIG_PM_SLEEP | ||
24 | extern int syscore_suspend(void); | ||
25 | extern void syscore_resume(void); | ||
26 | #endif | ||
27 | extern void syscore_shutdown(void); | ||
28 | |||
29 | #endif | ||
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c index aeaa7f846821..0da058bff8eb 100644 --- a/kernel/pm_qos_params.c +++ b/kernel/pm_qos_params.c | |||
@@ -103,11 +103,14 @@ static struct pm_qos_object *pm_qos_array[] = { | |||
103 | 103 | ||
104 | static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, | 104 | static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, |
105 | size_t count, loff_t *f_pos); | 105 | size_t count, loff_t *f_pos); |
106 | static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, | ||
107 | size_t count, loff_t *f_pos); | ||
106 | static int pm_qos_power_open(struct inode *inode, struct file *filp); | 108 | static int pm_qos_power_open(struct inode *inode, struct file *filp); |
107 | static int pm_qos_power_release(struct inode *inode, struct file *filp); | 109 | static int pm_qos_power_release(struct inode *inode, struct file *filp); |
108 | 110 | ||
109 | static const struct file_operations pm_qos_power_fops = { | 111 | static const struct file_operations pm_qos_power_fops = { |
110 | .write = pm_qos_power_write, | 112 | .write = pm_qos_power_write, |
113 | .read = pm_qos_power_read, | ||
111 | .open = pm_qos_power_open, | 114 | .open = pm_qos_power_open, |
112 | .release = pm_qos_power_release, | 115 | .release = pm_qos_power_release, |
113 | .llseek = noop_llseek, | 116 | .llseek = noop_llseek, |
@@ -376,6 +379,27 @@ static int pm_qos_power_release(struct inode *inode, struct file *filp) | |||
376 | } | 379 | } |
377 | 380 | ||
378 | 381 | ||
382 | static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, | ||
383 | size_t count, loff_t *f_pos) | ||
384 | { | ||
385 | s32 value; | ||
386 | unsigned long flags; | ||
387 | struct pm_qos_object *o; | ||
388 | struct pm_qos_request_list *pm_qos_req = filp->private_data;; | ||
389 | |||
390 | if (!pm_qos_req) | ||
391 | return -EINVAL; | ||
392 | if (!pm_qos_request_active(pm_qos_req)) | ||
393 | return -EINVAL; | ||
394 | |||
395 | o = pm_qos_array[pm_qos_req->pm_qos_class]; | ||
396 | spin_lock_irqsave(&pm_qos_lock, flags); | ||
397 | value = pm_qos_get_value(o); | ||
398 | spin_unlock_irqrestore(&pm_qos_lock, flags); | ||
399 | |||
400 | return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); | ||
401 | } | ||
402 | |||
379 | static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, | 403 | static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, |
380 | size_t count, loff_t *f_pos) | 404 | size_t count, loff_t *f_pos) |
381 | { | 405 | { |
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 265729966ece..4603f08dc47b 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -1,125 +1,12 @@ | |||
1 | config PM | ||
2 | bool "Power Management support" | ||
3 | depends on !IA64_HP_SIM | ||
4 | ---help--- | ||
5 | "Power Management" means that parts of your computer are shut | ||
6 | off or put into a power conserving "sleep" mode if they are not | ||
7 | being used. There are two competing standards for doing this: APM | ||
8 | and ACPI. If you want to use either one, say Y here and then also | ||
9 | to the requisite support below. | ||
10 | |||
11 | Power Management is most important for battery powered laptop | ||
12 | computers; if you have a laptop, check out the Linux Laptop home | ||
13 | page on the WWW at <http://www.linux-on-laptops.com/> or | ||
14 | Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/> | ||
15 | and the Battery Powered Linux mini-HOWTO, available from | ||
16 | <http://www.tldp.org/docs.html#howto>. | ||
17 | |||
18 | Note that, even if you say N here, Linux on the x86 architecture | ||
19 | will issue the hlt instruction if nothing is to be done, thereby | ||
20 | sending the processor to sleep and saving power. | ||
21 | |||
22 | config PM_DEBUG | ||
23 | bool "Power Management Debug Support" | ||
24 | depends on PM | ||
25 | ---help--- | ||
26 | This option enables various debugging support in the Power Management | ||
27 | code. This is helpful when debugging and reporting PM bugs, like | ||
28 | suspend support. | ||
29 | |||
30 | config PM_ADVANCED_DEBUG | ||
31 | bool "Extra PM attributes in sysfs for low-level debugging/testing" | ||
32 | depends on PM_DEBUG | ||
33 | default n | ||
34 | ---help--- | ||
35 | Add extra sysfs attributes allowing one to access some Power Management | ||
36 | fields of device objects from user space. If you are not a kernel | ||
37 | developer interested in debugging/testing Power Management, say "no". | ||
38 | |||
39 | config PM_VERBOSE | ||
40 | bool "Verbose Power Management debugging" | ||
41 | depends on PM_DEBUG | ||
42 | default n | ||
43 | ---help--- | ||
44 | This option enables verbose messages from the Power Management code. | ||
45 | |||
46 | config CAN_PM_TRACE | ||
47 | def_bool y | ||
48 | depends on PM_DEBUG && PM_SLEEP && EXPERIMENTAL | ||
49 | |||
50 | config PM_TRACE | ||
51 | bool | ||
52 | help | ||
53 | This enables code to save the last PM event point across | ||
54 | reboot. The architecture needs to support this, x86 for | ||
55 | example does by saving things in the RTC, see below. | ||
56 | |||
57 | The architecture specific code must provide the extern | ||
58 | functions from <linux/resume-trace.h> as well as the | ||
59 | <asm/resume-trace.h> header with a TRACE_RESUME() macro. | ||
60 | |||
61 | The way the information is presented is architecture- | ||
62 | dependent, x86 will print the information during a | ||
63 | late_initcall. | ||
64 | |||
65 | config PM_TRACE_RTC | ||
66 | bool "Suspend/resume event tracing" | ||
67 | depends on CAN_PM_TRACE | ||
68 | depends on X86 | ||
69 | select PM_TRACE | ||
70 | default n | ||
71 | ---help--- | ||
72 | This enables some cheesy code to save the last PM event point in the | ||
73 | RTC across reboots, so that you can debug a machine that just hangs | ||
74 | during suspend (or more commonly, during resume). | ||
75 | |||
76 | To use this debugging feature you should attempt to suspend the | ||
77 | machine, reboot it and then run | ||
78 | |||
79 | dmesg -s 1000000 | grep 'hash matches' | ||
80 | |||
81 | CAUTION: this option will cause your machine's real-time clock to be | ||
82 | set to an invalid time after a resume. | ||
83 | |||
84 | config PM_SLEEP_SMP | ||
85 | bool | ||
86 | depends on SMP | ||
87 | depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE | ||
88 | depends on PM_SLEEP | ||
89 | select HOTPLUG | ||
90 | select HOTPLUG_CPU | ||
91 | default y | ||
92 | |||
93 | config PM_SLEEP | ||
94 | bool | ||
95 | depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE | ||
96 | default y | ||
97 | |||
98 | config PM_SLEEP_ADVANCED_DEBUG | ||
99 | bool | ||
100 | depends on PM_ADVANCED_DEBUG | ||
101 | default n | ||
102 | |||
103 | config SUSPEND | 1 | config SUSPEND |
104 | bool "Suspend to RAM and standby" | 2 | bool "Suspend to RAM and standby" |
105 | depends on PM && ARCH_SUSPEND_POSSIBLE | 3 | depends on ARCH_SUSPEND_POSSIBLE |
106 | default y | 4 | default y |
107 | ---help--- | 5 | ---help--- |
108 | Allow the system to enter sleep states in which main memory is | 6 | Allow the system to enter sleep states in which main memory is |
109 | powered and thus its contents are preserved, such as the | 7 | powered and thus its contents are preserved, such as the |
110 | suspend-to-RAM state (e.g. the ACPI S3 state). | 8 | suspend-to-RAM state (e.g. the ACPI S3 state). |
111 | 9 | ||
112 | config PM_TEST_SUSPEND | ||
113 | bool "Test suspend/resume and wakealarm during bootup" | ||
114 | depends on SUSPEND && PM_DEBUG && RTC_CLASS=y | ||
115 | ---help--- | ||
116 | This option will let you suspend your machine during bootup, and | ||
117 | make it wake up a few seconds later using an RTC wakeup alarm. | ||
118 | Enable this with a kernel parameter like "test_suspend=mem". | ||
119 | |||
120 | You probably want to have your system's RTC driver statically | ||
121 | linked, ensuring that it's available when this test runs. | ||
122 | |||
123 | config SUSPEND_FREEZER | 10 | config SUSPEND_FREEZER |
124 | bool "Enable freezer for suspend to RAM/standby" \ | 11 | bool "Enable freezer for suspend to RAM/standby" \ |
125 | if ARCH_WANTS_FREEZER_CONTROL || BROKEN | 12 | if ARCH_WANTS_FREEZER_CONTROL || BROKEN |
@@ -133,7 +20,7 @@ config SUSPEND_FREEZER | |||
133 | 20 | ||
134 | config HIBERNATION | 21 | config HIBERNATION |
135 | bool "Hibernation (aka 'suspend to disk')" | 22 | bool "Hibernation (aka 'suspend to disk')" |
136 | depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE | 23 | depends on SWAP && ARCH_HIBERNATION_POSSIBLE |
137 | select LZO_COMPRESS | 24 | select LZO_COMPRESS |
138 | select LZO_DECOMPRESS | 25 | select LZO_DECOMPRESS |
139 | ---help--- | 26 | ---help--- |
@@ -196,6 +83,106 @@ config PM_STD_PARTITION | |||
196 | suspended image to. It will simply pick the first available swap | 83 | suspended image to. It will simply pick the first available swap |
197 | device. | 84 | device. |
198 | 85 | ||
86 | config PM_SLEEP | ||
87 | def_bool y | ||
88 | depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE | ||
89 | |||
90 | config PM_SLEEP_SMP | ||
91 | def_bool y | ||
92 | depends on SMP | ||
93 | depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE | ||
94 | depends on PM_SLEEP | ||
95 | select HOTPLUG | ||
96 | select HOTPLUG_CPU | ||
97 | |||
98 | config PM_RUNTIME | ||
99 | bool "Run-time PM core functionality" | ||
100 | depends on !IA64_HP_SIM | ||
101 | ---help--- | ||
102 | Enable functionality allowing I/O devices to be put into energy-saving | ||
103 | (low power) states at run time (or autosuspended) after a specified | ||
104 | period of inactivity and woken up in response to a hardware-generated | ||
105 | wake-up event or a driver's request. | ||
106 | |||
107 | Hardware support is generally required for this functionality to work | ||
108 | and the bus type drivers of the buses the devices are on are | ||
109 | responsible for the actual handling of the autosuspend requests and | ||
110 | wake-up events. | ||
111 | |||
112 | config PM | ||
113 | def_bool y | ||
114 | depends on PM_SLEEP || PM_RUNTIME | ||
115 | |||
116 | config PM_DEBUG | ||
117 | bool "Power Management Debug Support" | ||
118 | depends on PM | ||
119 | ---help--- | ||
120 | This option enables various debugging support in the Power Management | ||
121 | code. This is helpful when debugging and reporting PM bugs, like | ||
122 | suspend support. | ||
123 | |||
124 | config PM_VERBOSE | ||
125 | bool "Verbose Power Management debugging" | ||
126 | depends on PM_DEBUG | ||
127 | ---help--- | ||
128 | This option enables verbose messages from the Power Management code. | ||
129 | |||
130 | config PM_ADVANCED_DEBUG | ||
131 | bool "Extra PM attributes in sysfs for low-level debugging/testing" | ||
132 | depends on PM_DEBUG | ||
133 | ---help--- | ||
134 | Add extra sysfs attributes allowing one to access some Power Management | ||
135 | fields of device objects from user space. If you are not a kernel | ||
136 | developer interested in debugging/testing Power Management, say "no". | ||
137 | |||
138 | config PM_TEST_SUSPEND | ||
139 | bool "Test suspend/resume and wakealarm during bootup" | ||
140 | depends on SUSPEND && PM_DEBUG && RTC_CLASS=y | ||
141 | ---help--- | ||
142 | This option will let you suspend your machine during bootup, and | ||
143 | make it wake up a few seconds later using an RTC wakeup alarm. | ||
144 | Enable this with a kernel parameter like "test_suspend=mem". | ||
145 | |||
146 | You probably want to have your system's RTC driver statically | ||
147 | linked, ensuring that it's available when this test runs. | ||
148 | |||
149 | config CAN_PM_TRACE | ||
150 | def_bool y | ||
151 | depends on PM_DEBUG && PM_SLEEP | ||
152 | |||
153 | config PM_TRACE | ||
154 | bool | ||
155 | help | ||
156 | This enables code to save the last PM event point across | ||
157 | reboot. The architecture needs to support this, x86 for | ||
158 | example does by saving things in the RTC, see below. | ||
159 | |||
160 | The architecture specific code must provide the extern | ||
161 | functions from <linux/resume-trace.h> as well as the | ||
162 | <asm/resume-trace.h> header with a TRACE_RESUME() macro. | ||
163 | |||
164 | The way the information is presented is architecture- | ||
165 | dependent, x86 will print the information during a | ||
166 | late_initcall. | ||
167 | |||
168 | config PM_TRACE_RTC | ||
169 | bool "Suspend/resume event tracing" | ||
170 | depends on CAN_PM_TRACE | ||
171 | depends on X86 | ||
172 | select PM_TRACE | ||
173 | ---help--- | ||
174 | This enables some cheesy code to save the last PM event point in the | ||
175 | RTC across reboots, so that you can debug a machine that just hangs | ||
176 | during suspend (or more commonly, during resume). | ||
177 | |||
178 | To use this debugging feature you should attempt to suspend the | ||
179 | machine, reboot it and then run | ||
180 | |||
181 | dmesg -s 1000000 | grep 'hash matches' | ||
182 | |||
183 | CAUTION: this option will cause your machine's real-time clock to be | ||
184 | set to an invalid time after a resume. | ||
185 | |||
199 | config APM_EMULATION | 186 | config APM_EMULATION |
200 | tristate "Advanced Power Management Emulation" | 187 | tristate "Advanced Power Management Emulation" |
201 | depends on PM && SYS_SUPPORTS_APM_EMULATION | 188 | depends on PM && SYS_SUPPORTS_APM_EMULATION |
@@ -222,31 +209,11 @@ config APM_EMULATION | |||
222 | anything, try disabling/enabling this option (or disabling/enabling | 209 | anything, try disabling/enabling this option (or disabling/enabling |
223 | APM in your BIOS). | 210 | APM in your BIOS). |
224 | 211 | ||
225 | config PM_RUNTIME | ||
226 | bool "Run-time PM core functionality" | ||
227 | depends on PM | ||
228 | ---help--- | ||
229 | Enable functionality allowing I/O devices to be put into energy-saving | ||
230 | (low power) states at run time (or autosuspended) after a specified | ||
231 | period of inactivity and woken up in response to a hardware-generated | ||
232 | wake-up event or a driver's request. | ||
233 | |||
234 | Hardware support is generally required for this functionality to work | ||
235 | and the bus type drivers of the buses the devices are on are | ||
236 | responsible for the actual handling of the autosuspend requests and | ||
237 | wake-up events. | ||
238 | |||
239 | config PM_OPS | ||
240 | bool | ||
241 | depends on PM_SLEEP || PM_RUNTIME | ||
242 | default y | ||
243 | |||
244 | config ARCH_HAS_OPP | 212 | config ARCH_HAS_OPP |
245 | bool | 213 | bool |
246 | 214 | ||
247 | config PM_OPP | 215 | config PM_OPP |
248 | bool "Operating Performance Point (OPP) Layer library" | 216 | bool "Operating Performance Point (OPP) Layer library" |
249 | depends on PM | ||
250 | depends on ARCH_HAS_OPP | 217 | depends on ARCH_HAS_OPP |
251 | ---help--- | 218 | ---help--- |
252 | SOCs have a standard set of tuples consisting of frequency and | 219 | SOCs have a standard set of tuples consisting of frequency and |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 1832bd264219..aeabd26e3342 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/freezer.h> | 24 | #include <linux/freezer.h> |
25 | #include <linux/gfp.h> | 25 | #include <linux/gfp.h> |
26 | #include <linux/syscore_ops.h> | ||
26 | #include <scsi/scsi_scan.h> | 27 | #include <scsi/scsi_scan.h> |
27 | #include <asm/suspend.h> | 28 | #include <asm/suspend.h> |
28 | 29 | ||
@@ -272,6 +273,8 @@ static int create_image(int platform_mode) | |||
272 | local_irq_disable(); | 273 | local_irq_disable(); |
273 | 274 | ||
274 | error = sysdev_suspend(PMSG_FREEZE); | 275 | error = sysdev_suspend(PMSG_FREEZE); |
276 | if (!error) | ||
277 | error = syscore_suspend(); | ||
275 | if (error) { | 278 | if (error) { |
276 | printk(KERN_ERR "PM: Some system devices failed to power down, " | 279 | printk(KERN_ERR "PM: Some system devices failed to power down, " |
277 | "aborting hibernation\n"); | 280 | "aborting hibernation\n"); |
@@ -295,6 +298,7 @@ static int create_image(int platform_mode) | |||
295 | } | 298 | } |
296 | 299 | ||
297 | Power_up: | 300 | Power_up: |
301 | syscore_resume(); | ||
298 | sysdev_resume(); | 302 | sysdev_resume(); |
299 | /* NOTE: dpm_resume_noirq() is just a resume() for devices | 303 | /* NOTE: dpm_resume_noirq() is just a resume() for devices |
300 | * that suspended with irqs off ... no overall powerup. | 304 | * that suspended with irqs off ... no overall powerup. |
@@ -403,6 +407,8 @@ static int resume_target_kernel(bool platform_mode) | |||
403 | local_irq_disable(); | 407 | local_irq_disable(); |
404 | 408 | ||
405 | error = sysdev_suspend(PMSG_QUIESCE); | 409 | error = sysdev_suspend(PMSG_QUIESCE); |
410 | if (!error) | ||
411 | error = syscore_suspend(); | ||
406 | if (error) | 412 | if (error) |
407 | goto Enable_irqs; | 413 | goto Enable_irqs; |
408 | 414 | ||
@@ -429,6 +435,7 @@ static int resume_target_kernel(bool platform_mode) | |||
429 | restore_processor_state(); | 435 | restore_processor_state(); |
430 | touch_softlockup_watchdog(); | 436 | touch_softlockup_watchdog(); |
431 | 437 | ||
438 | syscore_resume(); | ||
432 | sysdev_resume(); | 439 | sysdev_resume(); |
433 | 440 | ||
434 | Enable_irqs: | 441 | Enable_irqs: |
@@ -516,6 +523,7 @@ int hibernation_platform_enter(void) | |||
516 | 523 | ||
517 | local_irq_disable(); | 524 | local_irq_disable(); |
518 | sysdev_suspend(PMSG_HIBERNATE); | 525 | sysdev_suspend(PMSG_HIBERNATE); |
526 | syscore_suspend(); | ||
519 | if (pm_wakeup_pending()) { | 527 | if (pm_wakeup_pending()) { |
520 | error = -EAGAIN; | 528 | error = -EAGAIN; |
521 | goto Power_up; | 529 | goto Power_up; |
@@ -526,6 +534,7 @@ int hibernation_platform_enter(void) | |||
526 | while (1); | 534 | while (1); |
527 | 535 | ||
528 | Power_up: | 536 | Power_up: |
537 | syscore_resume(); | ||
529 | sysdev_resume(); | 538 | sysdev_resume(); |
530 | local_irq_enable(); | 539 | local_irq_enable(); |
531 | enable_nonboot_cpus(); | 540 | enable_nonboot_cpus(); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 701853042c28..8eaba5f27b10 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -17,9 +17,6 @@ | |||
17 | 17 | ||
18 | DEFINE_MUTEX(pm_mutex); | 18 | DEFINE_MUTEX(pm_mutex); |
19 | 19 | ||
20 | unsigned int pm_flags; | ||
21 | EXPORT_SYMBOL(pm_flags); | ||
22 | |||
23 | #ifdef CONFIG_PM_SLEEP | 20 | #ifdef CONFIG_PM_SLEEP |
24 | 21 | ||
25 | /* Routines for PM-transition notifications */ | 22 | /* Routines for PM-transition notifications */ |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 64db648ff911..ca0aacc24874 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -42,15 +42,15 @@ static void swsusp_unset_page_forbidden(struct page *); | |||
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Preferred image size in bytes (tunable via /sys/power/image_size). | 44 | * Preferred image size in bytes (tunable via /sys/power/image_size). |
45 | * When it is set to N, swsusp will do its best to ensure the image | 45 | * When it is set to N, the image creating code will do its best to |
46 | * size will not exceed N bytes, but if that is impossible, it will | 46 | * ensure the image size will not exceed N bytes, but if that is |
47 | * try to create the smallest image possible. | 47 | * impossible, it will try to create the smallest image possible. |
48 | */ | 48 | */ |
49 | unsigned long image_size; | 49 | unsigned long image_size; |
50 | 50 | ||
51 | void __init hibernate_image_size_init(void) | 51 | void __init hibernate_image_size_init(void) |
52 | { | 52 | { |
53 | image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE; | 53 | image_size = (totalram_pages / 3) * PAGE_SIZE; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* List of PBEs needed for restoring the pages that were allocated before | 56 | /* List of PBEs needed for restoring the pages that were allocated before |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index de6f86bfa303..2814c32aed51 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/suspend.h> | 24 | #include <linux/suspend.h> |
25 | #include <linux/syscore_ops.h> | ||
25 | #include <trace/events/power.h> | 26 | #include <trace/events/power.h> |
26 | 27 | ||
27 | #include "power.h" | 28 | #include "power.h" |
@@ -163,11 +164,14 @@ static int suspend_enter(suspend_state_t state) | |||
163 | BUG_ON(!irqs_disabled()); | 164 | BUG_ON(!irqs_disabled()); |
164 | 165 | ||
165 | error = sysdev_suspend(PMSG_SUSPEND); | 166 | error = sysdev_suspend(PMSG_SUSPEND); |
167 | if (!error) | ||
168 | error = syscore_suspend(); | ||
166 | if (!error) { | 169 | if (!error) { |
167 | if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { | 170 | if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) { |
168 | error = suspend_ops->enter(state); | 171 | error = suspend_ops->enter(state); |
169 | events_check_enabled = false; | 172 | events_check_enabled = false; |
170 | } | 173 | } |
174 | syscore_resume(); | ||
171 | sysdev_resume(); | 175 | sysdev_resume(); |
172 | } | 176 | } |
173 | 177 | ||
diff --git a/kernel/sys.c b/kernel/sys.c index 18da702ec813..1ad48b3b9068 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/ptrace.h> | 37 | #include <linux/ptrace.h> |
38 | #include <linux/fs_struct.h> | 38 | #include <linux/fs_struct.h> |
39 | #include <linux/gfp.h> | 39 | #include <linux/gfp.h> |
40 | #include <linux/syscore_ops.h> | ||
40 | 41 | ||
41 | #include <linux/compat.h> | 42 | #include <linux/compat.h> |
42 | #include <linux/syscalls.h> | 43 | #include <linux/syscalls.h> |
@@ -298,6 +299,7 @@ void kernel_restart_prepare(char *cmd) | |||
298 | system_state = SYSTEM_RESTART; | 299 | system_state = SYSTEM_RESTART; |
299 | device_shutdown(); | 300 | device_shutdown(); |
300 | sysdev_shutdown(); | 301 | sysdev_shutdown(); |
302 | syscore_shutdown(); | ||
301 | } | 303 | } |
302 | 304 | ||
303 | /** | 305 | /** |
@@ -336,6 +338,7 @@ void kernel_halt(void) | |||
336 | { | 338 | { |
337 | kernel_shutdown_prepare(SYSTEM_HALT); | 339 | kernel_shutdown_prepare(SYSTEM_HALT); |
338 | sysdev_shutdown(); | 340 | sysdev_shutdown(); |
341 | syscore_shutdown(); | ||
339 | printk(KERN_EMERG "System halted.\n"); | 342 | printk(KERN_EMERG "System halted.\n"); |
340 | kmsg_dump(KMSG_DUMP_HALT); | 343 | kmsg_dump(KMSG_DUMP_HALT); |
341 | machine_halt(); | 344 | machine_halt(); |
@@ -355,6 +358,7 @@ void kernel_power_off(void) | |||
355 | pm_power_off_prepare(); | 358 | pm_power_off_prepare(); |
356 | disable_nonboot_cpus(); | 359 | disable_nonboot_cpus(); |
357 | sysdev_shutdown(); | 360 | sysdev_shutdown(); |
361 | syscore_shutdown(); | ||
358 | printk(KERN_EMERG "Power down.\n"); | 362 | printk(KERN_EMERG "Power down.\n"); |
359 | kmsg_dump(KMSG_DUMP_POWEROFF); | 363 | kmsg_dump(KMSG_DUMP_POWEROFF); |
360 | machine_power_off(); | 364 | machine_power_off(); |