#include <linux/mutex.h>
 #include <linux/export.h>
 #include <linux/pm_runtime.h>
+#include <linux/err.h>
 
 #include "power.h"
 
        struct pm_qos_flags *pqf;
        s32 val;
 
-       if (!qos)
+       if (IS_ERR_OR_NULL(qos))
                return PM_QOS_FLAGS_UNDEFINED;
 
        pqf = &qos->flags;
  */
 s32 __dev_pm_qos_read_value(struct device *dev)
 {
-       return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
+       return IS_ERR_OR_NULL(dev->power.qos) ?
+               0 : pm_qos_read_value(&dev->power.qos->latency);
 }
 
 /**
        return 0;
 }
 
-/**
- * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
- * @dev: target device
- *
- * Called from the device PM subsystem during device insertion under
- * device_pm_lock().
- */
-void dev_pm_qos_constraints_init(struct device *dev)
-{
-       mutex_lock(&dev_pm_qos_mtx);
-       dev->power.qos = NULL;
-       dev->power.power_state = PMSG_ON;
-       mutex_unlock(&dev_pm_qos_mtx);
-}
+static void __dev_pm_qos_hide_latency_limit(struct device *dev);
+static void __dev_pm_qos_hide_flags(struct device *dev);
 
 /**
  * dev_pm_qos_constraints_destroy
        struct pm_qos_constraints *c;
        struct pm_qos_flags *f;
 
+       mutex_lock(&dev_pm_qos_mtx);
+
        /*
         * If the device's PM QoS resume latency limit or PM QoS flags have been
         * exposed to user space, they have to be hidden at this point.
         */
-       dev_pm_qos_hide_latency_limit(dev);
-       dev_pm_qos_hide_flags(dev);
-
-       mutex_lock(&dev_pm_qos_mtx);
+       __dev_pm_qos_hide_latency_limit(dev);
+       __dev_pm_qos_hide_flags(dev);
 
-       dev->power.power_state = PMSG_INVALID;
        qos = dev->power.qos;
        if (!qos)
                goto out;
        }
 
        spin_lock_irq(&dev->power.lock);
-       dev->power.qos = NULL;
+       dev->power.qos = ERR_PTR(-ENODEV);
        spin_unlock_irq(&dev->power.lock);
 
        kfree(c->notifiers);
                 "%s() called for already added request\n", __func__))
                return -EINVAL;
 
-       req->dev = dev;
-
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos) {
-               if (dev->power.power_state.event == PM_EVENT_INVALID) {
-                       /* The device has been removed from the system. */
-                       req->dev = NULL;
-                       ret = -ENODEV;
-                       goto out;
-               } else {
-                       /*
-                        * Allocate the constraints data on the first call to
-                        * add_request, i.e. only if the data is not already
-                        * allocated and if the device has not been removed.
-                        */
-                       ret = dev_pm_qos_constraints_allocate(dev);
-               }
-       }
+       if (IS_ERR(dev->power.qos))
+               ret = -ENODEV;
+       else if (!dev->power.qos)
+               ret = dev_pm_qos_constraints_allocate(dev);
 
        if (!ret) {
+               req->dev = dev;
                req->type = type;
                ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
        }
 
- out:
        mutex_unlock(&dev_pm_qos_mtx);
 
        return ret;
                 "%s() called for unknown object\n", __func__))
                return -EINVAL;
 
-       if (!req->dev->power.qos)
+       if (IS_ERR_OR_NULL(req->dev->power.qos))
                return -ENODEV;
 
        switch(req->type) {
 
 static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 {
-       int ret = 0;
+       int ret;
 
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
                 "%s() called for unknown object\n", __func__))
                return -EINVAL;
 
-       if (req->dev->power.qos) {
-               ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
-                                      PM_QOS_DEFAULT_VALUE);
-               memset(req, 0, sizeof(*req));
-       } else {
-               ret = -ENODEV;
-       }
+       if (IS_ERR_OR_NULL(req->dev->power.qos))
+               return -ENODEV;
+
+       ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+       memset(req, 0, sizeof(*req));
        return ret;
 }
 
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos)
-               ret = dev->power.power_state.event != PM_EVENT_INVALID ?
-                       dev_pm_qos_constraints_allocate(dev) : -ENODEV;
+       if (IS_ERR(dev->power.qos))
+               ret = -ENODEV;
+       else if (!dev->power.qos)
+               ret = dev_pm_qos_constraints_allocate(dev);
 
        if (!ret)
                ret = blocking_notifier_chain_register(
        mutex_lock(&dev_pm_qos_mtx);
 
        /* Silently return if the constraints object is not present. */
-       if (dev->power.qos)
+       if (!IS_ERR_OR_NULL(dev->power.qos))
                retval = blocking_notifier_chain_unregister(
                                dev->power.qos->latency.notifiers,
                                notifier);
 
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos)
+       if (IS_ERR_OR_NULL(dev->power.qos))
                ret = -ENODEV;
        else if (dev->power.qos->latency_req)
                ret = -EEXIST;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
+static void __dev_pm_qos_hide_latency_limit(struct device *dev)
+{
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
+               pm_qos_sysfs_remove_latency(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+       }
+}
+
 /**
  * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space.
  * @dev: Device whose PM QoS latency limit is to be hidden from user space.
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
        mutex_lock(&dev_pm_qos_mtx);
-
-       if (dev->power.qos && dev->power.qos->latency_req) {
-               pm_qos_sysfs_remove_latency(dev);
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
-       }
-
+       __dev_pm_qos_hide_latency_limit(dev);
        mutex_unlock(&dev_pm_qos_mtx);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
        pm_runtime_get_sync(dev);
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos)
+       if (IS_ERR_OR_NULL(dev->power.qos))
                ret = -ENODEV;
        else if (dev->power.qos->flags_req)
                ret = -EEXIST;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
 
+static void __dev_pm_qos_hide_flags(struct device *dev)
+{
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
+               pm_qos_sysfs_remove_flags(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+       }
+}
+
 /**
  * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
  * @dev: Device whose PM QoS flags are to be hidden from user space.
 {
        pm_runtime_get_sync(dev);
        mutex_lock(&dev_pm_qos_mtx);
-
-       if (dev->power.qos && dev->power.qos->flags_req) {
-               pm_qos_sysfs_remove_flags(dev);
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
-       }
-
+       __dev_pm_qos_hide_flags(dev);
        mutex_unlock(&dev_pm_qos_mtx);
        pm_runtime_put(dev);
 }
        pm_runtime_get_sync(dev);
        mutex_lock(&dev_pm_qos_mtx);
 
-       if (!dev->power.qos || !dev->power.qos->flags_req) {
+       if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) {
                ret = -EINVAL;
                goto out;
        }
        pm_runtime_put(dev);
        return ret;
 }
+#else /* !CONFIG_PM_RUNTIME */
+static void __dev_pm_qos_hide_latency_limit(struct device *dev) {}
+static void __dev_pm_qos_hide_flags(struct device *dev) {}
 #endif /* CONFIG_PM_RUNTIME */