These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / base / power / domain.c
index 2327613..65f50ec 100644 (file)
@@ -6,6 +6,7 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
@@ -19,6 +20,8 @@
 #include <linux/suspend.h>
 #include <linux/export.h>
 
+#define GENPD_RETRY_MAX_MS     250             /* Approximate */
+
 #define GENPD_DEV_CALLBACK(genpd, type, callback, dev)         \
 ({                                                             \
        type (*__routine)(struct device *__d);                  \
        __ret;                                                  \
 })
 
-#define GENPD_DEV_TIMED_CALLBACK(genpd, type, callback, dev, field, name)      \
-({                                                                             \
-       ktime_t __start = ktime_get();                                          \
-       type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev);         \
-       s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start));           \
-       struct gpd_timing_data *__td = &dev_gpd_data(dev)->td;                  \
-       if (!__retval && __elapsed > __td->field) {                             \
-               __td->field = __elapsed;                                        \
-               dev_dbg(dev, name " latency exceeded, new value %lld ns\n",     \
-                       __elapsed);                                             \
-               genpd->max_off_time_changed = true;                             \
-               __td->constraint_changed = true;                                \
-       }                                                                       \
-       __retval;                                                               \
-})
-
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
-static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
-{
-       struct generic_pm_domain *genpd = NULL, *gpd;
-
-       if (IS_ERR_OR_NULL(domain_name))
-               return NULL;
-
-       mutex_lock(&gpd_list_lock);
-       list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
-               if (!strcmp(gpd->name, domain_name)) {
-                       genpd = gpd;
-                       break;
-               }
-       }
-       mutex_unlock(&gpd_list_lock);
-       return genpd;
-}
-
 /*
  * Get the generic PM domain for a particular struct device.
  * This validates the struct device pointer, the PM domain pointer,
@@ -107,14 +76,12 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
 
 static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, stop, dev,
-                                       stop_latency_ns, "stop");
+       return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
 }
 
 static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
-                                       start_latency_ns, "start");
+       return GENPD_DEV_CALLBACK(genpd, int, start, dev);
 }
 
 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
@@ -133,55 +100,7 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
        smp_mb__after_atomic();
 }
 
-static void genpd_acquire_lock(struct generic_pm_domain *genpd)
-{
-       DEFINE_WAIT(wait);
-
-       mutex_lock(&genpd->lock);
-       /*
-        * Wait for the domain to transition into either the active,
-        * or the power off state.
-        */
-       for (;;) {
-               prepare_to_wait(&genpd->status_wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (genpd->status == GPD_STATE_ACTIVE
-                   || genpd->status == GPD_STATE_POWER_OFF)
-                       break;
-               mutex_unlock(&genpd->lock);
-
-               schedule();
-
-               mutex_lock(&genpd->lock);
-       }
-       finish_wait(&genpd->status_wait_queue, &wait);
-}
-
-static void genpd_release_lock(struct generic_pm_domain *genpd)
-{
-       mutex_unlock(&genpd->lock);
-}
-
-static void genpd_set_active(struct generic_pm_domain *genpd)
-{
-       if (genpd->resume_count == 0)
-               genpd->status = GPD_STATE_ACTIVE;
-}
-
-static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd)
-{
-       s64 usecs64;
-
-       if (!genpd->cpuidle_data)
-               return;
-
-       usecs64 = genpd->power_on_latency_ns;
-       do_div(usecs64, NSEC_PER_USEC);
-       usecs64 += genpd->cpuidle_data->saved_exit_latency;
-       genpd->cpuidle_data->idle_state->exit_latency = usecs64;
-}
-
-static int genpd_power_on(struct generic_pm_domain *genpd)
+static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
 {
        ktime_t time_start;
        s64 elapsed_ns;
@@ -190,6 +109,9 @@ static int genpd_power_on(struct generic_pm_domain *genpd)
        if (!genpd->power_on)
                return 0;
 
+       if (!timed)
+               return genpd->power_on(genpd);
+
        time_start = ktime_get();
        ret = genpd->power_on(genpd);
        if (ret)
@@ -201,14 +123,13 @@ static int genpd_power_on(struct generic_pm_domain *genpd)
 
        genpd->power_on_latency_ns = elapsed_ns;
        genpd->max_off_time_changed = true;
-       genpd_recalc_cpu_exit_latency(genpd);
        pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
                 genpd->name, "on", elapsed_ns);
 
        return ret;
 }
 
