diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 4a6d59e50de5..3d913f457fce 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -265,7 +265,8 @@ static const struct file_operations pm_qos_debug_fops = { .release = single_release, }; -static inline void pm_qos_set_value_for_cpus(struct pm_qos_constraints *c) +static inline void pm_qos_set_value_for_cpus(struct pm_qos_constraints *c, + struct cpumask *cpus) { struct pm_qos_request *req = NULL; int cpu; @@ -288,8 +289,11 @@ static inline void pm_qos_set_value_for_cpus(struct pm_qos_constraints *c) } } - for_each_possible_cpu(cpu) + for_each_possible_cpu(cpu) { + if (c->target_per_cpu[cpu] != qos_val[cpu]) + cpumask_set_cpu(cpu, cpus); c->target_per_cpu[cpu] = qos_val[cpu]; + } } /** @@ -308,6 +312,7 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, { unsigned long flags; int prev_value, curr_value, new_value; + struct cpumask cpus; int ret; spin_lock_irqsave(&pm_qos_lock, flags); @@ -339,18 +344,24 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, } curr_value = pm_qos_get_value(c); + cpumask_clear(&cpus); pm_qos_set_value(c, curr_value); - pm_qos_set_value_for_cpus(c); + pm_qos_set_value_for_cpus(c, &cpus); spin_unlock_irqrestore(&pm_qos_lock, flags); trace_pm_qos_update_target(action, prev_value, curr_value); - if (prev_value != curr_value) { + + /* + * if cpu mask bits are set, call the notifier call chain + * to update the new qos restriction for the cores + */ + + if (!cpumask_empty(&cpus)) { ret = 1; if (c->notifiers) blocking_notifier_call_chain(c->notifiers, - (unsigned long)curr_value, - NULL); + (unsigned long)curr_value, &cpus); } else { ret = 0; }