PM: introduce set_target method in pm_ops

Commit 52ade9b3b97fd3bea42842a056fe0786c28d0555 changed the suspend code
ordering to execute pm_ops->prepare() after the device model per-device
.suspend() calls in order to fix some ACPI-related issues. Unfortunately, it
broke the at91 platform which assumed that pm_ops->prepare() would be called
before suspending devices.

at91 used pm_ops->prepare() to get notified of the target system sleep state,
so that it could use this information while suspending devices. However, with
the current suspend code ordering pm_ops->prepare() is called too late for
this purpose. Thus, at91 needs an additional method in 'struct pm_ops' that
will be used for notifying the platform of the target system sleep state.
Moreover, in the future such a method will also be needed by ACPI.

This patch adds the .set_target() method to 'struct pm_ops' and makes the
suspend code call it, if implemented, before executing the device model
per-device .suspend() calls. It also modifies the at91 code to use
pm_ops->set_target() instead of pm_ops->prepare().

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Len Brown <lenb@kernel.org>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Rafael J. Wysocki and committed by Linus Torvalds 2391dae3 cbcdd772

+54 -18
+2 -2
arch/arm/mach-at91/pm.c
··· 53 53 /* 54 54 * Called after processes are frozen, but before we shutdown devices. 55 55 */ 56 - static int at91_pm_prepare(suspend_state_t state) 56 + static int at91_pm_set_target(suspend_state_t state) 57 57 { 58 58 target_state = state; 59 59 return 0; ··· 201 201 202 202 static struct pm_ops at91_pm_ops ={ 203 203 .valid = at91_pm_valid_state, 204 - .prepare = at91_pm_prepare, 204 + .set_target = at91_pm_set_target, 205 205 .enter = at91_pm_enter, 206 206 }; 207 207
+47 -15
include/linux/pm.h
··· 110 110 #define PM_SUSPEND_MAX ((__force suspend_state_t) 4) 111 111 112 112 /** 113 - * struct pm_ops - Callbacks for managing platform dependent suspend states. 114 - * @valid: Callback to determine whether the given state can be entered. 115 - * Valid states are advertised in /sys/power/state but can still 116 - * be rejected by prepare or enter if the conditions aren't right. 117 - * There is a %pm_valid_only_mem function available that can be assigned 118 - * to this if you only implement mem sleep. 113 + * struct pm_ops - Callbacks for managing platform dependent system sleep 114 + * states. 119 115 * 120 - * @prepare: Prepare the platform for the given suspend state. Can return a 121 - * negative error code if necessary. 116 + * @valid: Callback to determine if given system sleep state is supported by 117 + * the platform. 118 + * Valid (ie. supported) states are advertised in /sys/power/state. Note 119 + * that it still may be impossible to enter given system sleep state if the 120 + * conditions aren't right. 121 + * There is the %pm_valid_only_mem function available that can be assigned 122 + * to this if the platform only supports mem sleep. 122 123 * 123 - * @enter: Enter the given suspend state, must be assigned. Can return a 124 - * negative error code if necessary. 124 + * @set_target: Tell the platform which system sleep state is going to be 125 + * entered. 126 + * @set_target() is executed right prior to suspending devices. The 127 + * information conveyed to the platform code by @set_target() should be 128 + * disregarded by the platform as soon as @finish() is executed and if 129 + * @prepare() fails. If @set_target() fails (ie. returns nonzero), 130 + * @prepare(), @enter() and @finish() will not be called by the PM core. 131 + * This callback is optional. However, if it is implemented, the argument 132 + * passed to @prepare(), @enter() and @finish() is meaningless and should 133 + * be ignored. 125 134 * 126 - * @finish: Called when the system has left the given state and all devices 127 - * are resumed. The return value is ignored. 135 + * @prepare: Prepare the platform for entering the system sleep state indicated 136 + * by @set_target() or represented by the argument if @set_target() is not 137 + * implemented. 138 + * @prepare() is called right after devices have been suspended (ie. the 139 + * appropriate .suspend() method has been executed for each device) and 140 + * before the nonboot CPUs are disabled (it is executed with IRQs enabled). 141 + * This callback is optional. It returns 0 on success or a negative 142 + * error code otherwise, in which case the system cannot enter the desired 143 + * sleep state (@enter() and @finish() will not be called in that case). 144 + * 145 + * @enter: Enter the system sleep state indicated by @set_target() or 146 + * represented by the argument if @set_target() is not implemented. 147 + * This callback is mandatory. It returns 0 on success or a negative 148 + * error code otherwise, in which case the system cannot enter the desired 149 + * sleep state. 150 + * 151 + * @finish: Called when the system has just left a sleep state, right after 152 + * the nonboot CPUs have been enabled and before devices are resumed (it is 153 + * executed with IRQs enabled). If @set_target() is not implemented, the 154 + * argument represents the sleep state being left. 155 + * This callback is optional, but should be implemented by the platforms 156 + * that implement @prepare(). If implemented, it is always called after 157 + * @enter() (even if @enter() fails). 128 158 */ 129 159 struct pm_ops { 130 160 int (*valid)(suspend_state_t state); 161 + int (*set_target)(suspend_state_t state); 131 162 int (*prepare)(suspend_state_t state); 132 163 int (*enter)(suspend_state_t state); 133 164 int (*finish)(suspend_state_t state); 134 165 }; 166 + 167 + extern struct pm_ops *pm_ops; 135 168 136 169 /** 137 170 * pm_set_ops - set platform dependent power management ops 138 171 * @pm_ops: The new power management operations to set. 139 172 */ 140 173 extern void pm_set_ops(struct pm_ops *pm_ops); 141 - extern struct pm_ops *pm_ops; 142 - extern int pm_suspend(suspend_state_t state); 143 - 144 174 extern int pm_valid_only_mem(suspend_state_t state); 145 175 146 176 /** ··· 190 160 * done. Not called for suspend to disk. 191 161 */ 192 162 extern void arch_suspend_enable_irqs(void); 163 + 164 + extern int pm_suspend(suspend_state_t state); 193 165 194 166 /* 195 167 * Device power management
+5 -1
kernel/power/main.c
··· 15 15 #include <linux/delay.h> 16 16 #include <linux/errno.h> 17 17 #include <linux/init.h> 18 - #include <linux/pm.h> 19 18 #include <linux/console.h> 20 19 #include <linux/cpu.h> 21 20 #include <linux/resume-trace.h> ··· 96 97 } 97 98 } 98 99 100 + if (pm_ops->set_target) { 101 + error = pm_ops->set_target(state); 102 + if (error) 103 + goto Thaw; 104 + } 99 105 suspend_console(); 100 106 error = device_suspend(PMSG_SUSPEND); 101 107 if (error) {