-static int genpd_power_off(struct generic_pm_domain *genpd)
+static int genpd_power_off(struct generic_pm_domain *genpd, bool timed)
 {
        ktime_t time_start;
        s64 elapsed_ns;
@@ -217,6 +138,9 @@ static int genpd_power_off(struct generic_pm_domain *genpd)
        if (!genpd->power_off)
                return 0;
 
+       if (!timed)
+               return genpd->power_off(genpd);
+
        time_start = ktime_get();
        ret = genpd->power_off(genpd);
        if (ret == -EBUSY)
@@ -235,49 +159,35 @@ static int genpd_power_off(struct generic_pm_domain *genpd)
 }
 
 /**
- * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * genpd_queue_power_off_work - Queue up the execution of genpd_poweroff().
+ * @genpd: PM domait to power off.
+ *
+ * Queue up the execution of genpd_poweroff() unless it's already been done
+ * before.
+ */
+static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
+{
+       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.
  *
  * Restore power to @genpd and all of its masters so that it is possible to
  * resume a device belonging to it.
  */
-static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
-       __releases(&genpd->lock) __acquires(&genpd->lock)
+static int __genpd_poweron(struct generic_pm_domain *genpd)
 {
        struct gpd_link *link;
-       DEFINE_WAIT(wait);
        int ret = 0;
 
-       /* If the domain's master is being waited for, we have to wait too. */
-       for (;;) {
-               prepare_to_wait(&genpd->status_wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (genpd->status != GPD_STATE_WAIT_MASTER)
-                       break;
-               mutex_unlock(&genpd->lock);
-
-               schedule();
-
-               mutex_lock(&genpd->lock);
-       }
-       finish_wait(&genpd->status_wait_queue, &wait);
-
        if (genpd->status == GPD_STATE_ACTIVE
            || (genpd->prepared_count > 0 && genpd->suspend_power_off))
                return 0;
 
-       if (genpd->status != GPD_STATE_POWER_OFF) {
-               genpd_set_active(genpd);
-               return 0;
-       }
-
-       if (genpd->cpuidle_data) {
-               cpuidle_pause_and_lock();
-               genpd->cpuidle_data->idle_state->disabled = true;
-               cpuidle_resume_and_unlock();
-               goto out;
-       }
-
        /*
         * The list is guaranteed not to change while the loop below is being
         * executed, unless one of the masters' .power_on() callbacks fiddles
@@ -285,85 +195,55 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
         */
        list_for_each_entry(link, &genpd->slave_links, slave_node) {
                genpd_sd_counter_inc(link->master);
-               genpd->status = GPD_STATE_WAIT_MASTER;
 
-               mutex_unlock(&genpd->lock);
-
-               ret = pm_genpd_poweron(link->master);
-
-               mutex_lock(&genpd->lock);
-
-               /*
-                * The "wait for parent" status is guaranteed not to change
-                * while the master is powering on.
-                */
-               genpd->status = GPD_STATE_POWER_OFF;
-               wake_up_all(&genpd->status_wait_queue);
+               ret = genpd_poweron(link->master);
                if (ret) {
                        genpd_sd_counter_dec(link->master);
                        goto err;
                }
        }
 
-       ret = genpd_power_on(genpd);
+       ret = genpd_power_on(genpd, true);
        if (ret)
                goto err;
 
- out:
-       genpd_set_active(genpd);
-
+       genpd->status = GPD_STATE_ACTIVE;
        return 0;
 
  err:
-       list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node)
+       list_for_each_entry_continue_reverse(link,
+                                       &genpd->slave_links,
+                                       slave_node) {
                genpd_sd_counter_dec(link->master);
+               genpd_queue_power_off_work(link->master);
+       }
 
        return ret;
 }
 
 /**
- * pm_genpd_poweron - Restore power to a given PM domain and its masters.
+ * genpd_poweron - Restore power to a given PM domain and its masters.
  * @genpd: PM domain to power up.
  */
-int pm_genpd_poweron(struct generic_pm_domain *genpd)
+static int genpd_poweron(struct generic_pm_domain *genpd)
 {
        int ret;
 
        mutex_lock(&genpd->lock);
-       ret = __pm_genpd_poweron(genpd);
+       ret = __genpd_poweron(genpd);
        mutex_unlock(&genpd->lock);
        return ret;
 }
 
-/**
- * pm_genpd_name_poweron - Restore power to a given PM domain and its masters.
- * @domain_name: Name of the PM domain to power up.
- */
-int pm_genpd_name_poweron(const char *domain_name)
-{
-       struct generic_pm_domain *genpd;
-
-       genpd = pm_genpd_lookup_name(domain_name);
-       return genpd ? pm_genpd_poweron(genpd) : -EINVAL;
-}
-
-static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd,
-                                    struct device *dev)
-{
-       return GENPD_DEV_CALLBACK(genpd, int, start, dev);
-}
-
 static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
-                                       save_state_latency_ns, "state save");
+       return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
 }
 
-static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
+static int genpd_restore_dev(struct generic_pm_domain *genpd,
+                       struct device *dev)
 {
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
-                                       restore_state_latency_ns,
-                                       "state restore");
+       return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
 }
 
 static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
