diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-06-17 19:55:13 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-06-17 19:55:13 -0400 |
| commit | 9d066a252786e1a18484a6283f82614d42a9f4ac (patch) | |
| tree | 72188d2f86b3d0c4100257c8d5734f2c648a8bc7 /drivers/base/power | |
| parent | 79ee2e8f730411a30b271d5f9cdeae189fa66174 (diff) | |
| parent | b00345d1994d588fa2687e1238fcd542f0320cba (diff) | |
Merge branches 'pm-opp' and 'pm-cpufreq-fixes'
* pm-opp:
PM / OPP: Add 'UNKNOWN' status for shared_opp in struct opp_table
* pm-cpufreq-fixes:
cpufreq: intel_pstate: Adjust _PSS[0] freqeuency if needed
Diffstat (limited to 'drivers/base/power')
| -rw-r--r-- | drivers/base/power/clock_ops.c | 2 | ||||
| -rw-r--r-- | drivers/base/power/domain.c | 145 | ||||
| -rw-r--r-- | drivers/base/power/domain_governor.c | 20 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 23 | ||||
| -rw-r--r-- | drivers/base/power/runtime.c | 9 |
5 files changed, 85 insertions, 114 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 0e64a1b5e62a..3657ac1cb801 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c | |||
| @@ -159,7 +159,7 @@ int of_pm_clk_add_clks(struct device *dev) | |||
| 159 | 159 | ||
| 160 | count = of_count_phandle_with_args(dev->of_node, "clocks", | 160 | count = of_count_phandle_with_args(dev->of_node, "clocks", |
| 161 | "#clock-cells"); | 161 | "#clock-cells"); |
| 162 | if (count == 0) | 162 | if (count <= 0) |
| 163 | return -ENODEV; | 163 | return -ENODEV; |
| 164 | 164 | ||
| 165 | clks = kcalloc(count, sizeof(*clks), GFP_KERNEL); | 165 | clks = kcalloc(count, sizeof(*clks), GFP_KERNEL); |
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 56705b52758e..de23b648fce3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -229,17 +229,6 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth) | |||
| 229 | return ret; | 229 | return ret; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) | ||
| 233 | { | ||
| 234 | return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); | ||
| 235 | } | ||
| 236 | |||
| 237 | static int genpd_restore_dev(struct generic_pm_domain *genpd, | ||
| 238 | struct device *dev) | ||
| 239 | { | ||
| 240 | return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev); | ||
| 241 | } | ||
| 242 | |||
| 243 | static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, | 232 | static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, |
| 244 | unsigned long val, void *ptr) | 233 | unsigned long val, void *ptr) |
| 245 | { | 234 | { |
| @@ -372,17 +361,63 @@ static void genpd_power_off_work_fn(struct work_struct *work) | |||
| 372 | } | 361 | } |
| 373 | 362 | ||
| 374 | /** | 363 | /** |
| 375 | * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. | 364 | * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks |
| 365 | * @dev: Device to handle. | ||
| 366 | */ | ||
| 367 | static int __genpd_runtime_suspend(struct device *dev) | ||
| 368 | { | ||
| 369 | int (*cb)(struct device *__dev); | ||
| 370 | |||
| 371 | if (dev->type && dev->type->pm) | ||
| 372 | cb = dev->type->pm->runtime_suspend; | ||
| 373 | else if (dev->class && dev->class->pm) | ||
| 374 | cb = dev->class->pm->runtime_suspend; | ||
| 375 | else if (dev->bus && dev->bus->pm) | ||
| 376 | cb = dev->bus->pm->runtime_suspend; | ||
| 377 | else | ||
| 378 | cb = NULL; | ||
| 379 | |||
| 380 | if (!cb && dev->driver && dev->driver->pm) | ||
| 381 | cb = dev->driver->pm->runtime_suspend; | ||
| 382 | |||
| 383 | return cb ? cb(dev) : 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | /** | ||
| 387 | * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks | ||
| 388 | * @dev: Device to handle. | ||
| 389 | */ | ||
| 390 | static int __genpd_runtime_resume(struct device *dev) | ||
| 391 | { | ||
| 392 | int (*cb)(struct device *__dev); | ||
| 393 | |||
| 394 | if (dev->type && dev->type->pm) | ||
| 395 | cb = dev->type->pm->runtime_resume; | ||
| 396 | else if (dev->class && dev->class->pm) | ||
| 397 | cb = dev->class->pm->runtime_resume; | ||
| 398 | else if (dev->bus && dev->bus->pm) | ||
| 399 | cb = dev->bus->pm->runtime_resume; | ||
| 400 | else | ||
| 401 | cb = NULL; | ||
| 402 | |||
| 403 | if (!cb && dev->driver && dev->driver->pm) | ||
| 404 | cb = dev->driver->pm->runtime_resume; | ||
| 405 | |||
| 406 | return cb ? cb(dev) : 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | /** | ||
| 410 | * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain. | ||
| 376 | * @dev: Device to suspend. | 411 | * @dev: Device to suspend. |
| 377 | * | 412 | * |
| 378 | * Carry out a runtime suspend of a device under the assumption that its | 413 | * Carry out a runtime suspend of a device under the assumption that its |
| 379 | * pm_domain field points to the domain member of an object of type | 414 | * pm_domain field points to the domain member of an object of type |
| 380 | * struct generic_pm_domain representing a PM domain consisting of I/O devices. | 415 | * struct generic_pm_domain representing a PM domain consisting of I/O devices. |
| 381 | */ | 416 | */ |
| 382 | static int pm_genpd_runtime_suspend(struct device *dev) | 417 | static int genpd_runtime_suspend(struct device *dev) |
| 383 | { | 418 | { |
| 384 | struct generic_pm_domain *genpd; | 419 | struct generic_pm_domain *genpd; |
| 385 | bool (*stop_ok)(struct device *__dev); | 420 | bool (*suspend_ok)(struct device *__dev); |
| 386 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; | 421 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; |
| 387 | bool runtime_pm = pm_runtime_enabled(dev); | 422 | bool runtime_pm = pm_runtime_enabled(dev); |
| 388 | ktime_t time_start; | 423 | ktime_t time_start; |
| @@ -401,21 +436,21 @@ static int pm_genpd_runtime_suspend(struct device *dev) | |||
| 401 | * runtime PM is disabled. Under these circumstances, we shall skip | 436 | * runtime PM is disabled. Under these circumstances, we shall skip |
| 402 | * validating/measuring the PM QoS latency. | 437 | * validating/measuring the PM QoS latency. |
| 403 | */ | 438 | */ |
| 404 | stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; | 439 | suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL; |
| 405 | if (runtime_pm && stop_ok && !stop_ok(dev)) | 440 | if (runtime_pm && suspend_ok && !suspend_ok(dev)) |
| 406 | return -EBUSY; | 441 | return -EBUSY; |
| 407 | 442 | ||
| 408 | /* Measure suspend latency. */ | 443 | /* Measure suspend latency. */ |
| 409 | if (runtime_pm) | 444 | if (runtime_pm) |
| 410 | time_start = ktime_get(); | 445 | time_start = ktime_get(); |
| 411 | 446 | ||
| 412 | ret = genpd_save_dev(genpd, dev); | 447 | ret = __genpd_runtime_suspend(dev); |
| 413 | if (ret) | 448 | if (ret) |
| 414 | return ret; | 449 | return ret; |
| 415 | 450 | ||
| 416 | ret = genpd_stop_dev(genpd, dev); | 451 | ret = genpd_stop_dev(genpd, dev); |
| 417 | if (ret) { | 452 | if (ret) { |
| 418 | genpd_restore_dev(genpd, dev); | 453 | __genpd_runtime_resume(dev); |
| 419 | return ret; | 454 | return ret; |
| 420 | } | 455 | } |
| 421 | 456 | ||
| @@ -446,14 +481,14 @@ static int pm_genpd_runtime_suspend(struct device *dev) | |||
| 446 | } | 481 | } |
| 447 | 482 | ||
| 448 | /** | 483 | /** |
| 449 | * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain. | 484 | * genpd_runtime_resume - Resume a device belonging to I/O PM domain. |
| 450 | * @dev: Device to resume. | 485 | * @dev: Device to resume. |
| 451 | * | 486 | * |
| 452 | * Carry out a runtime resume of a device under the assumption that its | 487 | * Carry out a runtime resume of a device under the assumption that its |
| 453 | * pm_domain field points to the domain member of an object of type | 488 | * pm_domain field points to the domain member of an object of type |
| 454 | * struct generic_pm_domain representing a PM domain consisting of I/O devices. | 489 | * struct generic_pm_domain representing a PM domain consisting of I/O devices. |
| 455 | */ | 490 | */ |
| 456 | static int pm_genpd_runtime_resume(struct device *dev) | 491 | static int genpd_runtime_resume(struct device *dev) |
| 457 | { | 492 | { |
| 458 | struct generic_pm_domain *genpd; | 493 | struct generic_pm_domain *genpd; |
| 459 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; | 494 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; |
| @@ -491,7 +526,7 @@ static int pm_genpd_runtime_resume(struct device *dev) | |||
| 491 | if (ret) | 526 | if (ret) |
| 492 | goto err_poweroff; | 527 | goto err_poweroff; |
| 493 | 528 | ||
| 494 | ret = genpd_restore_dev(genpd, dev); | 529 | ret = __genpd_runtime_resume(dev); |
| 495 | if (ret) | 530 | if (ret) |
| 496 | goto err_stop; | 531 | goto err_stop; |
| 497 | 532 | ||
| @@ -695,15 +730,6 @@ static int pm_genpd_prepare(struct device *dev) | |||
| 695 | * at this point and a system wakeup event should be reported if it's | 730 | * at this point and a system wakeup event should be reported if it's |
| 696 | * set up to wake up the system from sleep states. | 731 | * set up to wake up the system from sleep states. |
| 697 | */ | 732 | */ |
| 698 | pm_runtime_get_noresume(dev); | ||
| 699 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) | ||
| 700 | pm_wakeup_event(dev, 0); | ||
| 701 | |||
| 702 | if (pm_wakeup_pending()) { | ||
| 703 | pm_runtime_put(dev); | ||
| 704 | return -EBUSY; | ||
| 705 | } | ||
| 706 | |||
| 707 | if (resume_needed(dev, genpd)) | 733 | if (resume_needed(dev, genpd)) |
| 708 | pm_runtime_resume(dev); | 734 | pm_runtime_resume(dev); |
| 709 | 735 | ||
| @@ -716,10 +742,8 @@ static int pm_genpd_prepare(struct device *dev) | |||
| 716 | 742 | ||
| 717 | mutex_unlock(&genpd->lock); | 743 | mutex_unlock(&genpd->lock); |
| 718 | 744 | ||
| 719 | if (genpd->suspend_power_off) { | 745 | if (genpd->suspend_power_off) |
| 720 | pm_runtime_put_noidle(dev); | ||
| 721 | return 0; | 746 | return 0; |
| 722 | } | ||
| 723 | 747 | ||
| 724 | /* | 748 | /* |
| 725 | * The PM domain must be in the GPD_STATE_ACTIVE state at this point, | 749 | * The PM domain must be in the GPD_STATE_ACTIVE state at this point, |
| @@ -741,7 +765,6 @@ static int pm_genpd_prepare(struct device *dev) | |||
| 741 | pm_runtime_enable(dev); | 765 | pm_runtime_enable(dev); |
| 742 | } | 766 | } |
| 743 | 767 | ||
| 744 | pm_runtime_put(dev); | ||
| 745 | return ret; | 768 | return ret; |
| 746 | } | 769 | } |
| 747 | 770 | ||
| @@ -1427,54 +1450,6 @@ out: | |||
| 1427 | } | 1450 | } |
| 1428 | EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); | 1451 | EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); |
| 1429 | 1452 | ||
| 1430 | /* Default device callbacks for generic PM domains. */ | ||
| 1431 | |||
| 1432 | /** | ||
| 1433 | * pm_genpd_default_save_state - Default "save device state" for PM domains. | ||
| 1434 | * @dev: Device to handle. | ||
| 1435 | */ | ||
| 1436 | static int pm_genpd_default_save_state(struct device *dev) | ||
| 1437 | { | ||
| 1438 | int (*cb)(struct device *__dev); | ||
| 1439 | |||
| 1440 | if (dev->type && dev->type->pm) | ||
| 1441 | cb = dev->type->pm->runtime_suspend; | ||
| 1442 | else if (dev->class && dev->class->pm) | ||
| 1443 | cb = dev->class->pm->runtime_suspend; | ||
| 1444 | else if (dev->bus && dev->bus->pm) | ||
| 1445 | cb = dev->bus->pm->runtime_suspend; | ||
| 1446 | else | ||
| 1447 | cb = NULL; | ||
| 1448 | |||
| 1449 | if (!cb && dev->driver && dev->driver->pm) | ||
| 1450 | cb = dev->driver->pm->runtime_suspend; | ||
| 1451 | |||
| 1452 | return cb ? cb(dev) : 0; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | /** | ||
| 1456 | * pm_genpd_default_restore_state - Default PM domains "restore device state". | ||
| 1457 | * @dev: Device to handle. | ||
| 1458 | */ | ||
| 1459 | static int pm_genpd_default_restore_state(struct device *dev) | ||
| 1460 | { | ||
| 1461 | int (*cb)(struct device *__dev); | ||
| 1462 | |||
| 1463 | if (dev->type && dev->type->pm) | ||
| 1464 | cb = dev->type->pm->runtime_resume; | ||
| 1465 | else if (dev->class && dev->class->pm) | ||
| 1466 | cb = dev->class->pm->runtime_resume; | ||
| 1467 | else if (dev->bus && dev->bus->pm) | ||
| 1468 | cb = dev->bus->pm->runtime_resume; | ||
| 1469 | else | ||
| 1470 | cb = NULL; | ||
| 1471 | |||
| 1472 | if (!cb && dev->driver && dev->driver->pm) | ||
| 1473 | cb = dev->driver->pm->runtime_resume; | ||
| 1474 | |||
| 1475 | return cb ? cb(dev) : 0; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | /** | 1453 | /** |
| 1479 | * pm_genpd_init - Initialize a generic I/O PM domain object. | 1454 | * pm_genpd_init - Initialize a generic I/O PM domain object. |
| 1480 | * @genpd: PM domain object to initialize. | 1455 | * @genpd: PM domain object to initialize. |
| @@ -1498,8 +1473,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd, | |||
| 1498 | genpd->device_count = 0; | 1473 | genpd->device_count = 0; |
| 1499 | genpd->max_off_time_ns = -1; | 1474 | genpd->max_off_time_ns = -1; |
| 1500 | genpd->max_off_time_changed = true; | 1475 | genpd->max_off_time_changed = true; |
| 1501 | genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; | 1476 | genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; |
| 1502 | genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; | 1477 | genpd->domain.ops.runtime_resume = genpd_runtime_resume; |
| 1503 | genpd->domain.ops.prepare = pm_genpd_prepare; | 1478 | genpd->domain.ops.prepare = pm_genpd_prepare; |
| 1504 | genpd->domain.ops.suspend = pm_genpd_suspend; | 1479 | genpd->domain.ops.suspend = pm_genpd_suspend; |
| 1505 | genpd->domain.ops.suspend_late = pm_genpd_suspend_late; | 1480 | genpd->domain.ops.suspend_late = pm_genpd_suspend_late; |
| @@ -1520,8 +1495,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd, | |||
| 1520 | genpd->domain.ops.restore_early = pm_genpd_resume_early; | 1495 | genpd->domain.ops.restore_early = pm_genpd_resume_early; |
| 1521 | genpd->domain.ops.restore = pm_genpd_resume; | 1496 | genpd->domain.ops.restore = pm_genpd_resume; |
| 1522 | genpd->domain.ops.complete = pm_genpd_complete; | 1497 | genpd->domain.ops.complete = pm_genpd_complete; |
| 1523 | genpd->dev_ops.save_state = pm_genpd_default_save_state; | ||
| 1524 | genpd->dev_ops.restore_state = pm_genpd_default_restore_state; | ||
| 1525 | 1498 | ||
| 1526 | if (genpd->flags & GENPD_FLAG_PM_CLK) { | 1499 | if (genpd->flags & GENPD_FLAG_PM_CLK) { |
| 1527 | genpd->dev_ops.stop = pm_clk_suspend; | 1500 | genpd->dev_ops.stop = pm_clk_suspend; |
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 00a5436dd44b..2e0fce711135 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
| @@ -37,10 +37,10 @@ static int dev_update_qos_constraint(struct device *dev, void *data) | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | * default_stop_ok - Default PM domain governor routine for stopping devices. | 40 | * default_suspend_ok - Default PM domain governor routine to suspend devices. |
| 41 | * @dev: Device to check. | 41 | * @dev: Device to check. |
| 42 | */ | 42 | */ |
| 43 | static bool default_stop_ok(struct device *dev) | 43 | static bool default_suspend_ok(struct device *dev) |
| 44 | { | 44 | { |
| 45 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; | 45 | struct gpd_timing_data *td = &dev_gpd_data(dev)->td; |
| 46 | unsigned long flags; | 46 | unsigned long flags; |
| @@ -51,13 +51,13 @@ static bool default_stop_ok(struct device *dev) | |||
| 51 | spin_lock_irqsave(&dev->power.lock, flags); | 51 | spin_lock_irqsave(&dev->power.lock, flags); |
| 52 | 52 | ||
| 53 | if (!td->constraint_changed) { | 53 | if (!td->constraint_changed) { |
| 54 | bool ret = td->cached_stop_ok; | 54 | bool ret = td->cached_suspend_ok; |
| 55 | 55 | ||
| 56 | spin_unlock_irqrestore(&dev->power.lock, flags); | 56 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 57 | return ret; | 57 | return ret; |
| 58 | } | 58 | } |
| 59 | td->constraint_changed = false; | 59 | td->constraint_changed = false; |
| 60 | td->cached_stop_ok = false; | 60 | td->cached_suspend_ok = false; |
| 61 | td->effective_constraint_ns = -1; | 61 | td->effective_constraint_ns = -1; |
| 62 | constraint_ns = __dev_pm_qos_read_value(dev); | 62 | constraint_ns = __dev_pm_qos_read_value(dev); |
| 63 | 63 | ||
| @@ -83,13 +83,13 @@ static bool default_stop_ok(struct device *dev) | |||
| 83 | return false; | 83 | return false; |
| 84 | } | 84 | } |
| 85 | td->effective_constraint_ns = constraint_ns; | 85 | td->effective_constraint_ns = constraint_ns; |
| 86 | td->cached_stop_ok = constraint_ns >= 0; | 86 | td->cached_suspend_ok = constraint_ns >= 0; |
| 87 | 87 | ||
| 88 | /* | 88 | /* |
| 89 | * The children have been suspended already, so we don't need to take | 89 | * The children have been suspended already, so we don't need to take |
| 90 | * their stop latencies into account here. | 90 | * their suspend latencies into account here. |
| 91 | */ | 91 | */ |
| 92 | return td->cached_stop_ok; | 92 | return td->cached_suspend_ok; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /** | 95 | /** |
| @@ -150,7 +150,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, | |||
| 150 | */ | 150 | */ |
| 151 | td = &to_gpd_data(pdd)->td; | 151 | td = &to_gpd_data(pdd)->td; |
| 152 | constraint_ns = td->effective_constraint_ns; | 152 | constraint_ns = td->effective_constraint_ns; |
| 153 | /* default_stop_ok() need not be called before us. */ | 153 | /* default_suspend_ok() need not be called before us. */ |
| 154 | if (constraint_ns < 0) { | 154 | if (constraint_ns < 0) { |
| 155 | constraint_ns = dev_pm_qos_read_value(pdd->dev); | 155 | constraint_ns = dev_pm_qos_read_value(pdd->dev); |
| 156 | constraint_ns *= NSEC_PER_USEC; | 156 | constraint_ns *= NSEC_PER_USEC; |
| @@ -227,7 +227,7 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain) | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | struct dev_power_governor simple_qos_governor = { | 229 | struct dev_power_governor simple_qos_governor = { |
| 230 | .stop_ok = default_stop_ok, | 230 | .suspend_ok = default_suspend_ok, |
| 231 | .power_down_ok = default_power_down_ok, | 231 | .power_down_ok = default_power_down_ok, |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| @@ -236,5 +236,5 @@ struct dev_power_governor simple_qos_governor = { | |||
| 236 | */ | 236 | */ |
| 237 | struct dev_power_governor pm_domain_always_on_gov = { | 237 | struct dev_power_governor pm_domain_always_on_gov = { |
| 238 | .power_down_ok = always_on_power_down_ok, | 238 | .power_down_ok = always_on_power_down_ok, |
| 239 | .stop_ok = default_stop_ok, | 239 | .suspend_ok = default_suspend_ok, |
| 240 | }; | 240 | }; |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 6e7c3ccea24b..e44944f4be77 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -1267,14 +1267,15 @@ int dpm_suspend_late(pm_message_t state) | |||
| 1267 | error = device_suspend_late(dev); | 1267 | error = device_suspend_late(dev); |
| 1268 | 1268 | ||
| 1269 | mutex_lock(&dpm_list_mtx); | 1269 | mutex_lock(&dpm_list_mtx); |
| 1270 | if (!list_empty(&dev->power.entry)) | ||
| 1271 | list_move(&dev->power.entry, &dpm_late_early_list); | ||
| 1272 | |||
| 1270 | if (error) { | 1273 | if (error) { |
| 1271 | pm_dev_err(dev, state, " late", error); | 1274 | pm_dev_err(dev, state, " late", error); |
| 1272 | dpm_save_failed_dev(dev_name(dev)); | 1275 | dpm_save_failed_dev(dev_name(dev)); |
| 1273 | put_device(dev); | 1276 | put_device(dev); |
| 1274 | break; | 1277 | break; |
| 1275 | } | 1278 | } |
| 1276 | if (!list_empty(&dev->power.entry)) | ||
| 1277 | list_move(&dev->power.entry, &dpm_late_early_list); | ||
| 1278 | put_device(dev); | 1279 | put_device(dev); |
| 1279 | 1280 | ||
| 1280 | if (async_error) | 1281 | if (async_error) |
| @@ -1556,7 +1557,6 @@ int dpm_suspend(pm_message_t state) | |||
| 1556 | static int device_prepare(struct device *dev, pm_message_t state) | 1557 | static int device_prepare(struct device *dev, pm_message_t state) |
| 1557 | { | 1558 | { |
| 1558 | int (*callback)(struct device *) = NULL; | 1559 | int (*callback)(struct device *) = NULL; |
| 1559 | char *info = NULL; | ||
| 1560 | int ret = 0; | 1560 | int ret = 0; |
| 1561 | 1561 | ||
| 1562 | if (dev->power.syscore) | 1562 | if (dev->power.syscore) |
| @@ -1579,24 +1579,17 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
| 1579 | goto unlock; | 1579 | goto unlock; |
| 1580 | } | 1580 | } |
| 1581 | 1581 | ||
| 1582 | if (dev->pm_domain) { | 1582 | if (dev->pm_domain) |
| 1583 | info = "preparing power domain "; | ||
| 1584 | callback = dev->pm_domain->ops.prepare; | 1583 | callback = dev->pm_domain->ops.prepare; |
| 1585 | } else if (dev->type && dev->type->pm) { | 1584 | else if (dev->type && dev->type->pm) |
| 1586 | info = "preparing type "; | ||
| 1587 | callback = dev->type->pm->prepare; | 1585 | callback = dev->type->pm->prepare; |
| 1588 | } else if (dev->class && dev->class->pm) { | 1586 | else if (dev->class && dev->class->pm) |
| 1589 | info = "preparing class "; | ||
| 1590 | callback = dev->class->pm->prepare; | 1587 | callback = dev->class->pm->prepare; |
| 1591 | } else if (dev->bus && dev->bus->pm) { | 1588 | else if (dev->bus && dev->bus->pm) |
| 1592 | info = "preparing bus "; | ||
| 1593 | callback = dev->bus->pm->prepare; | 1589 | callback = dev->bus->pm->prepare; |
| 1594 | } | ||
| 1595 | 1590 | ||
| 1596 | if (!callback && dev->driver && dev->driver->pm) { | 1591 | if (!callback && dev->driver && dev->driver->pm) |
| 1597 | info = "preparing driver "; | ||
| 1598 | callback = dev->driver->pm->prepare; | 1592 | callback = dev->driver->pm->prepare; |
| 1599 | } | ||
| 1600 | 1593 | ||
| 1601 | if (callback) | 1594 | if (callback) |
| 1602 | ret = callback(dev); | 1595 | ret = callback(dev); |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 4c7055009bd6..b74690418504 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -1506,11 +1506,16 @@ int pm_runtime_force_resume(struct device *dev) | |||
| 1506 | goto out; | 1506 | goto out; |
| 1507 | } | 1507 | } |
| 1508 | 1508 | ||
| 1509 | ret = callback(dev); | 1509 | ret = pm_runtime_set_active(dev); |
| 1510 | if (ret) | 1510 | if (ret) |
| 1511 | goto out; | 1511 | goto out; |
| 1512 | 1512 | ||
| 1513 | pm_runtime_set_active(dev); | 1513 | ret = callback(dev); |
| 1514 | if (ret) { | ||
| 1515 | pm_runtime_set_suspended(dev); | ||
| 1516 | goto out; | ||
| 1517 | } | ||
| 1518 | |||
| 1514 | pm_runtime_mark_last_busy(dev); | 1519 | pm_runtime_mark_last_busy(dev); |
| 1515 | out: | 1520 | out: |
| 1516 | pm_runtime_enable(dev); | 1521 | pm_runtime_enable(dev); |
