Merge branches 'pm-cpuidle', 'pm-cpufreq', 'pm-domains' and 'pm-sleep'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 29 Jan 2016 20:45:17 +0000 (21:45 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 29 Jan 2016 20:45:17 +0000 (21:45 +0100)
* pm-cpuidle:
  cpuidle: coupled: remove unused define cpuidle_coupled_lock
  cpuidle: fix fallback mechanism for suspend to idle in absence of enter_freeze

* pm-cpufreq:
  cpufreq: cpufreq-dt: avoid uninitialized variable warnings:
  cpufreq: pxa2xx: fix pxa_cpufreq_change_voltage prototype
  cpufreq: Use list_is_last() to check last entry of the policy list
  cpufreq: Fix NULL reference crash while accessing policy->governor_data

* pm-domains:
  PM / Domains: Fix typo in comment
  PM / Domains: Fix potential deadlock while adding/removing subdomains
  PM / domains: fix lockdep issue for all subdomains

* pm-sleep:
  PM: APM_EMULATION does not depend on PM

1  2  3  4  5 
drivers/base/power/domain.c
kernel/sched/idle.c

     #include <linux/suspend.h>
     #include <linux/export.h>
     
 ++++#include "power.h"
 ++++
     #define GENPD_RETRY_MAX_MS 250             /* Approximate */
     
     #define GENPD_DEV_CALLBACK(genpd, type, callback, dev)             \
@@@@@@ -162,7 -160,7 -160,7 -160,7 -160,7 +162,7 @@@@@@ static int genpd_power_off(struct gener
     
     /**
      * genpd_queue_power_off_work - Queue up the execution of genpd_poweroff().
--- - * @genpd: PM domait to power off.
+++ + * @genpd: PM domain to power off.
      *
      * Queue up the execution of genpd_poweroff() unless it's already been done
      * before.
@@@@@@ -172,16 -170,16 -170,16 -170,15 -170,16 +172,15 @@@@@@ static void genpd_queue_power_off_work(
        queue_work(pm_wq, &genpd->power_off_work);
     }
     
--- -static int genpd_poweron(struct generic_pm_domain *genpd);
--- -
     /**
      * __genpd_poweron - Restore power to a given PM domain and its masters.
      * @genpd: PM domain to power up.
+++ + * @depth: nesting count for lockdep.
      *
      * Restore power to @genpd and all of its masters so that it is possible to
      * resume a device belonging to it.
      */
--- -static int __genpd_poweron(struct generic_pm_domain *genpd)
+++ +static int __genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
     {
        struct gpd_link *link;
        int ret = 0;
         * with it.
         */
        list_for_each_entry(link, &genpd->slave_links, slave_node) {
--- -           genpd_sd_counter_inc(link->master);
+++ +           struct generic_pm_domain *master = link->master;
+++ +
+++ +           genpd_sd_counter_inc(master);
+++ +
+++ +           mutex_lock_nested(&master->lock, depth + 1);
+++ +           ret = __genpd_poweron(master, depth + 1);
+++ +           mutex_unlock(&master->lock);
     
--- -           ret = genpd_poweron(link->master);
                if (ret) {
--- -                   genpd_sd_counter_dec(link->master);
+++ +                   genpd_sd_counter_dec(master);
                        goto err;
                }
        }
@@@@@@ -232,11 -230,11 -230,11 -234,12 -230,11 +236,12 @@@@@@ static int genpd_poweron(struct generic
        int ret;
     
        mutex_lock(&genpd->lock);
--- -   ret = __genpd_poweron(genpd);
+++ +   ret = __genpd_poweron(genpd, 0);
        mutex_unlock(&genpd->lock);
        return ret;
     }
     
+++ +
     static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
     {
        return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
@@@@@@ -392,7 -390,6 -390,7 -395,7 -390,6 +397,7 @@@@@@ static int pm_genpd_runtime_suspend(str
        struct generic_pm_domain *genpd;
        bool (*stop_ok)(struct device *__dev);
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 +  +   bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
        if (IS_ERR(genpd))
                return -EINVAL;
     
 +  +   /*
 +  +    * A runtime PM centric subsystem/driver may re-use the runtime PM
 +  +    * callbacks for other purposes than runtime PM. In those scenarios
 +  +    * runtime PM is disabled. Under these circumstances, we shall skip
 +  +    * validating/measuring the PM QoS latency.
 +  +    */
        stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
 -  -   if (stop_ok && !stop_ok(dev))
 +  +   if (runtime_pm && stop_ok && !stop_ok(dev))
                return -EBUSY;
     
        /* Measure suspend latency. */
 -  -   time_start = ktime_get();
 +  +   if (runtime_pm)
 +  +           time_start = ktime_get();
     
        ret = genpd_save_dev(genpd, dev);
        if (ret)
        }
     
        /* Update suspend latency value if the measured time exceeds it. */
 -  -   elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 -  -   if (elapsed_ns > td->suspend_latency_ns) {
 -  -           td->suspend_latency_ns = elapsed_ns;
 -  -           dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
 -  -                   elapsed_ns);
 -  -           genpd->max_off_time_changed = true;
 -  -           td->constraint_changed = true;
 +  +   if (runtime_pm) {
 +  +           elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 +  +           if (elapsed_ns > td->suspend_latency_ns) {
 +  +                   td->suspend_latency_ns = elapsed_ns;
 +  +                   dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
 +  +                           elapsed_ns);
 +  +                   genpd->max_off_time_changed = true;
 +  +                   td->constraint_changed = true;
 +  +           }
        }
     
        /*
@@@@@@ -465,7 -453,6 -463,7 -468,7 -453,6 +470,7 @@@@@@ static int pm_genpd_runtime_resume(stru
     {
        struct generic_pm_domain *genpd;
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 +  +   bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
        }
     
        mutex_lock(&genpd->lock);
--- -   ret = __genpd_poweron(genpd);
+++ +   ret = __genpd_poweron(genpd, 0);
        mutex_unlock(&genpd->lock);
     
        if (ret)
     
      out:
        /* Measure resume latency. */
 -  -   if (timed)
 +  +   if (timed && runtime_pm)
                time_start = ktime_get();
     
        genpd_start_dev(genpd, dev);
        genpd_restore_dev(genpd, dev);
     
        /* Update resume latency value if the measured time exceeds it. */
 -  -   if (timed) {
 +  +   if (timed && runtime_pm) {
                elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
                if (elapsed_ns > td->resume_latency_ns) {
                        td->resume_latency_ns = elapsed_ns;
@@@@@@ -1190,11 -1177,10 -1188,10 -1193,10 -1177,10 +1195,11 @@@@@@ static struct generic_pm_domain_data *g
        }
     
        dev->power.subsys_data->domain_data = &gpd_data->base;
 ----   dev->pm_domain = &genpd->domain;
     
        spin_unlock_irq(&dev->power.lock);
     
 ++++   dev_pm_domain_set(dev, &genpd->domain);
 ++++
        return gpd_data;
     
      err_free:
     static void genpd_free_dev_data(struct device *dev,
                                struct generic_pm_domain_data *gpd_data)
     {
 ++++   dev_pm_domain_set(dev, NULL);
 ++++
        spin_lock_irq(&dev->power.lock);
     
 ----   dev->pm_domain = NULL;
        dev->power.subsys_data->domain_data = NULL;
     
        spin_unlock_irq(&dev->power.lock);
@@@@@@ -1267,7 -1252,6 -1263,6 -1268,7 -1252,6 +1272,7 @@@@@@ int __pm_genpd_add_device(struct generi
     
        return ret;
     }
 ++ +EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
     
     /**
      * pm_genpd_remove_device - Remove a device from an I/O PM domain.
@@@@@@ -1318,7 -1302,6 -1313,6 -1319,7 -1302,6 +1323,7 @@@@@@ int pm_genpd_remove_device(struct gener
     
        return ret;
     }
 ++ +EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
     
     /**
      * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
@@@@@@ -1339,8 -1322,8 -1333,8 -1340,8 -1322,8 +1344,8 @@@@@@ int pm_genpd_add_subdomain(struct gener
        if (!link)
                return -ENOMEM;
     
--- -   mutex_lock(&genpd->lock);
--- -   mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
+++ +   mutex_lock(&subdomain->lock);
+++ +   mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
     
        if (genpd->status == GPD_STATE_POWER_OFF
            &&  subdomain->status != GPD_STATE_POWER_OFF) {
                genpd_sd_counter_inc(genpd);
     
      out:
--- -   mutex_unlock(&subdomain->lock);
        mutex_unlock(&genpd->lock);
+++ +   mutex_unlock(&subdomain->lock);
        if (ret)
                kfree(link);
        return ret;
@@@@@@ -1385,7 -1368,7 -1379,7 -1386,8 -1368,7 +1390,8 @@@@@@ int pm_genpd_remove_subdomain(struct ge
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
                return -EINVAL;
     
--- -   mutex_lock(&genpd->lock);
+++ +   mutex_lock(&subdomain->lock);
+++ +   mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
     
        if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
                pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
                if (link->slave != subdomain)
                        continue;
     
--- -           mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
--- -
                list_del(&link->master_node);
                list_del(&link->slave_node);
                kfree(link);
                if (subdomain->status != GPD_STATE_POWER_OFF)
                        genpd_sd_counter_dec(genpd);
     
--- -           mutex_unlock(&subdomain->lock);
--- -
                ret = 0;
                break;
        }
     
     out:
        mutex_unlock(&genpd->lock);
+++ +   mutex_unlock(&subdomain->lock);
     
        return ret;
     }
@@@@@@ -1792,10 -1775,10 -1786,10 -1791,10 -1775,10 +1795,10 @@@@@@ int genpd_dev_pm_attach(struct device *
        }
     
        pd = of_genpd_get_from_provider(&pd_args);
 +  +   of_node_put(pd_args.np);
        if (IS_ERR(pd)) {
                dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
                        __func__, PTR_ERR(pd));
 -  -           of_node_put(dev->of_node);
                return -EPROBE_DEFER;
        }
     
        if (ret < 0) {
                dev_err(dev, "failed to add to PM domain %s: %d",
                        pd->name, ret);
 -  -           of_node_put(dev->of_node);
                goto out;
        }
     
diff --combined kernel/sched/idle.c
@@@@@@ -97,6 -97,6 -97,12 -97,12 -97,12 +97,6 @@@@@@ void default_idle_call(void
     static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                      int next_state)
     {
  ---   /* Fall back to the default arch idle method on errors. */
  ---   if (next_state < 0) {
  ---           default_idle_call();
  ---           return next_state;
  ---   }
  ---
        /*
         * The idle task must be scheduled, it is pointless to go to idle, just
         * update no idle residency and return.
@@@@@@ -162,7 -162,7 -168,7 -168,7 -168,7 +162,7 @@@@@@ static void cpuidle_idle_call(void
         */
        if (idle_should_freeze()) {
                entered_state = cpuidle_enter_freeze(drv, dev);
- ---           if (entered_state >= 0) {
+ +++           if (entered_state > 0) {
                        local_irq_enable();
                        goto exit_idle;
                }
@@@@@@ -213,7 -213,6 -219,6 -219,6 -219,6 +213,7 @@@@@@ static void cpu_idle_loop(void
                 */
     
                __current_set_polling();
 ++++           quiet_vmstat();
                tick_nohz_idle_enter();
     
                while (!need_resched()) {