@@ -407,133 +287,31 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
 }
 
 /**
- * __pm_genpd_save_device - Save the pre-suspend state of a device.
- * @pdd: Domain data of the device to save the state of.
- * @genpd: PM domain the device belongs to.
- */
-static int __pm_genpd_save_device(struct pm_domain_data *pdd,
-                                 struct generic_pm_domain *genpd)
-       __releases(&genpd->lock) __acquires(&genpd->lock)
-{
-       struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
-       struct device *dev = pdd->dev;
-       int ret = 0;
-
-       if (gpd_data->need_restore > 0)
-               return 0;
-
-       /*
-        * If the value of the need_restore flag is still unknown at this point,
-        * we trust that pm_genpd_poweroff() has verified that the device is
-        * already runtime PM suspended.
-        */
-       if (gpd_data->need_restore < 0) {
-               gpd_data->need_restore = 1;
-               return 0;
-       }
-
-       mutex_unlock(&genpd->lock);
-
-       genpd_start_dev(genpd, dev);
-       ret = genpd_save_dev(genpd, dev);
-       genpd_stop_dev(genpd, dev);
-
-       mutex_lock(&genpd->lock);
-
-       if (!ret)
-               gpd_data->need_restore = 1;
-
-       return ret;
-}
-
-/**
- * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
- * @pdd: Domain data of the device to restore the state of.
- * @genpd: PM domain the device belongs to.
- */
-static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
-                                     struct generic_pm_domain *genpd)
-       __releases(&genpd->lock) __acquires(&genpd->lock)
-{
-       struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
-       struct device *dev = pdd->dev;
-       int need_restore = gpd_data->need_restore;
-
-       gpd_data->need_restore = 0;
-       mutex_unlock(&genpd->lock);
-
-       genpd_start_dev(genpd, dev);
-
-       /*
-        * Call genpd_restore_dev() for recently added devices too (need_restore
-        * is negative then).
-        */
-       if (need_restore)
-               genpd_restore_dev(genpd, dev);
-
-       mutex_lock(&genpd->lock);
-}
-
-/**
- * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
- * @genpd: PM domain to check.
- *
- * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
- * a "power off" operation, which means that a "power on" has occured in the
- * meantime, or if its resume_count field is different from zero, which means
- * that one of its devices has been resumed in the meantime.
- */
-static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
-{
-       return genpd->status == GPD_STATE_WAIT_MASTER
-               || genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
-}
-
-/**
- * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
- * @genpd: PM domait to power off.
- *
- * Queue up the execution of pm_genpd_poweroff() unless it's already been done
- * before.
- */
-static void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
-{
-       queue_work(pm_wq, &genpd->power_off_work);
-}
-
-/**
- * pm_genpd_poweroff - Remove power from a given PM domain.
+ * genpd_poweroff - Remove power from a given PM domain.
  * @genpd: PM domain to power down.
+ * @is_async: PM domain is powered down from a scheduled work
  *
  * If all of the @genpd's devices have been suspended and all of its subdomains
- * have been powered down, run the runtime suspend callbacks provided by all of
- * the @genpd's devices' drivers and remove power from @genpd.
+ * have been powered down, remove power from @genpd.
  */
-static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
-       __releases(&genpd->lock) __acquires(&genpd->lock)
+static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
 {
        struct pm_domain_data *pdd;
        struct gpd_link *link;
-       unsigned int not_suspended;
-       int ret = 0;
+       unsigned int not_suspended = 0;
 
- start:
        /*
         * Do not try to power off the domain in the following situations:
         * (1) The domain is already in the "power off" state.
-        * (2) The domain is waiting for its master to power up.
-        * (3) One of the domain's devices is being resumed right now.
-        * (4) System suspend is in progress.
+        * (2) System suspend is in progress.
         */
        if (genpd->status == GPD_STATE_POWER_OFF
-           || genpd->status == GPD_STATE_WAIT_MASTER
-           || genpd->resume_count > 0 || genpd->prepared_count > 0)
+           || genpd->prepared_count > 0)
                return 0;
 
        if (atomic_read(&genpd->sd_count) > 0)
                return -EBUSY;
 
-       not_suspended = 0;
        list_for_each_entry(pdd, &genpd->dev_list, list_node) {
                enum pm_qos_flags_status stat;
 
@@ -543,83 +321,35 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
                if (stat > PM_QOS_FLAGS_NONE)
                        return -EBUSY;
 
-               if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-                   || pdd->dev->power.irq_safe))
+               if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
                        not_suspended++;
        }
 
-       if (not_suspended > genpd->in_progress)
+       if (not_suspended > 1 || (not_suspended == 1 && is_async))
                return -EBUSY;
 
-       if (genpd->poweroff_task) {
-               /*
-                * Another instance of pm_genpd_poweroff() is executing
-                * callbacks, so tell it to start over and return.
-                */
-               genpd->status = GPD_STATE_REPEAT;
-               return 0;
-       }
-
        if (genpd->gov && genpd->gov->power_down_ok) {
                if (!genpd->gov->power_down_ok(&genpd->domain))
                        return -EAGAIN;
        }
 
