PM QoS: Add disable parameter
Antti P Miettinen [Mon, 20 Aug 2012 16:36:38 +0000 (19:36 +0300)]
For testing purposes it is useful to be able to disable
PM Qos.

Bug 1020898
Bug 917572

Change-Id: I266f5b5730cfe4705197d8b09db7f9eda6766c7c
Signed-off-by: Antti P Miettinen <amiettinen@nvidia.com>
Reviewed-on: http://git-master/r/124667
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>

kernel/pm_qos_params.c

index 82da7ac..c52405c 100644 (file)
@@ -174,6 +174,8 @@ static const struct file_operations pm_qos_power_fops = {
        .llseek = noop_llseek,
 };
 
+static bool pm_qos_enabled __read_mostly = true;
+
 /* unlocked internal variant */
 static inline int pm_qos_get_value(struct pm_qos_object *o)
 {
@@ -226,8 +228,11 @@ static void update_target(struct pm_qos_object *o, struct plist_node *node,
        } else {
                plist_add(node, &o->requests);
        }
-       curr_value = pm_qos_get_value(o);
-       pm_qos_set_value(o, curr_value);
+       if (pm_qos_enabled) {
+               curr_value = pm_qos_get_value(o);
+               pm_qos_set_value(o, curr_value);
+       } else
+               curr_value = o->default_value;
        spin_unlock_irqrestore(&pm_qos_lock, flags);
 
        if (prev_value != curr_value)
@@ -372,6 +377,58 @@ void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
 }
 EXPORT_SYMBOL_GPL(pm_qos_remove_request);
 
+static int pm_qos_enabled_set(const char *arg, const struct kernel_param *kp)
+{
+       unsigned long flags;
+       bool old;
+       s32 prev[PM_QOS_NUM_CLASSES], curr[PM_QOS_NUM_CLASSES];
+       int ret, i;
+
+       old = pm_qos_enabled;
+       ret = param_set_bool(arg, kp);
+       if (ret != 0) {
+               pr_warn("%s: cannot set PM QoS enable to %s\n",
+                       __FUNCTION__, arg);
+               return ret;
+       }
+       spin_lock_irqsave(&pm_qos_lock, flags);
+       for (i = 1; i < PM_QOS_NUM_CLASSES; i++)
+               prev[i] = pm_qos_read_value(pm_qos_array[i]);
+       if (old && !pm_qos_enabled) {
+               /* got disabled */
+               for (i = 1; i < PM_QOS_NUM_CLASSES; i++) {
+                       curr[i] = pm_qos_array[i]->default_value;
+                       pm_qos_set_value(pm_qos_array[i], curr[i]);
+               }
+       } else if (!old && pm_qos_enabled) {
+               /* got enabled */
+               for (i = 1; i < PM_QOS_NUM_CLASSES; i++) {
+                       curr[i] = pm_qos_get_value(pm_qos_array[i]);
+                       pm_qos_set_value(pm_qos_array[i], curr[i]);
+               }
+       }
+       spin_unlock_irqrestore(&pm_qos_lock, flags);
+       for (i = 1; i < PM_QOS_NUM_CLASSES; i++)
+               if (prev[i] != curr[i])
+                       blocking_notifier_call_chain(
+                               pm_qos_array[i]->notifiers,
+                               (unsigned long)curr[i],
+                               NULL);
+
+       return ret;
+}
+
+static int pm_qos_enabled_get(char *buffer, const struct kernel_param *kp)
+{
+       return param_get_bool(buffer, kp);
+}
+
+static struct kernel_param_ops pm_qos_enabled_ops = {
+       .set = pm_qos_enabled_set,
+       .get = pm_qos_enabled_get,
+};
+module_param_cb(enable, &pm_qos_enabled_ops, &pm_qos_enabled, 0644);
+
 /**
  * pm_qos_add_notifier - sets notification entry for changes to target value
  * @pm_qos_class: identifies which qos target changes should be notified.