diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/power/domain.c | 77 | ||||
| -rw-r--r-- | drivers/base/power/domain_governor.c | 67 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 70 | ||||
| -rw-r--r-- | drivers/base/power/wakeup.c | 6 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle-exynos.c | 2 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 19 |
6 files changed, 190 insertions, 51 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 96a6dc9d305c..ecac03dcc9b2 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
| 23 | #include <linux/suspend.h> | 23 | #include <linux/suspend.h> |
| 24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
| 25 | #include <linux/cpu.h> | ||
| 25 | 26 | ||
| 26 | #include "power.h" | 27 | #include "power.h" |
| 27 | 28 | ||
| @@ -128,6 +129,7 @@ static const struct genpd_lock_ops genpd_spin_ops = { | |||
| 128 | #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE) | 129 | #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE) |
| 129 | #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON) | 130 | #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON) |
| 130 | #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP) | 131 | #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP) |
| 132 | #define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN) | ||
| 131 | 133 | ||
| 132 | static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, | 134 | static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, |
| 133 | const struct generic_pm_domain *genpd) | 135 | const struct generic_pm_domain *genpd) |
| @@ -1454,6 +1456,56 @@ static void genpd_free_dev_data(struct device *dev, | |||
| 1454 | dev_pm_put_subsys_data(dev); | 1456 | dev_pm_put_subsys_data(dev); |
| 1455 | } | 1457 | } |
| 1456 | 1458 | ||
| 1459 | static void __genpd_update_cpumask(struct generic_pm_domain *genpd, | ||
| 1460 | int cpu, bool set, unsigned int depth) | ||
| 1461 | { | ||
| 1462 | struct gpd_link *link; | ||
| 1463 | |||
| 1464 | if (!genpd_is_cpu_domain(genpd)) | ||
| 1465 | return; | ||
| 1466 | |||
| 1467 | list_for_each_entry(link, &genpd->slave_links, slave_node) { | ||
| 1468 | struct generic_pm_domain *master = link->master; | ||
| 1469 | |||
| 1470 | genpd_lock_nested(master, depth + 1); | ||
| 1471 | __genpd_update_cpumask(master, cpu, set, depth + 1); | ||
| 1472 | genpd_unlock(master); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | if (set) | ||
| 1476 | cpumask_set_cpu(cpu, genpd->cpus); | ||
| 1477 | else | ||
| 1478 | cpumask_clear_cpu(cpu, genpd->cpus); | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | static void genpd_update_cpumask(struct generic_pm_domain *genpd, | ||
| 1482 | struct device *dev, bool set) | ||
| 1483 | { | ||
| 1484 | int cpu; | ||
| 1485 | |||
| 1486 | if (!genpd_is_cpu_domain(genpd)) | ||
| 1487 | return; | ||
| 1488 | |||
| 1489 | for_each_possible_cpu(cpu) { | ||
| 1490 | if (get_cpu_device(cpu) == dev) { | ||
| 1491 | __genpd_update_cpumask(genpd, cpu, set, 0); | ||
| 1492 | return; | ||
| 1493 | } | ||
| 1494 | } | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static void genpd_set_cpumask(struct generic_pm_domain *genpd, | ||
| 1498 | struct device *dev) | ||
| 1499 | { | ||
| 1500 | genpd_update_cpumask(genpd, dev, true); | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | static void genpd_clear_cpumask(struct generic_pm_domain *genpd, | ||
| 1504 | struct device *dev) | ||
| 1505 | { | ||
| 1506 | genpd_update_cpumask(genpd, dev, false); | ||
| 1507 | } | ||
| 1508 | |||
| 1457 | static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, | 1509 | static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, |
| 1458 | struct gpd_timing_data *td) | 1510 | struct gpd_timing_data *td) |
| 1459 | { | 1511 | { |
| @@ -1475,6 +1527,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, | |||
| 1475 | 1527 | ||
| 1476 | genpd_lock(genpd); | 1528 | genpd_lock(genpd); |
| 1477 | 1529 | ||
| 1530 | genpd_set_cpumask(genpd, dev); | ||
| 1478 | dev_pm_domain_set(dev, &genpd->domain); | 1531 | dev_pm_domain_set(dev, &genpd->domain); |
| 1479 | 1532 | ||
| 1480 | genpd->device_count++; | 1533 | genpd->device_count++; |
| @@ -1532,6 +1585,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, | |||
| 1532 | genpd->device_count--; | 1585 | genpd->device_count--; |
| 1533 | genpd->max_off_time_changed = true; | 1586 | genpd->max_off_time_changed = true; |
| 1534 | 1587 | ||
| 1588 | genpd_clear_cpumask(genpd, dev); | ||
| 1535 | dev_pm_domain_set(dev, NULL); | 1589 | dev_pm_domain_set(dev, NULL); |
| 1536 | 1590 | ||
| 1537 | list_del_init(&pdd->list_node); | 1591 | list_del_init(&pdd->list_node); |
| @@ -1686,6 +1740,12 @@ out: | |||
| 1686 | } | 1740 | } |
| 1687 | EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); | 1741 | EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); |
| 1688 | 1742 | ||
| 1743 | static void genpd_free_default_power_state(struct genpd_power_state *states, | ||
| 1744 | unsigned int state_count) | ||
| 1745 | { | ||
| 1746 | kfree(states); | ||
| 1747 | } | ||
| 1748 | |||
| 1689 | static int genpd_set_default_power_state(struct generic_pm_domain *genpd) | 1749 | static int genpd_set_default_power_state(struct generic_pm_domain *genpd) |
| 1690 | { | 1750 | { |
| 1691 | struct genpd_power_state *state; | 1751 | struct genpd_power_state *state; |
| @@ -1696,7 +1756,7 @@ static int genpd_set_default_power_state(struct generic_pm_domain *genpd) | |||
| 1696 | 1756 | ||
| 1697 | genpd->states = state; | 1757 | genpd->states = state; |
| 1698 | genpd->state_count = 1; | 1758 | genpd->state_count = 1; |
| 1699 | genpd->free = state; | 1759 | genpd->free_states = genpd_free_default_power_state; |
| 1700 | 1760 | ||
| 1701 | return 0; | 1761 | return 0; |
| 1702 | } | 1762 | } |
| @@ -1762,11 +1822,18 @@ int pm_genpd_init(struct generic_pm_domain *genpd, | |||
| 1762 | if (genpd_is_always_on(genpd) && !genpd_status_on(genpd)) | 1822 | if (genpd_is_always_on(genpd) && !genpd_status_on(genpd)) |
| 1763 | return -EINVAL; | 1823 | return -EINVAL; |
| 1764 | 1824 | ||
| 1825 | if (genpd_is_cpu_domain(genpd) && | ||
| 1826 | !zalloc_cpumask_var(&genpd->cpus, GFP_KERNEL)) | ||
| 1827 | return -ENOMEM; | ||
| 1828 | |||
| 1765 | /* Use only one "off" state if there were no states declared */ | 1829 | /* Use only one "off" state if there were no states declared */ |
| 1766 | if (genpd->state_count == 0) { | 1830 | if (genpd->state_count == 0) { |
| 1767 | ret = genpd_set_default_power_state(genpd); | 1831 | ret = genpd_set_default_power_state(genpd); |
| 1768 | if (ret) | 1832 | if (ret) { |
| 1833 | if (genpd_is_cpu_domain(genpd)) | ||
| 1834 | free_cpumask_var(genpd->cpus); | ||
| 1769 | return ret; | 1835 | return ret; |
| 1836 | } | ||
| 1770 | } else if (!gov && genpd->state_count > 1) { | 1837 | } else if (!gov && genpd->state_count > 1) { |
| 1771 | pr_warn("%s: no governor for states\n", genpd->name); | 1838 | pr_warn("%s: no governor for states\n", genpd->name); |
| 1772 | } | 1839 | } |
| @@ -1812,7 +1879,11 @@ static int genpd_remove(struct generic_pm_domain *genpd) | |||
| 1812 | list_del(&genpd->gpd_list_node); | 1879 | list_del(&genpd->gpd_list_node); |
| 1813 | genpd_unlock(genpd); | 1880 | genpd_unlock(genpd); |
| 1814 | cancel_work_sync(&genpd->power_off_work); | 1881 | cancel_work_sync(&genpd->power_off_work); |
| 1815 | kfree(genpd->free); | 1882 | if (genpd_is_cpu_domain(genpd)) |
| 1883 | free_cpumask_var(genpd->cpus); | ||
| 1884 | if (genpd->free_states) | ||
| 1885 | genpd->free_states(genpd->states, genpd->state_count); | ||
| 1886 | |||
| 1816 | pr_debug("%s: removed %s\n", __func__, genpd->name); | 1887 | pr_debug("%s: removed %s\n", __func__, genpd->name); |
| 1817 | 1888 | ||
| 1818 | return 0; | 1889 | return 0; |
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 4d07e38a8247..7912bc957244 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
| @@ -10,6 +10,9 @@ | |||
| 10 | #include <linux/pm_domain.h> | 10 | #include <linux/pm_domain.h> |
| 11 | #include <linux/pm_qos.h> | 11 | #include <linux/pm_qos.h> |
| 12 | #include <linux/hrtimer.h> | 12 | #include <linux/hrtimer.h> |
| 13 | #include <linux/cpuidle.h> | ||
| 14 | #include <linux/cpumask.h> | ||
| 15 | #include <linux/ktime.h> | ||
| 13 | 16 | ||
| 14 | static int dev_update_qos_constraint(struct device *dev, void *data) | 17 | static int dev_update_qos_constraint(struct device *dev, void *data) |
| 15 | { | 18 | { |
| @@ -210,8 +213,10 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
| 210 | struct generic_pm_domain *genpd = pd_to_genpd(pd); | 213 | struct generic_pm_domain *genpd = pd_to_genpd(pd); |
| 211 | struct gpd_link *link; | 214 | struct gpd_link *link; |
| 212 | 215 | ||
| 213 | if (!genpd->max_off_time_changed) | 216 | if (!genpd->max_off_time_changed) { |
| 217 | genpd->state_idx = genpd->cached_power_down_state_idx; | ||
| 214 | return genpd->cached_power_down_ok; | 218 | return genpd->cached_power_down_ok; |
| 219 | } | ||
| 215 | 220 | ||
| 216 | /* | 221 | /* |
| 217 | * We have to invalidate the cached results for the masters, so | 222 | * We have to invalidate the cached results for the masters, so |
| @@ -236,6 +241,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) | |||
| 236 | genpd->state_idx--; | 241 | genpd->state_idx--; |
| 237 | } | 242 | } |
| 238 | 243 | ||
| 244 | genpd->cached_power_down_state_idx = genpd->state_idx; | ||
| 239 | return genpd->cached_power_down_ok; | 245 | return genpd->cached_power_down_ok; |
| 240 | } | 246 | } |
| 241 | 247 | ||
| @@ -244,6 +250,65 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain) | |||
| 244 | return false; | 250 | return false; |
| 245 | } | 251 | } |
| 246 | 252 | ||
| 253 | #ifdef CONFIG_CPU_IDLE | ||
| 254 | static bool cpu_power_down_ok(struct dev_pm_domain *pd) | ||
| 255 | { | ||
| 256 | struct generic_pm_domain *genpd = pd_to_genpd(pd); | ||
| 257 | struct cpuidle_device *dev; | ||
| 258 | ktime_t domain_wakeup, next_hrtimer; | ||
| 259 | s64 idle_duration_ns; | ||
| 260 | int cpu, i; | ||
| 261 | |||
| 262 | /* Validate dev PM QoS constraints. */ | ||
| 263 | if (!default_power_down_ok(pd)) | ||
| 264 | return false; | ||
| 265 | |||
| 266 | if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN)) | ||
| 267 | return true; | ||
| 268 | |||
| 269 | /* | ||
| 270 | * Find the next wakeup for any of the online CPUs within the PM domain | ||
| 271 | * and its subdomains. Note, we only need the genpd->cpus, as it already | ||
| 272 | * contains a mask of all CPUs from subdomains. | ||
| 273 | */ | ||
| 274 | domain_wakeup = ktime_set(KTIME_SEC_MAX, 0); | ||
| 275 | for_each_cpu_and(cpu, genpd->cpus, cpu_online_mask) { | ||
| 276 | dev = per_cpu(cpuidle_devices, cpu); | ||
| 277 | if (dev) { | ||
| 278 | next_hrtimer = READ_ONCE(dev->next_hrtimer); | ||
| 279 | if (ktime_before(next_hrtimer, domain_wakeup)) | ||
| 280 | domain_wakeup = next_hrtimer; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | /* The minimum idle duration is from now - until the next wakeup. */ | ||
| 285 | idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, ktime_get())); | ||
| 286 | if (idle_duration_ns <= 0) | ||
| 287 | return false; | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Find the deepest idle state that has its residency value satisfied | ||
| 291 | * and by also taking into account the power off latency for the state. | ||
| 292 | * Start at the state picked by the dev PM QoS constraint validation. | ||
| 293 | */ | ||
| 294 | i = genpd->state_idx; | ||
| 295 | do { | ||
| 296 | if (idle_duration_ns >= (genpd->states[i].residency_ns + | ||
| 297 | genpd->states[i].power_off_latency_ns)) { | ||
| 298 | genpd->state_idx = i; | ||
| 299 | return true; | ||
| 300 | } | ||
| 301 | } while (--i >= 0); | ||
| 302 | |||
| 303 | return false; | ||
| 304 | } | ||
| 305 | |||
| 306 | struct dev_power_governor pm_domain_cpu_gov = { | ||
| 307 | .suspend_ok = default_suspend_ok, | ||
| 308 | .power_down_ok = cpu_power_down_ok, | ||
| 309 | }; | ||
| 310 | #endif | ||
| 311 | |||
| 247 | struct dev_power_governor simple_qos_governor = { | 312 | struct dev_power_governor simple_qos_governor = { |
| 248 | .suspend_ok = default_suspend_ok, | 313 | .suspend_ok = default_suspend_ok, |
| 249 | .power_down_ok = default_power_down_ok, | 314 | .power_down_ok = default_power_down_ok, |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f80d298de3fa..43e863cc0c1b 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -478,7 +478,7 @@ struct dpm_watchdog { | |||
| 478 | 478 | ||
| 479 | /** | 479 | /** |
| 480 | * dpm_watchdog_handler - Driver suspend / resume watchdog handler. | 480 | * dpm_watchdog_handler - Driver suspend / resume watchdog handler. |
| 481 | * @data: Watchdog object address. | 481 | * @t: The timer that PM watchdog depends on. |
| 482 | * | 482 | * |
| 483 | * Called when a driver has timed out suspending or resuming. | 483 | * Called when a driver has timed out suspending or resuming. |
| 484 | * There's not much we can do here to recover so panic() to | 484 | * There's not much we can do here to recover so panic() to |
| @@ -706,6 +706,19 @@ static bool is_async(struct device *dev) | |||
| 706 | && !pm_trace_is_enabled(); | 706 | && !pm_trace_is_enabled(); |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | static bool dpm_async_fn(struct device *dev, async_func_t func) | ||
| 710 | { | ||
| 711 | reinit_completion(&dev->power.completion); | ||
| 712 | |||
| 713 | if (is_async(dev)) { | ||
| 714 | get_device(dev); | ||
| 715 | async_schedule(func, dev); | ||
| 716 | return true; | ||
| 717 | } | ||
| 718 | |||
| 719 | return false; | ||
| 720 | } | ||
| 721 | |||
| 709 | static void async_resume_noirq(void *data, async_cookie_t cookie) | 722 | static void async_resume_noirq(void *data, async_cookie_t cookie) |
| 710 | { | 723 | { |
| 711 | struct device *dev = (struct device *)data; | 724 | struct device *dev = (struct device *)data; |
| @@ -732,13 +745,8 @@ void dpm_noirq_resume_devices(pm_message_t state) | |||
| 732 | * in case the starting of async threads is | 745 | * in case the starting of async threads is |
| 733 | * delayed by non-async resuming devices. | 746 | * delayed by non-async resuming devices. |
| 734 | */ | 747 | */ |
| 735 | list_for_each_entry(dev, &dpm_noirq_list, power.entry) { | 748 | list_for_each_entry(dev, &dpm_noirq_list, power.entry) |
| 736 | reinit_completion(&dev->power.completion); | 749 | dpm_async_fn(dev, async_resume_noirq); |
| 737 | if (is_async(dev)) { | ||
| 738 | get_device(dev); | ||
| 739 | async_schedule_dev(async_resume_noirq, dev); | ||
| 740 | } | ||
| 741 | } | ||
| 742 | 750 | ||
| 743 | while (!list_empty(&dpm_noirq_list)) { | 751 | while (!list_empty(&dpm_noirq_list)) { |
| 744 | dev = to_device(dpm_noirq_list.next); | 752 | dev = to_device(dpm_noirq_list.next); |
| @@ -889,13 +897,8 @@ void dpm_resume_early(pm_message_t state) | |||
| 889 | * in case the starting of async threads is | 897 | * in case the starting of async threads is |
| 890 | * delayed by non-async resuming devices. | 898 | * delayed by non-async resuming devices. |
| 891 | */ | 899 | */ |
| 892 | list_for_each_entry(dev, &dpm_late_early_list, power.entry) { | 900 | list_for_each_entry(dev, &dpm_late_early_list, power.entry) |
| 893 | reinit_completion(&dev->power.completion); | 901 | dpm_async_fn(dev, async_resume_early); |
| 894 | if (is_async(dev)) { | ||
| 895 | get_device(dev); | ||
| 896 | async_schedule_dev(async_resume_early, dev); | ||
| 897 | } | ||
| 898 | } | ||
| 899 | 902 | ||
| 900 | while (!list_empty(&dpm_late_early_list)) { | 903 | while (!list_empty(&dpm_late_early_list)) { |
| 901 | dev = to_device(dpm_late_early_list.next); | 904 | dev = to_device(dpm_late_early_list.next); |
| @@ -1053,13 +1056,8 @@ void dpm_resume(pm_message_t state) | |||
| 1053 | pm_transition = state; | 1056 | pm_transition = state; |
| 1054 | async_error = 0; | 1057 | async_error = 0; |
| 1055 | 1058 | ||
| 1056 | list_for_each_entry(dev, &dpm_suspended_list, power.entry) { | 1059 | list_for_each_entry(dev, &dpm_suspended_list, power.entry) |
| 1057 | reinit_completion(&dev->power.completion); | 1060 | dpm_async_fn(dev, async_resume); |
| 1058 | if (is_async(dev)) { | ||
| 1059 | get_device(dev); | ||
| 1060 | async_schedule_dev(async_resume, dev); | ||
| 1061 | } | ||
| 1062 | } | ||
| 1063 | 1061 | ||
| 1064 | while (!list_empty(&dpm_suspended_list)) { | 1062 | while (!list_empty(&dpm_suspended_list)) { |
| 1065 | dev = to_device(dpm_suspended_list.next); | 1063 | dev = to_device(dpm_suspended_list.next); |
| @@ -1373,13 +1371,9 @@ static void async_suspend_noirq(void *data, async_cookie_t cookie) | |||
| 1373 | 1371 | ||
| 1374 | static int device_suspend_noirq(struct device *dev) | 1372 | static int device_suspend_noirq(struct device *dev) |
| 1375 | { | 1373 | { |
| 1376 | reinit_completion(&dev->power.completion); | 1374 | if (dpm_async_fn(dev, async_suspend_noirq)) |
| 1377 | |||
| 1378 | if (is_async(dev)) { | ||
| 1379 | get_device(dev); | ||
| 1380 | async_schedule_dev(async_suspend_noirq, dev); | ||
| 1381 | return 0; | 1375 | return 0; |
| 1382 | } | 1376 | |
| 1383 | return __device_suspend_noirq(dev, pm_transition, false); | 1377 | return __device_suspend_noirq(dev, pm_transition, false); |
| 1384 | } | 1378 | } |
| 1385 | 1379 | ||
| @@ -1576,13 +1570,8 @@ static void async_suspend_late(void *data, async_cookie_t cookie) | |||
| 1576 | 1570 | ||
| 1577 | static int device_suspend_late(struct device *dev) | 1571 | static int device_suspend_late(struct device *dev) |
| 1578 | { | 1572 | { |
| 1579 | reinit_completion(&dev->power.completion); | 1573 | if (dpm_async_fn(dev, async_suspend_late)) |
| 1580 | |||
| 1581 | if (is_async(dev)) { | ||
| 1582 | get_device(dev); | ||
| 1583 | async_schedule_dev(async_suspend_late, dev); | ||
| 1584 | return 0; | 1574 | return 0; |
| 1585 | } | ||
| 1586 | 1575 | ||
| 1587 | return __device_suspend_late(dev, pm_transition, false); | 1576 | return __device_suspend_late(dev, pm_transition, false); |
| 1588 | } | 1577 | } |
| @@ -1747,6 +1736,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
| 1747 | if (dev->power.syscore) | 1736 | if (dev->power.syscore) |
| 1748 | goto Complete; | 1737 | goto Complete; |
| 1749 | 1738 | ||
| 1739 | /* Avoid direct_complete to let wakeup_path propagate. */ | ||
| 1740 | if (device_may_wakeup(dev) || dev->power.wakeup_path) | ||
| 1741 | dev->power.direct_complete = false; | ||
| 1742 | |||
| 1750 | if (dev->power.direct_complete) { | 1743 | if (dev->power.direct_complete) { |
| 1751 | if (pm_runtime_status_suspended(dev)) { | 1744 | if (pm_runtime_status_suspended(dev)) { |
| 1752 | pm_runtime_disable(dev); | 1745 | pm_runtime_disable(dev); |
| @@ -1842,13 +1835,8 @@ static void async_suspend(void *data, async_cookie_t cookie) | |||
| 1842 | 1835 | ||
| 1843 | static int device_suspend(struct device *dev) | 1836 | static int device_suspend(struct device *dev) |
| 1844 | { | 1837 | { |
| 1845 | reinit_completion(&dev->power.completion); | 1838 | if (dpm_async_fn(dev, async_suspend)) |
| 1846 | |||
| 1847 | if (is_async(dev)) { | ||
| 1848 | get_device(dev); | ||
| 1849 | async_schedule_dev(async_suspend, dev); | ||
| 1850 | return 0; | 1839 | return 0; |
| 1851 | } | ||
| 1852 | 1840 | ||
| 1853 | return __device_suspend(dev, pm_transition, false); | 1841 | return __device_suspend(dev, pm_transition, false); |
| 1854 | } | 1842 | } |
| @@ -2069,8 +2057,8 @@ EXPORT_SYMBOL_GPL(__suspend_report_result); | |||
| 2069 | 2057 | ||
| 2070 | /** | 2058 | /** |
| 2071 | * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete. | 2059 | * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete. |
| 2072 | * @dev: Device to wait for. | ||
| 2073 | * @subordinate: Device that needs to wait for @dev. | 2060 | * @subordinate: Device that needs to wait for @dev. |
| 2061 | * @dev: Device to wait for. | ||
| 2074 | */ | 2062 | */ |
| 2075 | int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) | 2063 | int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) |
| 2076 | { | 2064 | { |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index bb1ae175fae1..23c243a4c675 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
| @@ -804,7 +804,7 @@ void pm_print_active_wakeup_sources(void) | |||
| 804 | srcuidx = srcu_read_lock(&wakeup_srcu); | 804 | srcuidx = srcu_read_lock(&wakeup_srcu); |
| 805 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) { | 805 | list_for_each_entry_rcu(ws, &wakeup_sources, entry) { |
| 806 | if (ws->active) { | 806 | if (ws->active) { |
| 807 | pr_debug("active wakeup source: %s\n", ws->name); | 807 | pm_pr_dbg("active wakeup source: %s\n", ws->name); |
| 808 | active = 1; | 808 | active = 1; |
| 809 | } else if (!active && | 809 | } else if (!active && |
| 810 | (!last_activity_ws || | 810 | (!last_activity_ws || |
| @@ -815,7 +815,7 @@ void pm_print_active_wakeup_sources(void) | |||
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | if (!active && last_activity_ws) | 817 | if (!active && last_activity_ws) |
| 818 | pr_debug("last active wakeup source: %s\n", | 818 | pm_pr_dbg("last active wakeup source: %s\n", |
| 819 | last_activity_ws->name); | 819 | last_activity_ws->name); |
| 820 | srcu_read_unlock(&wakeup_srcu, srcuidx); | 820 | srcu_read_unlock(&wakeup_srcu, srcuidx); |
| 821 | } | 821 | } |
| @@ -845,7 +845,7 @@ bool pm_wakeup_pending(void) | |||
| 845 | raw_spin_unlock_irqrestore(&events_lock, flags); | 845 | raw_spin_unlock_irqrestore(&events_lock, flags); |
| 846 | 846 | ||
| 847 | if (ret) { | 847 | if (ret) { |
| 848 | pr_debug("Wakeup pending, aborting suspend\n"); | 848 | pm_pr_dbg("Wakeup pending, aborting suspend\n"); |
| 849 | pm_print_active_wakeup_sources(); | 849 | pm_print_active_wakeup_sources(); |
| 850 | } | 850 | } |
| 851 | 851 | ||
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c index 0171a6e190d7..f7199a35cbb6 100644 --- a/drivers/cpuidle/cpuidle-exynos.c +++ b/drivers/cpuidle/cpuidle-exynos.c | |||
| @@ -84,7 +84,7 @@ static struct cpuidle_driver exynos_idle_driver = { | |||
| 84 | [1] = { | 84 | [1] = { |
| 85 | .enter = exynos_enter_lowpower, | 85 | .enter = exynos_enter_lowpower, |
| 86 | .exit_latency = 300, | 86 | .exit_latency = 300, |
| 87 | .target_residency = 100000, | 87 | .target_residency = 10000, |
| 88 | .name = "C1", | 88 | .name = "C1", |
| 89 | .desc = "ARM power down", | 89 | .desc = "ARM power down", |
| 90 | }, | 90 | }, |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 7f108309e871..0f4b7c45df3e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -328,9 +328,23 @@ int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, | |||
| 328 | int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, | 328 | int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, |
| 329 | int index) | 329 | int index) |
| 330 | { | 330 | { |
| 331 | int ret = 0; | ||
| 332 | |||
| 333 | /* | ||
| 334 | * Store the next hrtimer, which becomes either next tick or the next | ||
| 335 | * timer event, whatever expires first. Additionally, to make this data | ||
| 336 | * useful for consumers outside cpuidle, we rely on that the governor's | ||
| 337 | * ->select() callback have decided, whether to stop the tick or not. | ||
| 338 | */ | ||
| 339 | WRITE_ONCE(dev->next_hrtimer, tick_nohz_get_next_hrtimer()); | ||
| 340 | |||
| 331 | if (cpuidle_state_is_coupled(drv, index)) | 341 | if (cpuidle_state_is_coupled(drv, index)) |
| 332 | return cpuidle_enter_state_coupled(dev, drv, index); | 342 | ret = cpuidle_enter_state_coupled(dev, drv, index); |
| 333 | return cpuidle_enter_state(dev, drv, index); | 343 | else |
| 344 | ret = cpuidle_enter_state(dev, drv, index); | ||
| 345 | |||
| 346 | WRITE_ONCE(dev->next_hrtimer, 0); | ||
| 347 | return ret; | ||
| 334 | } | 348 | } |
| 335 | 349 | ||
| 336 | /** | 350 | /** |
| @@ -511,6 +525,7 @@ static void __cpuidle_device_init(struct cpuidle_device *dev) | |||
| 511 | { | 525 | { |
| 512 | memset(dev->states_usage, 0, sizeof(dev->states_usage)); | 526 | memset(dev->states_usage, 0, sizeof(dev->states_usage)); |
| 513 | dev->last_residency = 0; | 527 | dev->last_residency = 0; |
| 528 | dev->next_hrtimer = 0; | ||
| 514 | } | 529 | } |
| 515 | 530 | ||
| 516 | /** | 531 | /** |