-       genpd->status = GPD_STATE_BUSY;
-       genpd->poweroff_task = current;
-
-       list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
-               ret = atomic_read(&genpd->sd_count) == 0 ?
-                       __pm_genpd_save_device(pdd, genpd) : -EBUSY;
-
-               if (genpd_abort_poweroff(genpd))
-                       goto out;
-
-               if (ret) {
-                       genpd_set_active(genpd);
-                       goto out;
-               }
-
-               if (genpd->status == GPD_STATE_REPEAT) {
-                       genpd->poweroff_task = NULL;
-                       goto start;
-               }
-       }
-
-       if (genpd->cpuidle_data) {
-               /*
-                * If cpuidle_data is set, cpuidle should turn the domain off
-                * when the CPU in it is idle.  In that case we don't decrement
-                * the subdomain counts of the master domains, so that power is
-                * not removed from the current domain prematurely as a result
-                * of cutting off the masters' power.
-                */
-               genpd->status = GPD_STATE_POWER_OFF;
-               cpuidle_pause_and_lock();
-               genpd->cpuidle_data->idle_state->disabled = false;
-               cpuidle_resume_and_unlock();
-               goto out;
-       }
-
        if (genpd->power_off) {
-               if (atomic_read(&genpd->sd_count) > 0) {
-                       ret = -EBUSY;
-                       goto out;
-               }
+               int ret;
+
+               if (atomic_read(&genpd->sd_count) > 0)
+                       return -EBUSY;
 
                /*
                 * If sd_count > 0 at this point, one of the subdomains hasn't
-                * managed to call pm_genpd_poweron() for the master yet after
-                * incrementing it.  In that case pm_genpd_poweron() will wait
+                * managed to call genpd_poweron() for the master yet after
+                * incrementing it.  In that case genpd_poweron() will wait
                 * for us to drop the lock, so we can call .power_off() and let
-                * the pm_genpd_poweron() restore power for us (this shouldn't
+                * the genpd_poweron() restore power for us (this shouldn't
                 * happen very often).
                 */
-               ret = genpd_power_off(genpd);
-               if (ret == -EBUSY) {
-                       genpd_set_active(genpd);
-                       goto out;
-               }
+               ret = genpd_power_off(genpd, true);
+               if (ret)
+                       return ret;
        }
 
        genpd->status = GPD_STATE_POWER_OFF;
@@ -629,10 +359,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
                genpd_queue_power_off_work(link->master);
        }
 
- out:
-       genpd->poweroff_task = NULL;
-       wake_up_all(&genpd->status_wait_queue);
-       return ret;
+       return 0;
 }
 
 /**
@@ -645,9 +372,9 @@ static void genpd_power_off_work_fn(struct work_struct *work)
 
        genpd = container_of(work, struct generic_pm_domain, power_off_work);
 
-       genpd_acquire_lock(genpd);
-       pm_genpd_poweroff(genpd);
-       genpd_release_lock(genpd);
+       mutex_lock(&genpd->lock);
+       genpd_poweroff(genpd, true);
+       mutex_unlock(&genpd->lock);
 }
 
 /**
@@ -661,8 +388,11 @@ static void genpd_power_off_work_fn(struct work_struct *work)
 static int pm_genpd_runtime_suspend(struct device *dev)
 {
        struct generic_pm_domain *genpd;
-       struct generic_pm_domain_data *gpd_data;
        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;
 
        dev_dbg(dev, "%s()\n", __func__);
@@ -671,14 +401,42 @@ static int pm_genpd_runtime_suspend(struct device *dev)
        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;
 
-       ret = genpd_stop_dev(genpd, dev);
+       /* Measure suspend latency. */
+       if (runtime_pm)
+               time_start = ktime_get();
+
+       ret = genpd_save_dev(genpd, dev);
        if (ret)
                return ret;
 
+       ret = genpd_stop_dev(genpd, dev);
+       if (ret) {
+               genpd_restore_dev(genpd, dev);
+               return ret;
+       }
+
+       /* Update suspend latency value if the measured time exceeds it. */
+       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;
+               }
+       }
+
        /*
         * If power.irq_safe is set, this routine will be run with interrupts
         * off, so it can't use mutexes.
@@ -687,19 +445,7 @@ static int pm_genpd_runtime_suspend(struct device *dev)
                return 0;
 
        mutex_lock(&genpd->lock);
-
-       /*
-        * If we have an unknown state of the need_restore flag, it means none
-        * of the runtime PM callbacks has been invoked yet. Let's update the
-        * flag to reflect that the current state is active.
-        */
-       gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
-       if (gpd_data->need_restore < 0)
-               gpd_data->need_restore = 0;
-
-       genpd->in_progress++;
-       pm_genpd_poweroff(genpd);
-       genpd->in_progress--;
+       genpd_poweroff(genpd, false);
        mutex_unlock(&genpd->lock);
 
        return 0;
@@ -716,8 +462,12 @@ static int pm_genpd_runtime_suspend(struct device *dev)
 static int pm_genpd_runtime_resume(struct device *dev)
 {
        struct generic_pm_domain *genpd;
-       DEFINE_WAIT(wait);
+       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;
+       bool timed = true;
 
        dev_dbg(dev, "%s()\n", __func__);
 
@@ -726,39 +476,37 @@ static int pm_genpd_runtime_resume(struct device *dev)
                return -EINVAL;
 
        /* If power.irq_safe, the PM domain is never powered off. */
-       if (dev->power.irq_safe)
-               return genpd_start_dev_no_timing(genpd, dev);
+       if (dev->power.irq_safe) {
+               timed = false;
+               goto out;
+       }
 
        mutex_lock(&genpd->lock);
-       ret = __pm_genpd_poweron(genpd);
-       if (ret) {
-               mutex_unlock(&genpd->lock);
+       ret = __genpd_poweron(genpd);
+       mutex_unlock(&genpd->lock);
+
+       if (ret)
                return ret;
-       }
-       genpd->status = GPD_STATE_BUSY;
-       genpd->resume_count++;
-       for (;;) {
-               prepare_to_wait(&genpd->status_wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               /*
-                * If current is the powering off task, we have been called
-                * reentrantly from one of the device callbacks, so we should
-                * not wait.
-                */
-               if (!genpd->poweroff_task || genpd->poweroff_task == current)
-                       break;
-               mutex_unlock(&genpd->lock);
 
-               schedule();
+ out:
+       /* Measure resume latency. */
+       if (timed && runtime_pm)
+               time_start = ktime_get();
 
-               mutex_lock(&genpd->lock);
+       genpd_start_dev(genpd, dev);
+       genpd_restore_dev(genpd, dev);
+
+       /* Update resume latency value if the measured time exceeds it. */
+       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;
+                       dev_dbg(dev, "resume latency exceeded, %lld ns\n",
+                               elapsed_ns);
+                       genpd->max_off_time_changed = true;
+                       td->constraint_changed = true;
+               }
        }
-       finish_wait(&genpd->status_wait_queue, &wait);
-       __pm_genpd_restore_device(dev->power.subsys_data->domain_data, genpd);
-       genpd->resume_count--;
-       genpd_set_active(genpd);
-       wake_up_all(&genpd->status_wait_queue);
-       mutex_unlock(&genpd->lock);
 
        return 0;
 }
@@ -772,15 +520,15 @@ static int __init pd_ignore_unused_setup(char *__unused)
 __setup("pd_ignore_unused", pd_ignore_unused_setup);
 
 /**
- * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
+ * genpd_poweroff_unused - Power off all PM domains with no devices in use.
  */
-void pm_genpd_poweroff_unused(void)
+static int __init genpd_poweroff_unused(void)
 {
        struct generic_pm_domain *genpd;
 
        if (pd_ignore_unused) {
                pr_warn("genpd: Not disabling unused power domains\n");
-               return;
+               return 0;
        }
 
        mutex_lock(&gpd_list_lock);
@@ -789,11 +537,7 @@ void pm_genpd_poweroff_unused(void)
                genpd_queue_power_off_work(genpd);
 
        mutex_unlock(&gpd_list_lock);
-}
 
-static int __init genpd_poweroff_unused(void)
-{
-       pm_genpd_poweroff_unused();
        return 0;
 }
 late_initcall(genpd_poweroff_unused);
@@ -827,6 +571,7 @@ static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
 /**
  * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
  * @genpd: PM domain to power off, if possible.
+ * @timed: True if latency measurements are allowed.
  *
  * Check if the given PM domain can be powered off (during system suspend or
  * hibernation) and do that if so.  Also, in that case propagate to its masters.
@@ -836,7 +581,8 @@ static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
  * executed sequentially, so it is guaranteed that it will never run twice in
  * parallel).
  */
-static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
+static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd,
+                                  bool timed)
 {
        struct gpd_link *link;
 
@@ -847,38 +593,40 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
            || atomic_read(&genpd->sd_count) > 0)
                return;
 
-       genpd_power_off(genpd);
+       genpd_power_off(genpd, timed);
 
        genpd->status = GPD_STATE_POWER_OFF;
 
        list_for_each_entry(link, &genpd->slave_links, slave_node) {
                genpd_sd_counter_dec(link->master);
-               pm_genpd_sync_poweroff(link->master);
+               pm_genpd_sync_poweroff(link->master, timed);
        }
 }
 
 /**
  * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
  * @genpd: PM domain to power on.
+ * @timed: True if latency measurements are allowed.
  *
  * This function is only called in "noirq" and "syscore" stages of system power
  * transitions, so it need not acquire locks (all of the "noirq" callbacks are
  * executed sequentially, so it is guaranteed that it will never run twice in
  * parallel).
  */
-static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
+static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd,
+                                 bool timed)
 {
        struct gpd_link *link;
 
-       if (genpd->status != GPD_STATE_POWER_OFF)
+       if (genpd->status == GPD_STATE_ACTIVE)
                return;
 
        list_for_each_entry(link, &genpd->slave_links, slave_node) {
-               pm_genpd_sync_poweron(link->master);
+               pm_genpd_sync_poweron(link->master, timed);
                genpd_sd_counter_inc(link->master);
        }
 
-       genpd_power_on(genpd);
+       genpd_power_on(genpd, timed);
 
        genpd->status = GPD_STATE_ACTIVE;
 }
@@ -947,14 +695,14 @@ static int pm_genpd_prepare(struct device *dev)
        if (resume_needed(dev, genpd))
                pm_runtime_resume(dev);
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        if (genpd->prepared_count++ == 0) {
                genpd->suspended_count = 0;
                genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
        }
 
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 
        if (genpd->suspend_power_off) {
                pm_runtime_put_noidle(dev);
@@ -963,7 +711,7 @@ static int pm_genpd_prepare(struct device *dev)
 
        /*
         * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
-        * so pm_genpd_poweron() will return immediately, but if the device
+        * so genpd_poweron() will return immediately, but if the device
         * is suspended (e.g. it's been stopped by genpd_stop_dev()), we need
         * to make it operational.
         */
@@ -1056,7 +804,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
         * the same PM domain, so it is not necessary to use locking here.
         */
        genpd->suspended_count++;
-       pm_genpd_sync_poweroff(genpd);
+       pm_genpd_sync_poweroff(genpd, true);
 
        return 0;
 }
