stop_latency_ns, "stop");
 }
 
-static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
+static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev,
+                       bool timed)
 {
+       if (!timed)
+               return GENPD_DEV_CALLBACK(genpd, int, start, dev);
+
        return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
                                        start_latency_ns, "start");
 }
        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;
  * resume a device belonging to it.
  */
 static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
-       __releases(&genpd->lock) __acquires(&genpd->lock)
 {
        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;
         */
        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);
                if (ret) {
                        genpd_sd_counter_dec(link->master);
                        goto err;
                goto err;
 
  out:
-       genpd_set_active(genpd);
-
+       genpd->status = GPD_STATE_ACTIVE;
        return 0;
 
  err:
        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");
 }
 
-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, bool timed)
 {
+       if (!timed)
+               return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
+
        return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
                                        restore_state_latency_ns,
                                        "state restore");
        return NOTIFY_DONE;
 }
 
-/**
- * __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.
  * @genpd: PM domain to power down.
  *
  * 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)
 {
        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;
 
        if (not_suspended > genpd->in_progress)
                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
                cpuidle_pause_and_lock();
                genpd->cpuidle_data->idle_state->disabled = false;
                cpuidle_resume_and_unlock();
-               goto out;
+               return 0;
        }
 
        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
                 * happen very often).
                 */
                ret = genpd_power_off(genpd, true);
-               if (ret == -EBUSY) {
-                       genpd_set_active(genpd);
-                       goto out;
-               }
+               if (ret)
+                       return ret;
        }
 
        genpd->status = GPD_STATE_POWER_OFF;
                genpd_queue_power_off_work(link->master);
        }
 
- out:
-       genpd->poweroff_task = NULL;
-       wake_up_all(&genpd->status_wait_queue);
-       return ret;
+       return 0;
 }
 
 /**
 
        genpd = container_of(work, struct generic_pm_domain, power_off_work);
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
        pm_genpd_poweroff(genpd);
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 }
 
 /**
 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);
        int ret;
 
        if (stop_ok && !stop_ok(dev))
                return -EBUSY;
 
-       ret = genpd_stop_dev(genpd, dev);
+       ret = genpd_save_dev(genpd, dev);
        if (ret)
                return ret;
 
+       ret = genpd_stop_dev(genpd, dev);
+       if (ret) {
+               genpd_restore_dev(genpd, dev, true);
+               return ret;
+       }
+
        /*
         * If power.irq_safe is set, this routine will be run with interrupts
         * off, so it can't use mutexes.
                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--;
 static int pm_genpd_runtime_resume(struct device *dev)
 {
        struct generic_pm_domain *genpd;
-       DEFINE_WAIT(wait);
        int ret;
+       bool timed = true;
 
        dev_dbg(dev, "%s()\n", __func__);
 
                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);
-               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);
+       mutex_unlock(&genpd->lock);
 
-               schedule();
+       if (ret)
+               return ret;
 
-               mutex_lock(&genpd->lock);
-       }
-       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);
+ out:
+       genpd_start_dev(genpd, dev, timed);
+       genpd_restore_dev(genpd, dev, timed);
 
        return 0;
 }
 {
        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) {
        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);
        pm_genpd_sync_poweron(genpd, true);
        genpd->suspended_count--;
 
-       return genpd_start_dev(genpd, dev);
+       return genpd_start_dev(genpd, dev, true);
 }
 
 /**
        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, true);
 }
 
 /**
 
        pm_genpd_sync_poweron(genpd, true);
 
-       return genpd_start_dev(genpd, dev);
+       return genpd_start_dev(genpd, dev, true);
 }
 
 /**
                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;
        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;
        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);
        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;
 
        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;
            || genpd == subdomain)
                return -EINVAL;
 
- start:
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
        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;
-       }
-
        if (genpd->status == GPD_STATE_POWER_OFF
            &&  subdomain->status != GPD_STATE_POWER_OFF) {
                ret = -EINVAL;
 
  out:
        mutex_unlock(&subdomain->lock);
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 
        return ret;
 }
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
                return -EINVAL;
 
- start:
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        list_for_each_entry(link, &genpd->master_links, master_node) {
                if (link->slave != subdomain)
 
                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);
                break;
        }
 
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
 
        return ret;
 }
        if (IS_ERR_OR_NULL(genpd) || state < 0)
                return -EINVAL;
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        if (genpd->cpuidle_data) {
                ret = -EEXIST;
        genpd_recalc_cpu_exit_latency(genpd);
 
  out:
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
        return ret;
 
  err:
        if (IS_ERR_OR_NULL(genpd))
                return -EINVAL;
 
-       genpd_acquire_lock(genpd);
+       mutex_lock(&genpd->lock);
 
        cpuidle_data = genpd->cpuidle_data;
        if (!cpuidle_data) {
        kfree(cpuidle_data);
 
  out:
-       genpd_release_lock(genpd);
+       mutex_unlock(&genpd->lock);
        return ret;
 }
 
        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;
 {
        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;