On 16.10.2019 13:48, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > > Introduce frequency QoS, based on the "raw" low-level PM QoS, to > represent min and max frequency requests and aggregate constraints. > > The min and max frequency requests are to be represented by > struct freq_qos_request objects and the aggregate constraints are to > be represented by struct freq_constraints objects. The latter are > expected to be initialized with the help of freq_constraints_init(). > > The freq_qos_read_value() helper is defined to retrieve the aggregate > constraints values from a given struct freq_constraints object and > there are the freq_qos_add_request(), freq_qos_update_request() and > freq_qos_remove_request() helpers to manipulate the min and max > frequency requests. It is assumed that the the helpers will not > run concurrently with each other for the same struct freq_qos_request > object, so if that may be the case, their uses must ensure proper > synchronization between them (e.g. through locking). > > In addition, freq_qos_add_notifier() and freq_qos_remove_notifier() > are provided to add and remove notifiers that will trigger on aggregate > constraint changes to and from a given struct freq_constraints object, > respectively. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > --- > include/linux/pm_qos.h | 44 ++++++++ > kernel/power/qos.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 284 insertions(+) > > Index: linux-pm/include/linux/pm_qos.h > =================================================================== > --- linux-pm.orig/include/linux/pm_qos.h > +++ linux-pm/include/linux/pm_qos.h > @@ -267,4 +267,48 @@ static inline s32 dev_pm_qos_raw_resume_ > } > #endif > > +#define FREQ_QOS_MIN_DEFAULT_VALUE 0 > +#define FREQ_QOS_MAX_DEFAULT_VALUE (-1) > + > +enum freq_qos_req_type { > + FREQ_QOS_MIN = 1, > + FREQ_QOS_MAX, > +}; > + > +struct freq_constraints { > + struct pm_qos_constraints min_freq; > + struct blocking_notifier_head min_freq_notifiers; > + struct pm_qos_constraints max_freq; > + struct blocking_notifier_head max_freq_notifiers; These min/max_freq_notifiers fields seem unused? They're initialized but the freq_qos_add/remove_notifier calls use min/max_freq.notifiers directly. Should probably just be dropped. > +/** > + * freq_qos_add_notifier - Add frequency QoS change notifier. > + * @qos: List of requests to add the notifier to. > + * @type: Request type. > + * @notifier: Notifier block to add. > + */ > +int freq_qos_add_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier) > +{ > + int ret; > + > + if (IS_ERR_OR_NULL(qos) || !notifier) > + return -EINVAL; > + > + switch (type) { > + case FREQ_QOS_MIN: > + ret = blocking_notifier_chain_register(qos->min_freq.notifiers, > + notifier); > + break; > + case FREQ_QOS_MAX: > + ret = blocking_notifier_chain_register(qos->max_freq.notifiers, > + notifier); > + break; > + default: > + WARN_ON(1); > + ret = -EINVAL; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(freq_qos_add_notifier); > + > +/** > + * freq_qos_remove_notifier - Remove frequency QoS change notifier. > + * @qos: List of requests to remove the notifier from. > + * @type: Request type. > + * @notifier: Notifier block to remove. > + */ > +int freq_qos_remove_notifier(struct freq_constraints *qos, > + enum freq_qos_req_type type, > + struct notifier_block *notifier) > +{ > + int ret; > + > + if (IS_ERR_OR_NULL(qos) || !notifier) > + return -EINVAL; > + > + switch (type) { > + case FREQ_QOS_MIN: > + ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers, > + notifier); > + break; > + case FREQ_QOS_MAX: > + ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers, > + notifier); > + break; > + default: > + WARN_ON(1); > + ret = -EINVAL; > + } > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);