@@ -1086,7 +834,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
         * guaranteed that this function will never run twice in parallel for
         * the same PM domain, so it is not necessary to use locking here.
         */
-       pm_genpd_sync_poweron(genpd);
+       pm_genpd_sync_poweron(genpd, true);
        genpd->suspended_count--;
 
        return genpd_start_dev(genpd, dev);
@@ -1217,7 +965,8 @@ static int pm_genpd_thaw_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev);
+       return genpd->suspend_power_off ?
+               0 : genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1300,7 +1049,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
                         * If the domain was off before the hibernation, make
                         * sure it will be off going forward.
                         */
-                       genpd_power_off(genpd);
+                       genpd_power_off(genpd, true);
 
                        return 0;
                }
@@ -1309,7 +1058,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
        if (genpd->suspend_power_off)
                return 0;
 
-       pm_genpd_sync_poweron(genpd);
+       pm_genpd_sync_poweron(genpd, true);
 
        return genpd_start_dev(genpd, dev);
 }
@@ -1367,9 +1116,9 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
 
        if (suspend) {
                genpd->suspended_count++;
-               pm_genpd_sync_poweroff(genpd);
+               pm_genpd_sync_poweroff(genpd, false);
        } else {
-               pm_genpd_sync_poweron(genpd);
+               pm_genpd_sync_poweron(genpd, false);
                genpd->suspended_count--;
        }
 }
@@ -1427,7 +1176,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
                gpd_data->td = *td;
 
        gpd_data->base.dev = dev;
-       gpd_data->need_restore = -1;
        gpd_data->td.constraint_changed = true;
        gpd_data->td.effective_constraint_ns = -1;
        gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
@@ -1489,7 +1237,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        if (IS_ERR(gpd_data))
                return PTR_ERR(gpd_data);
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        if (genpd->prepared_count > 0) {
                ret = -EAGAIN;
@@ -1506,7 +1254,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 
  out:
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 
        if (ret)
                genpd_free_dev_data(dev, gpd_data);
@@ -1516,18 +1264,6 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        return ret;
 }
 
