aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/generic_ops.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-07-01 16:12:59 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-07-02 08:29:55 -0400
commite5291928839877f8e73c2643ee1d3fe0bcdcaf5c (patch)
treedf733cad71610a2f5ce283dcca5f2ad1d83bdf1f /drivers/base/power/generic_ops.c
parentf721889ff65afa6243c463832c74dee3bed418d5 (diff)
PM: Introduce generic "noirq" callback routines for subsystems (v2)
Introduce generic "noirq" power management callback routines for subsystems in addition to the "regular" generic PM callback routines. The new routines will be used, among other things, for implementing system-wide PM transitions support for generic PM domains. 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.c98
1 files changed, 83 insertions, 15 deletions
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index cb3bb368681c..9508df71274b 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -94,12 +94,13 @@ int pm_generic_prepare(struct device *dev)
94 * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback. 94 * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
95 * @dev: Device to handle. 95 * @dev: Device to handle.
96 * @event: PM transition of the system under way. 96 * @event: PM transition of the system under way.
97 * @bool: Whether or not this is the "noirq" stage.
97 * 98 *
98 * If the device has not been suspended at run time, execute the 99 * If the device has not been suspended at run time, execute the
99 * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and 100 * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
100 * return its error code. Otherwise, return zero. 101 * return its error code. Otherwise, return zero.
101 */ 102 */
102static int __pm_generic_call(struct device *dev, int event) 103static int __pm_generic_call(struct device *dev, int event, bool noirq)
103{ 104{
104 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 105 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
105 int (*callback)(struct device *); 106 int (*callback)(struct device *);
@@ -109,16 +110,16 @@ static int __pm_generic_call(struct device *dev, int event)
109 110
110 switch (event) { 111 switch (event) {
111 case PM_EVENT_SUSPEND: 112 case PM_EVENT_SUSPEND:
112 callback = pm->suspend; 113 callback = noirq ? pm->suspend_noirq : pm->suspend;
113 break; 114 break;
114 case PM_EVENT_FREEZE: 115 case PM_EVENT_FREEZE:
115 callback = pm->freeze; 116 callback = noirq ? pm->freeze_noirq : pm->freeze;
116 break; 117 break;
117 case PM_EVENT_HIBERNATE: 118 case PM_EVENT_HIBERNATE:
118 callback = pm->poweroff; 119 callback = noirq ? pm->poweroff_noirq : pm->poweroff;
119 break; 120 break;
120 case PM_EVENT_THAW: 121 case PM_EVENT_THAW:
121 callback = pm->thaw; 122 callback = noirq ? pm->thaw_noirq : pm->thaw;
122 break; 123 break;
123 default: 124 default:
124 callback = NULL; 125 callback = NULL;
@@ -129,42 +130,82 @@ static int __pm_generic_call(struct device *dev, int event)
129} 130}
130 131
131/** 132/**
133 * pm_generic_suspend_noirq - Generic suspend_noirq callback for subsystems.
134 * @dev: Device to suspend.
135 */
136int pm_generic_suspend_noirq(struct device *dev)
137{
138 return __pm_generic_call(dev, PM_EVENT_SUSPEND, true);
139}
140EXPORT_SYMBOL_GPL(pm_generic_suspend_noirq);
141
142/**
132 * pm_generic_suspend - Generic suspend callback for subsystems. 143 * pm_generic_suspend - Generic suspend callback for subsystems.
133 * @dev: Device to suspend. 144 * @dev: Device to suspend.
134 */ 145 */
135int pm_generic_suspend(struct device *dev) 146int pm_generic_suspend(struct device *dev)
136{ 147{
137 return __pm_generic_call(dev, PM_EVENT_SUSPEND); 148 return __pm_generic_call(dev, PM_EVENT_SUSPEND, false);
138} 149}
139EXPORT_SYMBOL_GPL(pm_generic_suspend); 150EXPORT_SYMBOL_GPL(pm_generic_suspend);
140 151
141/** 152/**
153 * pm_generic_freeze_noirq - Generic freeze_noirq callback for subsystems.
154 * @dev: Device to freeze.
155 */
156int pm_generic_freeze_noirq(struct device *dev)
157{
158 return __pm_generic_call(dev, PM_EVENT_FREEZE, true);
159}
160EXPORT_SYMBOL_GPL(pm_generic_freeze_noirq);
161
162/**
142 * pm_generic_freeze - Generic freeze callback for subsystems. 163 * pm_generic_freeze - Generic freeze callback for subsystems.
143 * @dev: Device to freeze. 164 * @dev: Device to freeze.
144 */ 165 */
145int pm_generic_freeze(struct device *dev) 166int pm_generic_freeze(struct device *dev)
146{ 167{
147 return __pm_generic_call(dev, PM_EVENT_FREEZE); 168 return __pm_generic_call(dev, PM_EVENT_FREEZE, false);
148} 169}
149EXPORT_SYMBOL_GPL(pm_generic_freeze); 170EXPORT_SYMBOL_GPL(pm_generic_freeze);
150 171
151/** 172/**
173 * pm_generic_poweroff_noirq - Generic poweroff_noirq callback for subsystems.
174 * @dev: Device to handle.
175 */
176int pm_generic_poweroff_noirq(struct device *dev)
177{
178 return __pm_generic_call(dev, PM_EVENT_HIBERNATE, true);
179}
180EXPORT_SYMBOL_GPL(pm_generic_poweroff_noirq);
181
182/**
152 * pm_generic_poweroff - Generic poweroff callback for subsystems. 183 * pm_generic_poweroff - Generic poweroff callback for subsystems.
153 * @dev: Device to handle. 184 * @dev: Device to handle.
154 */ 185 */
155int pm_generic_poweroff(struct device *dev) 186int pm_generic_poweroff(struct device *dev)
156{ 187{
157 return __pm_generic_call(dev, PM_EVENT_HIBERNATE); 188 return __pm_generic_call(dev, PM_EVENT_HIBERNATE, false);
158} 189}
159EXPORT_SYMBOL_GPL(pm_generic_poweroff); 190EXPORT_SYMBOL_GPL(pm_generic_poweroff);
160 191
161/** 192/**
193 * pm_generic_thaw_noirq - Generic thaw_noirq callback for subsystems.
194 * @dev: Device to thaw.
195 */
196int pm_generic_thaw_noirq(struct device *dev)
197{
198 return __pm_generic_call(dev, PM_EVENT_THAW, true);
199}
200EXPORT_SYMBOL_GPL(pm_generic_thaw_noirq);
201
202/**
162 * pm_generic_thaw - Generic thaw callback for subsystems. 203 * pm_generic_thaw - Generic thaw callback for subsystems.
163 * @dev: Device to thaw. 204 * @dev: Device to thaw.
164 */ 205 */
165int pm_generic_thaw(struct device *dev) 206int pm_generic_thaw(struct device *dev)
166{ 207{
167 return __pm_generic_call(dev, PM_EVENT_THAW); 208 return __pm_generic_call(dev, PM_EVENT_THAW, false);
168} 209}
169EXPORT_SYMBOL_GPL(pm_generic_thaw); 210EXPORT_SYMBOL_GPL(pm_generic_thaw);
170 211
@@ -172,12 +213,13 @@ EXPORT_SYMBOL_GPL(pm_generic_thaw);
172 * __pm_generic_resume - Generic resume/restore callback for subsystems. 213 * __pm_generic_resume - Generic resume/restore callback for subsystems.
173 * @dev: Device to handle. 214 * @dev: Device to handle.
174 * @event: PM transition of the system under way. 215 * @event: PM transition of the system under way.
216 * @bool: Whether or not this is the "noirq" stage.
175 * 217 *
176 * Execute the resume/resotre callback provided by the @dev's driver, if 218 * Execute the resume/resotre callback provided by the @dev's driver, if
177 * defined. If it returns 0, change the device's runtime PM status to 'active'. 219 * defined. If it returns 0, change the device's runtime PM status to 'active'.
178 * Return the callback's error code. 220 * Return the callback's error code.
179 */ 221 */
180static int __pm_generic_resume(struct device *dev, int event) 222static int __pm_generic_resume(struct device *dev, int event, bool noirq)
181{ 223{
182 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 224 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
183 int (*callback)(struct device *); 225 int (*callback)(struct device *);
@@ -188,10 +230,10 @@ static int __pm_generic_resume(struct device *dev, int event)
188 230
189 switch (event) { 231 switch (event) {
190 case PM_EVENT_RESUME: 232 case PM_EVENT_RESUME:
191 callback = pm->resume; 233 callback = noirq ? pm->resume_noirq : pm->resume;
192 break; 234 break;
193 case PM_EVENT_RESTORE: 235 case PM_EVENT_RESTORE:
194 callback = pm->restore; 236 callback = noirq ? pm->restore_noirq : pm->restore;
195 break; 237 break;
196 default: 238 default:
197 callback = NULL; 239 callback = NULL;
@@ -202,7 +244,7 @@ static int __pm_generic_resume(struct device *dev, int event)
202 return 0; 244 return 0;
203 245
204 ret = callback(dev); 246 ret = callback(dev);
205 if (!ret && pm_runtime_enabled(dev)) { 247 if (!ret && !noirq && pm_runtime_enabled(dev)) {
206 pm_runtime_disable(dev); 248 pm_runtime_disable(dev);
207 pm_runtime_set_active(dev); 249 pm_runtime_set_active(dev);
208 pm_runtime_enable(dev); 250 pm_runtime_enable(dev);
@@ -212,22 +254,42 @@ static int __pm_generic_resume(struct device *dev, int event)
212} 254}
213 255
214/** 256/**
257 * pm_generic_resume_noirq - Generic resume_noirq callback for subsystems.
258 * @dev: Device to resume.
259 */
260int pm_generic_resume_noirq(struct device *dev)
261{
262 return __pm_generic_resume(dev, PM_EVENT_RESUME, true);
263}
264EXPORT_SYMBOL_GPL(pm_generic_resume_noirq);
265
266/**
215 * pm_generic_resume - Generic resume callback for subsystems. 267 * pm_generic_resume - Generic resume callback for subsystems.
216 * @dev: Device to resume. 268 * @dev: Device to resume.
217 */ 269 */
218int pm_generic_resume(struct device *dev) 270int pm_generic_resume(struct device *dev)
219{ 271{
220 return __pm_generic_resume(dev, PM_EVENT_RESUME); 272 return __pm_generic_resume(dev, PM_EVENT_RESUME, false);
221} 273}
222EXPORT_SYMBOL_GPL(pm_generic_resume); 274EXPORT_SYMBOL_GPL(pm_generic_resume);
223 275
224/** 276/**
277 * pm_generic_restore_noirq - Generic restore_noirq callback for subsystems.
278 * @dev: Device to restore.
279 */
280int pm_generic_restore_noirq(struct device *dev)
281{
282 return __pm_generic_resume(dev, PM_EVENT_RESTORE, true);
283}
284EXPORT_SYMBOL_GPL(pm_generic_restore_noirq);
285
286/**
225 * pm_generic_restore - Generic restore callback for subsystems. 287 * pm_generic_restore - Generic restore callback for subsystems.
226 * @dev: Device to restore. 288 * @dev: Device to restore.
227 */ 289 */
228int pm_generic_restore(struct device *dev) 290int pm_generic_restore(struct device *dev)
229{ 291{
230 return __pm_generic_resume(dev, PM_EVENT_RESTORE); 292 return __pm_generic_resume(dev, PM_EVENT_RESTORE, false);
231} 293}
232EXPORT_SYMBOL_GPL(pm_generic_restore); 294EXPORT_SYMBOL_GPL(pm_generic_restore);
233 295
@@ -256,11 +318,17 @@ struct dev_pm_ops generic_subsys_pm_ops = {
256#ifdef CONFIG_PM_SLEEP 318#ifdef CONFIG_PM_SLEEP
257 .prepare = pm_generic_prepare, 319 .prepare = pm_generic_prepare,
258 .suspend = pm_generic_suspend, 320 .suspend = pm_generic_suspend,
321 .suspend_noirq = pm_generic_suspend_noirq,
259 .resume = pm_generic_resume, 322 .resume = pm_generic_resume,
323 .resume_noirq = pm_generic_resume_noirq,
260 .freeze = pm_generic_freeze, 324 .freeze = pm_generic_freeze,
325 .freeze_noirq = pm_generic_freeze_noirq,
261 .thaw = pm_generic_thaw, 326 .thaw = pm_generic_thaw,
327 .thaw_noirq = pm_generic_thaw_noirq,
262 .poweroff = pm_generic_poweroff, 328 .poweroff = pm_generic_poweroff,
329 .poweroff_noirq = pm_generic_poweroff_noirq,
263 .restore = pm_generic_restore, 330 .restore = pm_generic_restore,
331 .restore_noirq = pm_generic_restore_noirq,
264 .complete = pm_generic_complete, 332 .complete = pm_generic_complete,
265#endif 333#endif
266#ifdef CONFIG_PM_RUNTIME 334#ifdef CONFIG_PM_RUNTIME