diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
| -rw-r--r-- | drivers/base/power/runtime.c | 122 |
1 files changed, 54 insertions, 68 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index cd4e100a1362..e957c496a1b1 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -153,7 +153,6 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
| 153 | return retval; | 153 | return retval; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | |||
| 157 | /** | 156 | /** |
| 158 | * rpm_idle - Notify device bus type if the device can be suspended. | 157 | * rpm_idle - Notify device bus type if the device can be suspended. |
| 159 | * @dev: Device to notify the bus type about. | 158 | * @dev: Device to notify the bus type about. |
| @@ -167,8 +166,8 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
| 167 | * This function must be called under dev->power.lock with interrupts disabled. | 166 | * This function must be called under dev->power.lock with interrupts disabled. |
| 168 | */ | 167 | */ |
| 169 | static int rpm_idle(struct device *dev, int rpmflags) | 168 | static int rpm_idle(struct device *dev, int rpmflags) |
| 170 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
| 171 | { | 169 | { |
| 170 | int (*callback)(struct device *); | ||
| 172 | int retval; | 171 | int retval; |
| 173 | 172 | ||
| 174 | retval = rpm_check_suspend_allowed(dev); | 173 | retval = rpm_check_suspend_allowed(dev); |
| @@ -214,23 +213,19 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
| 214 | 213 | ||
| 215 | dev->power.idle_notification = true; | 214 | dev->power.idle_notification = true; |
| 216 | 215 | ||
| 217 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) { | 216 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) |
| 218 | spin_unlock_irq(&dev->power.lock); | 217 | callback = dev->bus->pm->runtime_idle; |
| 219 | 218 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) | |
| 220 | dev->bus->pm->runtime_idle(dev); | 219 | callback = dev->type->pm->runtime_idle; |
| 221 | 220 | else if (dev->class && dev->class->pm) | |
| 222 | spin_lock_irq(&dev->power.lock); | 221 | callback = dev->class->pm->runtime_idle; |
| 223 | } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { | 222 | else |
| 224 | spin_unlock_irq(&dev->power.lock); | 223 | callback = NULL; |
| 225 | |||
| 226 | dev->type->pm->runtime_idle(dev); | ||
| 227 | 224 | ||
| 228 | spin_lock_irq(&dev->power.lock); | 225 | if (callback) { |
| 229 | } else if (dev->class && dev->class->pm | ||
| 230 | && dev->class->pm->runtime_idle) { | ||
| 231 | spin_unlock_irq(&dev->power.lock); | 226 | spin_unlock_irq(&dev->power.lock); |
| 232 | 227 | ||
| 233 | dev->class->pm->runtime_idle(dev); | 228 | callback(dev); |
| 234 | 229 | ||
| 235 | spin_lock_irq(&dev->power.lock); | 230 | spin_lock_irq(&dev->power.lock); |
| 236 | } | 231 | } |
| @@ -243,6 +238,29 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
| 243 | } | 238 | } |
| 244 | 239 | ||
| 245 | /** | 240 | /** |
| 241 | * rpm_callback - Run a given runtime PM callback for a given device. | ||
| 242 | * @cb: Runtime PM callback to run. | ||
| 243 | * @dev: Device to run the callback for. | ||
| 244 | */ | ||
| 245 | static int rpm_callback(int (*cb)(struct device *), struct device *dev) | ||
| 246 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | ||
| 247 | { | ||
| 248 | int retval; | ||
| 249 | |||
| 250 | if (!cb) | ||
| 251 | return -ENOSYS; | ||
| 252 | |||
| 253 | spin_unlock_irq(&dev->power.lock); | ||
| 254 | |||
| 255 | retval = cb(dev); | ||
| 256 | |||
| 257 | spin_lock_irq(&dev->power.lock); | ||
| 258 | dev->power.runtime_error = retval; | ||
| 259 | |||
| 260 | return retval; | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 246 | * rpm_suspend - Carry out run-time suspend of given device. | 264 | * rpm_suspend - Carry out run-time suspend of given device. |
| 247 | * @dev: Device to suspend. | 265 | * @dev: Device to suspend. |
| 248 | * @rpmflags: Flag bits. | 266 | * @rpmflags: Flag bits. |
| @@ -261,6 +279,7 @@ static int rpm_idle(struct device *dev, int rpmflags) | |||
| 261 | static int rpm_suspend(struct device *dev, int rpmflags) | 279 | static int rpm_suspend(struct device *dev, int rpmflags) |
| 262 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | 280 | __releases(&dev->power.lock) __acquires(&dev->power.lock) |
| 263 | { | 281 | { |
| 282 | int (*callback)(struct device *); | ||
| 264 | struct device *parent = NULL; | 283 | struct device *parent = NULL; |
| 265 | bool notify = false; | 284 | bool notify = false; |
| 266 | int retval; | 285 | int retval; |
| @@ -351,33 +370,16 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
| 351 | 370 | ||
| 352 | __update_runtime_status(dev, RPM_SUSPENDING); | 371 | __update_runtime_status(dev, RPM_SUSPENDING); |
| 353 | 372 | ||
| 354 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { | 373 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) |
| 355 | spin_unlock_irq(&dev->power.lock); | 374 | callback = dev->bus->pm->runtime_suspend; |
| 356 | 375 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend) | |
| 357 | retval = dev->bus->pm->runtime_suspend(dev); | 376 | callback = dev->type->pm->runtime_suspend; |
| 358 | 377 | else if (dev->class && dev->class->pm) | |
| 359 | spin_lock_irq(&dev->power.lock); | 378 | callback = dev->class->pm->runtime_suspend; |
| 360 | dev->power.runtime_error = retval; | 379 | else |
| 361 | } else if (dev->type && dev->type->pm | 380 | callback = NULL; |
| 362 | && dev->type->pm->runtime_suspend) { | ||
| 363 | spin_unlock_irq(&dev->power.lock); | ||
| 364 | |||
| 365 | retval = dev->type->pm->runtime_suspend(dev); | ||
| 366 | |||
| 367 | spin_lock_irq(&dev->power.lock); | ||
| 368 | dev->power.runtime_error = retval; | ||
| 369 | } else if (dev->class && dev->class->pm | ||
| 370 | && dev->class->pm->runtime_suspend) { | ||
| 371 | spin_unlock_irq(&dev->power.lock); | ||
| 372 | |||
| 373 | retval = dev->class->pm->runtime_suspend(dev); | ||
| 374 | |||
| 375 | spin_lock_irq(&dev->power.lock); | ||
| 376 | dev->power.runtime_error = retval; | ||
| 377 | } else { | ||
| 378 | retval = -ENOSYS; | ||
| 379 | } | ||
| 380 | 381 | ||
| 382 | retval = rpm_callback(callback, dev); | ||
| 381 | if (retval) { | 383 | if (retval) { |
| 382 | __update_runtime_status(dev, RPM_ACTIVE); | 384 | __update_runtime_status(dev, RPM_ACTIVE); |
| 383 | dev->power.deferred_resume = 0; | 385 | dev->power.deferred_resume = 0; |
| @@ -443,6 +445,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
| 443 | static int rpm_resume(struct device *dev, int rpmflags) | 445 | static int rpm_resume(struct device *dev, int rpmflags) |
| 444 | __releases(&dev->power.lock) __acquires(&dev->power.lock) | 446 | __releases(&dev->power.lock) __acquires(&dev->power.lock) |
| 445 | { | 447 | { |
| 448 | int (*callback)(struct device *); | ||
| 446 | struct device *parent = NULL; | 449 | struct device *parent = NULL; |
| 447 | int retval = 0; | 450 | int retval = 0; |
| 448 | 451 | ||
| @@ -563,33 +566,16 @@ static int rpm_resume(struct device *dev, int rpmflags) | |||
| 563 | 566 | ||
| 564 | __update_runtime_status(dev, RPM_RESUMING); | 567 | __update_runtime_status(dev, RPM_RESUMING); |
| 565 | 568 | ||
| 566 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) { | 569 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) |
| 567 | spin_unlock_irq(&dev->power.lock); | 570 | callback = dev->bus->pm->runtime_resume; |
| 568 | 571 | else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) | |
| 569 | retval = dev->bus->pm->runtime_resume(dev); | 572 | callback = dev->type->pm->runtime_resume; |
| 570 | 573 | else if (dev->class && dev->class->pm) | |
| 571 | spin_lock_irq(&dev->power.lock); | 574 | callback = dev->class->pm->runtime_resume; |
| 572 | dev->power.runtime_error = retval; | 575 | else |
| 573 | } else if (dev->type && dev->type->pm | 576 | callback = NULL; |
| 574 | && dev->type->pm->runtime_resume) { | ||
| 575 | spin_unlock_irq(&dev->power.lock); | ||
| 576 | |||
| 577 | retval = dev->type->pm->runtime_resume(dev); | ||
| 578 | |||
| 579 | spin_lock_irq(&dev->power.lock); | ||
| 580 | dev->power.runtime_error = retval; | ||
| 581 | } else if (dev->class && dev->class->pm | ||
| 582 | && dev->class->pm->runtime_resume) { | ||
| 583 | spin_unlock_irq(&dev->power.lock); | ||
| 584 | |||
| 585 | retval = dev->class->pm->runtime_resume(dev); | ||
| 586 | |||
| 587 | spin_lock_irq(&dev->power.lock); | ||
| 588 | dev->power.runtime_error = retval; | ||
| 589 | } else { | ||
| 590 | retval = -ENOSYS; | ||
| 591 | } | ||
| 592 | 577 | ||
| 578 | retval = rpm_callback(callback, dev); | ||
| 593 | if (retval) { | 579 | if (retval) { |
| 594 | __update_runtime_status(dev, RPM_SUSPENDED); | 580 | __update_runtime_status(dev, RPM_SUSPENDED); |
| 595 | pm_runtime_cancel_pending(dev); | 581 | pm_runtime_cancel_pending(dev); |
