diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-01-29 14:38:41 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-01-29 14:38:41 -0500 |
commit | e470d06655e00749f6f9372e4fa4f20cea7ed7c5 (patch) | |
tree | 63e56f01b27ee9693bfb9d9127e4763ba0937057 /drivers/base/power/generic_ops.c | |
parent | cf579dfb82550e34de7ccf3ef090d8b834ccd3a9 (diff) |
PM / Sleep: Introduce generic callbacks for new device PM phases
Introduce generic subsystem callbacks for the new phases of device
suspend/resume during system power transitions: "late suspend",
"early resume", "late freeze", "early thaw", "late poweroff",
"early restore".
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base/power/generic_ops.c')
-rw-r--r-- | drivers/base/power/generic_ops.c | 157 |
1 files changed, 104 insertions, 53 deletions
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c index 10bdd793f0bd..d03d290f31c2 100644 --- a/drivers/base/power/generic_ops.c +++ b/drivers/base/power/generic_ops.c | |||
@@ -92,59 +92,28 @@ int pm_generic_prepare(struct device *dev) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. | 95 | * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems. |
96 | * @dev: Device to handle. | 96 | * @dev: Device to suspend. |
97 | * @event: PM transition of the system under way. | ||
98 | * @bool: Whether or not this is the "noirq" stage. | ||
99 | * | ||
100 | * Execute the PM callback corresponding to @event provided by the driver of | ||
101 | * @dev, if defined, and return its error code. Return 0 if the callback is | ||
102 | * not present. | ||
103 | */ | 97 | */ |
104 | static int __pm_generic_call(struct device *dev, int event, bool noirq) | 98 | int pm_generic_suspend_noirq(struct device *dev) |
105 | { | 99 | { |
106 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 100 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
107 | int (*callback)(struct device *); | ||
108 | |||
109 | if (!pm) | ||
110 | return 0; | ||
111 | |||
112 | switch (event) { | ||
113 | case PM_EVENT_SUSPEND: | ||
114 | callback = noirq ? pm->suspend_noirq : pm->suspend; | ||
115 | break; | ||
116 | case PM_EVENT_FREEZE: | ||
117 | callback = noirq ? pm->freeze_noirq : pm->freeze; | ||
118 | break; | ||
119 | case PM_EVENT_HIBERNATE: | ||
120 | callback = noirq ? pm->poweroff_noirq : pm->poweroff; | ||
121 | break; | ||
122 | case PM_EVENT_RESUME: | ||
123 | callback = noirq ? pm->resume_noirq : pm->resume; | ||
124 | break; | ||
125 | case PM_EVENT_THAW: | ||
126 | callback = noirq ? pm->thaw_noirq : pm->thaw; | ||
127 | break; | ||
128 | case PM_EVENT_RESTORE: | ||
129 | callback = noirq ? pm->restore_noirq : pm->restore; | ||
130 | break; | ||
131 | default: | ||
132 | callback = NULL; | ||
133 | break; | ||
134 | } | ||
135 | 101 | ||
136 | return callback ? callback(dev) : 0; | 102 | return pm && pm->suspend_noirq ? pm->suspend_noirq(dev) : 0; |
137 | } | 103 | } |
104 | EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq); | ||
138 | 105 | ||
139 | /** | 106 | /** |
140 | * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems. | 107 | * pm_generic_suspend_late - Generic suspend_late callback for subsystems. |
141 | * @dev: Device to suspend. | 108 | * @dev: Device to suspend. |
142 | */ | 109 | */ |
143 | int pm_generic_suspend_noirq(struct device *dev) | 110 | int pm_generic_suspend_late(struct device *dev) |
144 | { | 111 | { |
145 | return __pm_generic_call(dev, PM_EVENT_SUSPEND, true); | 112 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
113 | |||
114 | return pm && pm->suspend_late ? pm->suspend_late(dev) : 0; | ||
146 | } | 115 | } |
147 | EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq); | 116 | EXPORT_SYMBOL_GPL(pm_generic_suspend_late); |
148 | 117 | ||
149 | /** | 118 | /** |
150 | * pm_generic_suspend - Generic suspend callback for subsystems. | 119 | * pm_generic_suspend - Generic suspend callback for subsystems. |
@@ -152,7 +121,9 @@ EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq); | |||
152 | */ | 121 | */ |
153 | int pm_generic_suspend(struct device *dev) | 122 | int pm_generic_suspend(struct device *dev) |
154 | { | 123 | { |
155 | return __pm_generic_call(dev, PM_EVENT_SUSPEND, false); | 124 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
125 | |||
126 | return pm && pm->suspend ? pm->suspend(dev) : 0; | ||
156 | } | 127 | } |
157 | EXPORT_SYMBOL_GPL(pm_generic_suspend); | 128 | EXPORT_SYMBOL_GPL(pm_generic_suspend); |
158 | 129 | ||
@@ -162,17 +133,33 @@ EXPORT_SYMBOL_GPL(pm_generic_suspend); | |||
162 | */ | 133 | */ |
163 | int pm_generic_freeze_noirq(struct device *dev) | 134 | int pm_generic_freeze_noirq(struct device *dev) |
164 | { | 135 | { |
165 | return __pm_generic_call(dev, PM_EVENT_FREEZE, true); | 136 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
137 | |||
138 | return pm && pm->freeze_noirq ? pm->freeze_noirq(dev) : 0; | ||
166 | } | 139 | } |
167 | EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq); | 140 | EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq); |
168 | 141 | ||
169 | /** | 142 | /** |
143 | * pm_generic_freeze_late - Generic freeze_late callback for subsystems. | ||
144 | * @dev: Device to freeze. | ||
145 | */ | ||
146 | int pm_generic_freeze_late(struct device *dev) | ||
147 | { | ||
148 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
149 | |||
150 | return pm && pm->freeze_late ? pm->freeze_late(dev) : 0; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(pm_generic_freeze_late); | ||
153 | |||
154 | /** | ||
170 | * pm_generic_freeze - Generic freeze callback for subsystems. | 155 | * pm_generic_freeze - Generic freeze callback for subsystems. |
171 | * @dev: Device to freeze. | 156 | * @dev: Device to freeze. |
172 | */ | 157 | */ |
173 | int pm_generic_freeze(struct device *dev) | 158 | int pm_generic_freeze(struct device *dev) |
174 | { | 159 | { |
175 | return __pm_generic_call(dev, PM_EVENT_FREEZE, false); | 160 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
161 | |||
162 | return pm && pm->freeze ? pm->freeze(dev) : 0; | ||
176 | } | 163 | } |
177 | EXPORT_SYMBOL_GPL(pm_generic_freeze); | 164 | EXPORT_SYMBOL_GPL(pm_generic_freeze); |
178 | 165 | ||
@@ -182,17 +169,33 @@ EXPORT_SYMBOL_GPL(pm_generic_freeze); | |||
182 | */ | 169 | */ |
183 | int pm_generic_poweroff_noirq(struct device *dev) | 170 | int pm_generic_poweroff_noirq(struct device *dev) |
184 | { | 171 | { |
185 | return __pm_generic_call(dev, PM_EVENT_HIBERNATE, true); | 172 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
173 | |||
174 | return pm && pm->poweroff_noirq ? pm->poweroff_noirq(dev) : 0; | ||
186 | } | 175 | } |
187 | EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq); | 176 | EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq); |
188 | 177 | ||
189 | /** | 178 | /** |
179 | * pm_generic_poweroff_late - Generic poweroff_late callback for subsystems. | ||
180 | * @dev: Device to handle. | ||
181 | */ | ||
182 | int pm_generic_poweroff_late(struct device *dev) | ||
183 | { | ||
184 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
185 | |||
186 | return pm && pm->poweroff_late ? pm->poweroff_late(dev) : 0; | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(pm_generic_poweroff_late); | ||
189 | |||
190 | /** | ||
190 | * pm_generic_poweroff - Generic poweroff callback for subsystems. | 191 | * pm_generic_poweroff - Generic poweroff callback for subsystems. |
191 | * @dev: Device to handle. | 192 | * @dev: Device to handle. |
192 | */ | 193 | */ |
193 | int pm_generic_poweroff(struct device *dev) | 194 | int pm_generic_poweroff(struct device *dev) |
194 | { | 195 | { |
195 | return __pm_generic_call(dev, PM_EVENT_HIBERNATE, false); | 196 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
197 | |||
198 | return pm && pm->poweroff ? pm->poweroff(dev) : 0; | ||
196 | } | 199 | } |
197 | EXPORT_SYMBOL_GPL(pm_generic_poweroff); | 200 | EXPORT_SYMBOL_GPL(pm_generic_poweroff); |
198 | 201 | ||
@@ -202,17 +205,33 @@ EXPORT_SYMBOL_GPL(pm_generic_poweroff); | |||
202 | */ | 205 | */ |
203 | int pm_generic_thaw_noirq(struct device *dev) | 206 | int pm_generic_thaw_noirq(struct device *dev) |
204 | { | 207 | { |
205 | return __pm_generic_call(dev, PM_EVENT_THAW, true); | 208 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
209 | |||
210 | return pm && pm->thaw_noirq ? pm->thaw_noirq(dev) : 0; | ||
206 | } | 211 | } |
207 | EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq); | 212 | EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq); |
208 | 213 | ||
209 | /** | 214 | /** |
215 | * pm_generic_thaw_early - Generic thaw_early callback for subsystems. | ||
216 | * @dev: Device to thaw. | ||
217 | */ | ||
218 | int pm_generic_thaw_early(struct device *dev) | ||
219 | { | ||
220 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
221 | |||
222 | return pm && pm->thaw_early ? pm->thaw_early(dev) : 0; | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(pm_generic_thaw_early); | ||
225 | |||
226 | /** | ||
210 | * pm_generic_thaw - Generic thaw callback for subsystems. | 227 | * pm_generic_thaw - Generic thaw callback for subsystems. |
211 | * @dev: Device to thaw. | 228 | * @dev: Device to thaw. |
212 | */ | 229 | */ |
213 | int pm_generic_thaw(struct device *dev) | 230 | int pm_generic_thaw(struct device *dev) |
214 | { | 231 | { |
215 | return __pm_generic_call(dev, PM_EVENT_THAW, false); | 232 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
233 | |||
234 | return pm && pm->thaw ? pm->thaw(dev) : 0; | ||
216 | } | 235 | } |
217 | EXPORT_SYMBOL_GPL(pm_generic_thaw); | 236 | EXPORT_SYMBOL_GPL(pm_generic_thaw); |
218 | 237 | ||
@@ -222,17 +241,33 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw); | |||
222 | */ | 241 | */ |
223 | int pm_generic_resume_noirq(struct device *dev) | 242 | int pm_generic_resume_noirq(struct device *dev) |
224 | { | 243 | { |
225 | return __pm_generic_call(dev, PM_EVENT_RESUME, true); | 244 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
245 | |||
246 | return pm && pm->resume_noirq ? pm->resume_noirq(dev) : 0; | ||
226 | } | 247 | } |
227 | EXPORT_SYMBOL_GPL(pm_generic_resume_noirq); | 248 | EXPORT_SYMBOL_GPL(pm_generic_resume_noirq); |
228 | 249 | ||
229 | /** | 250 | /** |
251 | * pm_generic_resume_early - Generic resume_early callback for subsystems. | ||
252 | * @dev: Device to resume. | ||
253 | */ | ||
254 | int pm_generic_resume_early(struct device *dev) | ||
255 | { | ||
256 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
257 | |||
258 | return pm && pm->resume_early ? pm->resume_early(dev) : 0; | ||
259 | } | ||
260 | EXPORT_SYMBOL_GPL(pm_generic_resume_early); | ||
261 | |||
262 | /** | ||
230 | * pm_generic_resume - Generic resume callback for subsystems. | 263 | * pm_generic_resume - Generic resume callback for subsystems. |
231 | * @dev: Device to resume. | 264 | * @dev: Device to resume. |
232 | */ | 265 | */ |
233 | int pm_generic_resume(struct device *dev) | 266 | int pm_generic_resume(struct device *dev) |
234 | { | 267 | { |
235 | return __pm_generic_call(dev, PM_EVENT_RESUME, false); | 268 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
269 | |||
270 | return pm && pm->resume ? pm->resume(dev) : 0; | ||
236 | } | 271 | } |
237 | EXPORT_SYMBOL_GPL(pm_generic_resume); | 272 | EXPORT_SYMBOL_GPL(pm_generic_resume); |
238 | 273 | ||
@@ -242,17 +277,33 @@ EXPORT_SYMBOL_GPL(pm_generic_resume); | |||
242 | */ | 277 | */ |
243 | int pm_generic_restore_noirq(struct device *dev) | 278 | int pm_generic_restore_noirq(struct device *dev) |
244 | { | 279 | { |
245 | return __pm_generic_call(dev, PM_EVENT_RESTORE, true); | 280 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
281 | |||
282 | return pm && pm->restore_noirq ? pm->restore_noirq(dev) : 0; | ||
246 | } | 283 | } |
247 | EXPORT_SYMBOL_GPL(pm_generic_restore_noirq); | 284 | EXPORT_SYMBOL_GPL(pm_generic_restore_noirq); |
248 | 285 | ||
249 | /** | 286 | /** |
287 | * pm_generic_restore_early - Generic restore_early callback for subsystems. | ||
288 | * @dev: Device to resume. | ||
289 | */ | ||
290 | int pm_generic_restore_early(struct device *dev) | ||
291 | { | ||
292 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
293 | |||
294 | return pm && pm->restore_early ? pm->restore_early(dev) : 0; | ||
295 | } | ||
296 | EXPORT_SYMBOL_GPL(pm_generic_restore_early); | ||
297 | |||
298 | /** | ||
250 | * pm_generic_restore - Generic restore callback for subsystems. | 299 | * pm_generic_restore - Generic restore callback for subsystems. |
251 | * @dev: Device to restore. | 300 | * @dev: Device to restore. |
252 | */ | 301 | */ |
253 | int pm_generic_restore(struct device *dev) | 302 | int pm_generic_restore(struct device *dev) |
254 | { | 303 | { |
255 | return __pm_generic_call(dev, PM_EVENT_RESTORE, false); | 304 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
305 | |||
306 | return pm && pm->restore ? pm->restore(dev) : 0; | ||
256 | } | 307 | } |
257 | EXPORT_SYMBOL_GPL(pm_generic_restore); | 308 | EXPORT_SYMBOL_GPL(pm_generic_restore); |
258 | 309 | ||