]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/power/qos.c
Merge branch 'pm-sleep-next' into linux-next
[karo-tx-linux.git] / kernel / power / qos.c
index 4da05cee81bfe1a6eb1c9aa90a1ab35fe98f7f3a..9322ff7eaad68d41512763d3b337d123601f32b7 100644 (file)
@@ -212,6 +212,69 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
        }
 }
 
+/**
+ * pm_qos_flags_remove_req - Remove device PM QoS flags request.
+ * @pqf: Device PM QoS flags set to remove the request from.
+ * @req: Request to remove from the set.
+ */
+static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
+                                   struct pm_qos_flags_request *req)
+{
+       s32 val = 0;
+
+       list_del(&req->node);
+       list_for_each_entry(req, &pqf->list, node)
+               val |= req->flags;
+
+       pqf->effective_flags = val;
+}
+
+/**
+ * pm_qos_update_flags - Update a set of PM QoS flags.
+ * @pqf: Set of flags to update.
+ * @req: Request to add to the set, to modify, or to remove from the set.
+ * @action: Action to take on the set.
+ * @val: Value of the request to add or modify.
+ *
+ * Update the given set of PM QoS flags and call notifiers if the aggregate
+ * value has changed.  Returns 1 if the aggregate constraint value has changed,
+ * 0 otherwise.
+ */
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+                        struct pm_qos_flags_request *req,
+                        enum pm_qos_req_action action, s32 val)
+{
+       unsigned long irqflags;
+       s32 prev_value, curr_value;
+
+       spin_lock_irqsave(&pm_qos_lock, irqflags);
+
+       prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+       switch (action) {
+       case PM_QOS_REMOVE_REQ:
+               pm_qos_flags_remove_req(pqf, req);
+               break;
+       case PM_QOS_UPDATE_REQ:
+               pm_qos_flags_remove_req(pqf, req);
+       case PM_QOS_ADD_REQ:
+               req->flags = val;
+               INIT_LIST_HEAD(&req->node);
+               list_add_tail(&req->node, &pqf->list);
+               pqf->effective_flags |= val;
+               break;
+       default:
+               /* no action */
+               ;
+       }
+
+       curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+       spin_unlock_irqrestore(&pm_qos_lock, irqflags);
+
+       return prev_value != curr_value;
+}
+
 /**
  * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested