diff options
| -rw-r--r-- | drivers/base/power/main.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7e79201b09bb..6efef9fb23a1 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -495,12 +495,12 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) | |||
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | /** | 497 | /** |
| 498 | * __device_resume - Execute "resume" callbacks for given device. | 498 | * device_resume - Execute "resume" callbacks for given device. |
| 499 | * @dev: Device to handle. | 499 | * @dev: Device to handle. |
| 500 | * @state: PM transition of the system being carried out. | 500 | * @state: PM transition of the system being carried out. |
| 501 | * @async: If true, the device is being resumed asynchronously. | 501 | * @async: If true, the device is being resumed asynchronously. |
| 502 | */ | 502 | */ |
| 503 | static int __device_resume(struct device *dev, pm_message_t state, bool async) | 503 | static int device_resume(struct device *dev, pm_message_t state, bool async) |
| 504 | { | 504 | { |
| 505 | int error = 0; | 505 | int error = 0; |
| 506 | 506 | ||
| @@ -510,6 +510,8 @@ static int __device_resume(struct device *dev, pm_message_t state, bool async) | |||
| 510 | dpm_wait(dev->parent, async); | 510 | dpm_wait(dev->parent, async); |
| 511 | down(&dev->sem); | 511 | down(&dev->sem); |
| 512 | 512 | ||
| 513 | dev->power.status = DPM_RESUMING; | ||
| 514 | |||
| 513 | if (dev->bus) { | 515 | if (dev->bus) { |
| 514 | if (dev->bus->pm) { | 516 | if (dev->bus->pm) { |
| 515 | pm_dev_dbg(dev, state, ""); | 517 | pm_dev_dbg(dev, state, ""); |
| @@ -553,24 +555,16 @@ static void async_resume(void *data, async_cookie_t cookie) | |||
| 553 | struct device *dev = (struct device *)data; | 555 | struct device *dev = (struct device *)data; |
| 554 | int error; | 556 | int error; |
| 555 | 557 | ||
| 556 | error = __device_resume(dev, pm_transition, true); | 558 | error = device_resume(dev, pm_transition, true); |
| 557 | if (error) | 559 | if (error) |
| 558 | pm_dev_err(dev, pm_transition, " async", error); | 560 | pm_dev_err(dev, pm_transition, " async", error); |
| 559 | put_device(dev); | 561 | put_device(dev); |
| 560 | } | 562 | } |
| 561 | 563 | ||
| 562 | static int device_resume(struct device *dev) | 564 | static bool is_async(struct device *dev) |
| 563 | { | 565 | { |
| 564 | INIT_COMPLETION(dev->power.completion); | 566 | return dev->power.async_suspend && pm_async_enabled |
| 565 | 567 | && !pm_trace_is_enabled(); | |
| 566 | if (pm_async_enabled && dev->power.async_suspend | ||
| 567 | && !pm_trace_is_enabled()) { | ||
| 568 | get_device(dev); | ||
| 569 | async_schedule(async_resume, dev); | ||
| 570 | return 0; | ||
| 571 | } | ||
| 572 | |||
| 573 | return __device_resume(dev, pm_transition, false); | ||
| 574 | } | 568 | } |
| 575 | 569 | ||
| 576 | /** | 570 | /** |
| @@ -583,22 +577,33 @@ static int device_resume(struct device *dev) | |||
| 583 | static void dpm_resume(pm_message_t state) | 577 | static void dpm_resume(pm_message_t state) |
| 584 | { | 578 | { |
| 585 | struct list_head list; | 579 | struct list_head list; |
| 580 | struct device *dev; | ||
| 586 | ktime_t starttime = ktime_get(); | 581 | ktime_t starttime = ktime_get(); |
| 587 | 582 | ||
| 588 | INIT_LIST_HEAD(&list); | 583 | INIT_LIST_HEAD(&list); |
| 589 | mutex_lock(&dpm_list_mtx); | 584 | mutex_lock(&dpm_list_mtx); |
| 590 | pm_transition = state; | 585 | pm_transition = state; |
| 591 | while (!list_empty(&dpm_list)) { | ||
| 592 | struct device *dev = to_device(dpm_list.next); | ||
| 593 | 586 | ||
| 587 | list_for_each_entry(dev, &dpm_list, power.entry) { | ||
| 588 | if (dev->power.status < DPM_OFF) | ||
| 589 | continue; | ||
| 590 | |||
| 591 | INIT_COMPLETION(dev->power.completion); | ||
| 592 | if (is_async(dev)) { | ||
| 593 | get_device(dev); | ||
| 594 | async_schedule(async_resume, dev); | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | while (!list_empty(&dpm_list)) { | ||
| 599 | dev = to_device(dpm_list.next); | ||
| 594 | get_device(dev); | 600 | get_device(dev); |
| 595 | if (dev->power.status >= DPM_OFF) { | 601 | if (dev->power.status >= DPM_OFF && !is_async(dev)) { |
| 596 | int error; | 602 | int error; |
| 597 | 603 | ||
| 598 | dev->power.status = DPM_RESUMING; | ||
| 599 | mutex_unlock(&dpm_list_mtx); | 604 | mutex_unlock(&dpm_list_mtx); |
| 600 | 605 | ||
| 601 | error = device_resume(dev); | 606 | error = device_resume(dev, state, false); |
| 602 | 607 | ||
| 603 | mutex_lock(&dpm_list_mtx); | 608 | mutex_lock(&dpm_list_mtx); |
| 604 | if (error) | 609 | if (error) |