-/**
- * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it.
- * @domain_name: Name of the PM domain to add the device to.
- * @dev: Device to be added.
- * @td: Set of PM QoS timing parameters to attach to the device.
- */
-int __pm_genpd_name_add_device(const char *domain_name, struct device *dev,
-                              struct gpd_timing_data *td)
-{
-       return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td);
-}
-
 /**
  * pm_genpd_remove_device - Remove a device from an I/O PM domain.
  * @genpd: PM domain to remove the device from.
@@ -1550,7 +1286,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
        gpd_data = to_gpd_data(pdd);
        dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        if (genpd->prepared_count > 0) {
                ret = -EAGAIN;
@@ -1565,14 +1301,14 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 
        list_del_init(&pdd->list_node);
 
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 
        genpd_free_dev_data(dev, gpd_data);
 
        return 0;
 
  out:
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
        dev_pm_qos_add_notifier(dev, &gpd_data->nb);
 
        return ret;
@@ -1586,23 +1322,19 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                           struct generic_pm_domain *subdomain)
 {
-       struct gpd_link *link;
+       struct gpd_link *link, *itr;
        int ret = 0;
 
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
            || genpd == subdomain)
                return -EINVAL;
 
- start:
-       genpd_acquire_lock(genpd);
-       mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
+       link = kzalloc(sizeof(*link), GFP_KERNEL);
+       if (!link)
+               return -ENOMEM;
 
-       if (subdomain->status != GPD_STATE_POWER_OFF
-           && subdomain->status != GPD_STATE_ACTIVE) {
-               mutex_unlock(&subdomain->lock);
-               genpd_release_lock(genpd);
-               goto start;
-       }
+       mutex_lock(&genpd->lock);
+       mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
 
        if (genpd->status == GPD_STATE_POWER_OFF
            &&  subdomain->status != GPD_STATE_POWER_OFF) {
@@ -1610,18 +1342,13 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                goto out;
        }
 
-       list_for_each_entry(link, &genpd->master_links, master_node) {
-               if (link->slave == subdomain && link->master == genpd) {
+       list_for_each_entry(itr, &genpd->master_links, master_node) {
+               if (itr->slave == subdomain && itr->master == genpd) {
                        ret = -EINVAL;
                        goto out;
                }
        }
 
-       link = kzalloc(sizeof(*link), GFP_KERNEL);
-       if (!link) {
-               ret = -ENOMEM;
-               goto out;
-       }
        link->master = genpd;
        list_add_tail(&link->master_node, &genpd->master_links);
        link->slave = subdomain;
@@ -1631,39 +1358,12 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 
  out:
        mutex_unlock(&subdomain->lock);
-       genpd_release_lock(genpd);
-
+       mutex_unlock(&genpd->lock);
+       if (ret)
+               kfree(link);
        return ret;
 }
-
-/**
- * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain.
- * @master_name: Name of the master PM domain to add the subdomain to.
- * @subdomain_name: Name of the subdomain to be added.
- */
-int pm_genpd_add_subdomain_names(const char *master_name,
-                                const char *subdomain_name)
-{
-       struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd;
-
-       if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name))
-               return -EINVAL;
-
-       mutex_lock(&gpd_list_lock);
-       list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
-               if (!master && !strcmp(gpd->name, master_name))
-                       master = gpd;
-
-               if (!subdomain && !strcmp(gpd->name, subdomain_name))
-                       subdomain = gpd;
-
-               if (master && subdomain)
-                       break;
-       }
-       mutex_unlock(&gpd_list_lock);
-
-       return pm_genpd_add_subdomain(master, subdomain);
-}
+EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
 
 /**
  * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
@@ -1679,8 +1379,14 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
                return -EINVAL;
 
- start:
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
+
+       if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
+               pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
+                       subdomain->name);
+               ret = -EBUSY;
+               goto out;
+       }
 
        list_for_each_entry(link, &genpd->master_links, master_node) {
                if (link->slave != subdomain)
@@ -1688,13 +1394,6 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 
                mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
 
-               if (subdomain->status != GPD_STATE_POWER_OFF
-                   && subdomain->status != GPD_STATE_ACTIVE) {
-                       mutex_unlock(&subdomain->lock);
-                       genpd_release_lock(genpd);
-                       goto start;
-               }
-
                list_del(&link->master_node);
                list_del(&link->slave_node);
                kfree(link);
@@ -1707,128 +1406,12 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
                break;
        }
 
-       genpd_release_lock(genpd);
-
-       return ret;
-}
-
-/**
- * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle.
- * @genpd: PM domain to be connected with cpuidle.
- * @state: cpuidle state this domain can disable/enable.
- *
- * Make a PM domain behave as though it contained a CPU core, that is, instead
- * of calling its power down routine it will enable the given cpuidle state so
- * that the cpuidle subsystem can power it down (if possible and desirable).
- */
-int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
-{
-       struct cpuidle_driver *cpuidle_drv;
-       struct gpd_cpuidle_data *cpuidle_data;
-       struct cpuidle_state *idle_state;
-       int ret = 0;
-
-       if (IS_ERR_OR_NULL(genpd) || state < 0)
-               return -EINVAL;
-
-       genpd_acquire_lock(genpd);
-
-       if (genpd->cpuidle_data) {
-               ret = -EEXIST;
-               goto out;
-       }
-       cpuidle_data = kzalloc(sizeof(*cpuidle_data), GFP_KERNEL);
-       if (!cpuidle_data) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       cpuidle_drv = cpuidle_driver_ref();
-       if (!cpuidle_drv) {
-               ret = -ENODEV;
-               goto err_drv;
-       }
-       if (cpuidle_drv->state_count <= state) {
-               ret = -EINVAL;
-               goto err;
-       }
-       idle_state = &cpuidle_drv->states[state];
-       if (!idle_state->disabled) {
-               ret = -EAGAIN;
-               goto err;
-       }
-       cpuidle_data->idle_state = idle_state;
-       cpuidle_data->saved_exit_latency = idle_state->exit_latency;
-       genpd->cpuidle_data = cpuidle_data;
-       genpd_recalc_cpu_exit_latency(genpd);
-
- out:
-       genpd_release_lock(genpd);
-       return ret;
-
- err:
-       cpuidle_driver_unref();
-
- err_drv:
-       kfree(cpuidle_data);
-       goto out;
-}
-
-/**
- * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it.
- * @name: Name of the domain to connect to cpuidle.
- * @state: cpuidle state this domain can manipulate.
- */
-int pm_genpd_name_attach_cpuidle(const char *name, int state)
-{
-       return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state);
-}
-
-/**
- * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain.
- * @genpd: PM domain to remove the cpuidle connection from.
- *
- * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the
- * given PM domain.
- */
-int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd)
-{
-       struct gpd_cpuidle_data *cpuidle_data;
-       struct cpuidle_state *idle_state;
-       int ret = 0;
-
-       if (IS_ERR_OR_NULL(genpd))
-               return -EINVAL;
-
-       genpd_acquire_lock(genpd);
-
-       cpuidle_data = genpd->cpuidle_data;
-       if (!cpuidle_data) {
-               ret = -ENODEV;
-               goto out;
-       }
-       idle_state = cpuidle_data->idle_state;
-       if (!idle_state->disabled) {
-               ret = -EAGAIN;
-               goto out;
-       }
-       idle_state->exit_latency = cpuidle_data->saved_exit_latency;
-       cpuidle_driver_unref();
-       genpd->cpuidle_data = NULL;
-       kfree(cpuidle_data);
+out:
+       mutex_unlock(&genpd->lock);
 
- out:
-       genpd_release_lock(genpd);
        return ret;
 }
