*
  * This QoS design is best effort based. Dependents register their QoS needs.
  * Watchers register to keep track of the current QoS needs of the system.
+ * Watchers can register different types of notification callbacks:
+ *  . a per-device notification callback using the dev_pm_qos_*_notifier API.
+ *    The notification chain data is stored in the per-device constraint
+ *    data struct.
+ *  . a system-wide notification callback using the dev_pm_qos_*_global_notifier
+ *    API. The notification chain data is stored in a static variable.
  *
  * Note about the per-device constraint data struct allocation:
  * . The per-device constraints data struct ptr is tored into the device
 
 
 static DEFINE_MUTEX(dev_pm_qos_mtx);
+static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
+
+/*
+ * apply_constraint
+ * @req: constraint request to apply
+ * @action: action to perform add/update/remove, of type enum pm_qos_req_action
+ * @value: defines the qos request
+ *
+ * Internal function to update the constraints list using the PM QoS core
+ * code and if needed call the per-device and the global notification
+ * callbacks
+ */
+static int apply_constraint(struct dev_pm_qos_request *req,
+                           enum pm_qos_req_action action, int value)
+{
+       int ret, curr_value;
+
+       ret = pm_qos_update_target(req->dev->power.constraints,
+                                  &req->node, action, value);
+
+       if (ret) {
+               /* Call the global callbacks if needed */
+               curr_value = pm_qos_read_value(req->dev->power.constraints);
+               blocking_notifier_call_chain(&dev_pm_notifiers,
+                                            (unsigned long)curr_value,
+                                            req);
+       }
+
+       return ret;
+}
 
 /*
  * dev_pm_qos_constraints_allocate
                                          &dev->power.constraints->list,
                                          node) {
                        /*
-                        * Update constraints list and call the per-device
+                        * Update constraints list and call the notification
                         * callbacks if needed
                         */
-                       pm_qos_update_target(req->dev->power.constraints,
-                                          &req->node, PM_QOS_REMOVE_REQ,
-                                          PM_QOS_DEFAULT_VALUE);
+                       apply_constraint(req, PM_QOS_REMOVE_REQ,
+                                        PM_QOS_DEFAULT_VALUE);
                        memset(req, 0, sizeof(*req));
                }
 
  * removed from the system
  */
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
-                           s32 value)
+                          s32 value)
 {
        int ret = 0;
 
                ret = dev_pm_qos_constraints_allocate(dev);
 
        if (!ret)
-               ret = pm_qos_update_target(dev->power.constraints, &req->node,
-                                          PM_QOS_ADD_REQ, value);
+               ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
 
 out:
        mutex_unlock(&dev_pm_qos_mtx);
 
        if (req->dev->power.constraints_state == DEV_PM_QOS_ALLOCATED) {
                if (new_value != req->node.prio)
-                       ret = pm_qos_update_target(req->dev->power.constraints,
-                                                  &req->node,
-                                                  PM_QOS_UPDATE_REQ,
-                                                  new_value);
+                       ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
+                                              new_value);
        } else {
                /* Return if the device has been removed */
                ret = -ENODEV;
        mutex_lock(&dev_pm_qos_mtx);
 
        if (req->dev->power.constraints_state == DEV_PM_QOS_ALLOCATED) {
-               ret = pm_qos_update_target(req->dev->power.constraints,
-                                          &req->node, PM_QOS_REMOVE_REQ,
-                                          PM_QOS_DEFAULT_VALUE);
+               ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
+                                      PM_QOS_DEFAULT_VALUE);
                memset(req, 0, sizeof(*req));
        } else {
                /* Return if the device has been removed */
        return retval;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
+
+/**
+ * dev_pm_qos_add_global_notifier - sets notification entry for changes to
+ * target value of the PM QoS constraints for any device
+ *
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
+{
+       return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);
+
+/**
+ * dev_pm_qos_remove_global_notifier - deletes notification for changes to
+ * target value of PM QoS constraints for any device
+ *
+ * @notifier: notifier block to be removed.
+ *
+ * Will remove the notifier from the notification chain that gets called
+ * upon changes to the target value for any device.
+ */
+int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
+{
+       return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
 
 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
 int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
 int pm_qos_request_active(struct pm_qos_request *req);
+s32 pm_qos_read_value(struct pm_qos_constraints *c);
 
 int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
                           s32 value);
                            struct notifier_block *notifier);
 int dev_pm_qos_remove_notifier(struct device *dev,
                               struct notifier_block *notifier);
+int dev_pm_qos_add_global_notifier(struct notifier_block *notifier);
+int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier);
 void dev_pm_qos_constraints_init(struct device *dev);
 void dev_pm_qos_constraints_destroy(struct device *dev);
 #else
                        { return 0; }
 static inline int pm_qos_request_active(struct pm_qos_request *req)
                        { return 0; }
+static inline s32 pm_qos_read_value(struct pm_qos_constraints *c)
+                       { return 0; }
 
 static inline int dev_pm_qos_add_request(struct device *dev,
                                         struct dev_pm_qos_request *req,
 static inline int dev_pm_qos_remove_notifier(struct device *dev,
                                             struct notifier_block *notifier)
                        { return 0; }
+static inline int dev_pm_qos_add_global_notifier(
+                                       struct notifier_block *notifier)
+                       { return 0; }
+static inline int dev_pm_qos_remove_global_notifier(
+                                       struct notifier_block *notifier)
+                       { return 0; }
 static inline void dev_pm_qos_constraints_init(struct device *dev)
                        { return; }
 static inline void dev_pm_qos_constraints_destroy(struct device *dev)