diff options
-rw-r--r-- | drivers/base/power/runtime.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 04e18abb50bb..aecb2a887ed7 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -155,6 +155,31 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | /** | 157 | /** |
158 | * __rpm_callback - Run a given runtime PM callback for a given device. | ||
159 | * @cb: Runtime PM callback to run. | ||
160 | * @dev: Device to run the callback for. | ||
161 | */ | ||
162 | static int __rpm_callback(int (*cb)(struct device *), struct device *dev) | ||
163 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
164 | { | ||
165 | int retval; | ||
166 | |||
167 | if (dev->power.irq_safe) | ||
168 | spin_unlock(&dev->power.lock); | ||
169 | else | ||
170 | spin_unlock_irq(&dev->power.lock); | ||
171 | |||
172 | retval = cb(dev); | ||
173 | |||
174 | if (dev->power.irq_safe) | ||
175 | spin_lock(&dev->power.lock); | ||
176 | else | ||
177 | spin_lock_irq(&dev->power.lock); | ||
178 | |||
179 | return retval; | ||
180 | } | ||
181 | |||
182 | /** | ||
158 | * rpm_idle - Notify device bus type if the device can be suspended. | 183 | * rpm_idle - Notify device bus type if the device can be suspended. |
159 | * @dev: Device to notify the bus type about. | 184 | * @dev: Device to notify the bus type about. |
160 | * @rpmflags: Flag bits. | 185 | * @rpmflags: Flag bits. |
@@ -225,19 +250,8 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
225 | else | 250 | else |
226 | callback = NULL; | 251 | callback = NULL; |
227 | 252 | ||
228 | if (callback) { | 253 | if (callback) |
229 | if (dev->power.irq_safe) | 254 | __rpm_callback(callback, dev); |
230 | spin_unlock(&dev->power.lock); | ||
231 | else | ||
232 | spin_unlock_irq(&dev->power.lock); | ||
233 | |||
234 | callback(dev); | ||
235 | |||
236 | if (dev->power.irq_safe) | ||
237 | spin_lock(&dev->power.lock); | ||
238 | else | ||
239 | spin_lock_irq(&dev->power.lock); | ||
240 | } | ||
241 | 255 | ||
242 | dev->power.idle_notification = false; | 256 | dev->power.idle_notification = false; |
243 | wake_up_all(&dev->power.wait_queue); | 257 | wake_up_all(&dev->power.wait_queue); |
@@ -252,22 +266,14 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
252 | * @dev: Device to run the callback for. | 266 | * @dev: Device to run the callback for. |
253 | */ | 267 | */ |
254 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) | 268 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) |
255 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
256 | { | 269 | { |
257 | int retval; | 270 | int retval; |
258 | 271 | ||
259 | if (!cb) | 272 | if (!cb) |
260 | return -ENOSYS; | 273 | return -ENOSYS; |
261 | 274 | ||
262 | if (dev->power.irq_safe) { | 275 | retval = __rpm_callback(cb, dev); |
263 | retval = cb(dev); | ||
264 | } else { | ||
265 | spin_unlock_irq(&dev->power.lock); | ||
266 | |||
267 | retval = cb(dev); | ||
268 | 276 | ||
269 | spin_lock_irq(&dev->power.lock); | ||
270 | } | ||
271 | dev->power.runtime_error = retval; | 277 | dev->power.runtime_error = retval; |
272 | return retval != -EACCES ? retval : -EIO; | 278 | return retval != -EACCES ? retval : -EIO; |
273 | } | 279 | } |
@@ -347,6 +353,15 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
347 | goto out; | 353 | goto out; |
348 | } | 354 | } |
349 | 355 | ||
356 | if (dev->power.irq_safe) { | ||
357 | spin_unlock(&dev->power.lock); | ||
358 | |||
359 | cpu_relax(); | ||
360 | |||
361 | spin_lock(&dev->power.lock); | ||
362 | goto repeat; | ||
363 | } | ||
364 | |||
350 | /* Wait for the other suspend running in parallel with us. */ | 365 | /* Wait for the other suspend running in parallel with us. */ |
351 | for (;;) { | 366 | for (;;) { |
352 | prepare_to_wait(&dev->power.wait_queue, &wait, | 367 | prepare_to_wait(&dev->power.wait_queue, &wait, |
@@ -496,6 +511,15 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
496 | goto out; | 511 | goto out; |
497 | } | 512 | } |
498 | 513 | ||
514 | if (dev->power.irq_safe) { | ||
515 | spin_unlock(&dev->power.lock); | ||
516 | |||
517 | cpu_relax(); | ||
518 | |||
519 | spin_lock(&dev->power.lock); | ||
520 | goto repeat; | ||
521 | } | ||
522 | |||
499 | /* Wait for the operation carried out in parallel with us. */ | 523 | /* Wait for the operation carried out in parallel with us. */ |
500 | for (;;) { | 524 | for (;;) { |
501 | prepare_to_wait(&dev->power.wait_queue, &wait, | 525 | prepare_to_wait(&dev->power.wait_queue, &wait, |