-
-/**
- * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it.
- * @name: Name of the domain to disconnect cpuidle from.
- */
-int pm_genpd_name_detach_cpuidle(const char *name)
-{
-       return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name));
-}
+EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
 
 /* Default device callbacks for generic PM domains. */
 
@@ -1896,12 +1479,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
        mutex_init(&genpd->lock);
        genpd->gov = gov;
        INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
-       genpd->in_progress = 0;
        atomic_set(&genpd->sd_count, 0);
        genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
-       init_waitqueue_head(&genpd->status_wait_queue);
-       genpd->poweroff_task = NULL;
-       genpd->resume_count = 0;
        genpd->device_count = 0;
        genpd->max_off_time_ns = -1;
        genpd->max_off_time_changed = true;
@@ -1939,6 +1518,7 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
        list_add(&genpd->gpd_list_node, &gpd_list);
        mutex_unlock(&gpd_list_lock);
 }
+EXPORT_SYMBOL_GPL(pm_genpd_init);
 
 #ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 /*
@@ -2112,7 +1692,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
 
 /**
  * genpd_dev_pm_detach - Detach a device from its PM domain.
- * @dev: Device to attach.
+ * @dev: Device to detach.
  * @power_off: Currently not used
  *
  * Try to locate a corresponding generic PM domain, which the device was
@@ -2121,6 +1701,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
 static void genpd_dev_pm_detach(struct device *dev, bool power_off)
 {
        struct generic_pm_domain *pd;
+       unsigned int i;
        int ret = 0;
 
        pd = pm_genpd_lookup_dev(dev);
@@ -2129,10 +1710,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
 
        dev_dbg(dev, "removing from PM domain %s\n", pd->name);
 
-       while (1) {
+       for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
                ret = pm_genpd_remove_device(pd, dev);
                if (ret != -EAGAIN)
                        break;
+
+               mdelay(i);
                cond_resched();
        }
 
@@ -2167,12 +1750,16 @@ static void genpd_dev_pm_sync(struct device *dev)
  * Both generic and legacy Samsung-specific DT bindings are supported to keep
  * backwards compatibility with existing DTBs.
  *
- * Returns 0 on successfully attached PM domain or negative error code.
+ * Returns 0 on successfully attached PM domain or negative error code. Note
+ * that if a power-domain exists for the device, but it cannot be found or
+ * turned on, then return -EPROBE_DEFER to ensure that the device is not
+ * probed and to re-try again later.
  */
 int genpd_dev_pm_attach(struct device *dev)
 {
        struct of_phandle_args pd_args;
        struct generic_pm_domain *pd;
+       unsigned int i;
        int ret;
 
        if (!dev->of_node)
@@ -2199,34 +1786,36 @@ int genpd_dev_pm_attach(struct device *dev)
        }
 
        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 PTR_ERR(pd);
+               return -EPROBE_DEFER;
        }
 
        dev_dbg(dev, "adding to PM domain %s\n", pd->name);
 
-       while (1) {
+       for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
                ret = pm_genpd_add_device(pd, dev);
                if (ret != -EAGAIN)
                        break;
+
+               mdelay(i);
                cond_resched();
        }
 
        if (ret < 0) {
                dev_err(dev, "failed to add to PM domain %s: %d",
                        pd->name, ret);
-               of_node_put(dev->of_node);
-               return ret;
+               goto out;
        }
 
        dev->pm_domain->detach = genpd_dev_pm_detach;
        dev->pm_domain->sync = genpd_dev_pm_sync;
-       pm_genpd_poweron(pd);
+       ret = genpd_poweron(pd);
 
-       return 0;
+out:
+       return ret ? -EPROBE_DEFER : 0;
 }
 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
@@ -2274,9 +1863,6 @@ static int pm_genpd_summary_one(struct seq_file *s,
 {
        static const char * const status_lookup[] = {
                [GPD_STATE_ACTIVE] = "on",
-               [GPD_STATE_WAIT_MASTER] = "wait-master",
-               [GPD_STATE_BUSY] = "busy",
-               [GPD_STATE_REPEAT] = "off-in-progress",
                [GPD_STATE_POWER_OFF] = "off"
        };
        struct pm_domain_data *pm_data;
@@ -2290,7 +1876,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
 
        if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup)))
                goto exit;
-       seq_printf(s, "%-30s  %-15s  ", genpd->name, status_lookup[genpd->status]);
+       seq_printf(s, "%-30s  %-15s ", genpd->name, status_lookup[genpd->status]);
 
        /*
         * Modifications on the list require holding locks on both
@@ -2325,8 +1911,8 @@ static int pm_genpd_summary_show(struct seq_file *s, void *data)
        struct generic_pm_domain *genpd;
        int ret = 0;
 
-       seq_puts(s, "    domain                      status         slaves\n");
-       seq_puts(s, "           /device                                      runtime status\n");
+       seq_puts(s, "domain                          status          slaves\n");
+       seq_puts(s, "    /device                                             runtime status\n");
        seq_puts(s, "----------------------------------------------------------------------\n");
 
        ret = mutex_lock_interruptible(&gpd_list_lock);