On 20 March 2017 at 10:32, Viresh Kumar <viresh.ku...@linaro.org> wrote: > Only the resume_latency constraint uses the notifiers right now. In > order to prepare for adding new constraint types with notifiers, move to > a common notifier list. > > Update pm_qos_update_target() to pass a pointer to the constraint > structure to the notifier callbacks. Also update the notifier callbacks > as well to error out for unexpected constraints. > > Signed-off-by: Viresh Kumar <viresh.ku...@linaro.org> > --- > drivers/base/power/domain.c | 26 +++++++++++++++++++------- > drivers/base/power/qos.c | 15 ++++----------- > include/linux/pm_qos.h | 7 +++++++ > kernel/power/qos.c | 2 +- > 4 files changed, 31 insertions(+), 19 deletions(-) > > diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c > index 1a0549f1944a..6e4e22aa14a2 100644 > --- a/drivers/base/power/domain.c > +++ b/drivers/base/power/domain.c > @@ -416,14 +416,10 @@ static int genpd_power_on(struct generic_pm_domain > *genpd, unsigned int depth) > return ret; > } > > -static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, > - unsigned long val, void *ptr) > +static int __resume_latency_notifier(struct generic_pm_domain_data *gpd_data, > + unsigned long val)
Could you perhaps rename this to genpd_latency_notifier(), as I think it better follows the naming conventions in genpd. > { > - struct generic_pm_domain_data *gpd_data; > - struct device *dev; > - > - gpd_data = container_of(nb, struct generic_pm_domain_data, nb); > - dev = gpd_data->base.dev; > + struct device *dev = gpd_data->base.dev; > > for (;;) { > struct generic_pm_domain *genpd; > @@ -456,6 +452,22 @@ static int genpd_dev_pm_qos_notifier(struct > notifier_block *nb, > return NOTIFY_DONE; > } > > +static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, > + unsigned long val, void *ptr) > +{ > + struct generic_pm_domain_data *gpd_data; > + struct device *dev; > + > + gpd_data = container_of(nb, struct generic_pm_domain_data, nb); > + dev = gpd_data->base.dev; > + > + if (dev_pm_qos_notifier_is_resume_latency(dev, ptr)) > + return __resume_latency_notifier(gpd_data, val); > + > + dev_err(dev, "%s: Unexpected notifier call\n", __func__); > + return NOTIFY_BAD; > +} > + > /** > * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0. > * @work: Work structure used for scheduling the execution of this function. > diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c > index f850daeffba4..654d8a12c2e7 100644 > --- a/drivers/base/power/qos.c > +++ b/drivers/base/power/qos.c > @@ -172,18 +172,12 @@ static int dev_pm_qos_constraints_allocate(struct > device *dev) > { > struct dev_pm_qos *qos; > struct pm_qos_constraints *c; > - struct blocking_notifier_head *n; > > qos = kzalloc(sizeof(*qos), GFP_KERNEL); > if (!qos) > return -ENOMEM; > > - n = kzalloc(sizeof(*n), GFP_KERNEL); > - if (!n) { > - kfree(qos); > - return -ENOMEM; > - } > - BLOCKING_INIT_NOTIFIER_HEAD(n); > + BLOCKING_INIT_NOTIFIER_HEAD(&qos->notifiers); > > c = &qos->resume_latency; > plist_head_init(&c->list); > @@ -191,7 +185,7 @@ static int dev_pm_qos_constraints_allocate(struct device > *dev) > c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; > c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; > c->type = PM_QOS_MIN; > - c->notifiers = n; > + c->notifiers = &qos->notifiers; > > c = &qos->latency_tolerance; > plist_head_init(&c->list); > @@ -268,7 +262,6 @@ void dev_pm_qos_constraints_destroy(struct device *dev) > dev->power.qos = ERR_PTR(-ENODEV); > spin_unlock_irq(&dev->power.lock); > > - kfree(qos->resume_latency.notifiers); > kfree(qos); > > out: > @@ -487,7 +480,7 @@ int dev_pm_qos_add_notifier(struct device *dev, struct > notifier_block *notifier) > ret = dev_pm_qos_constraints_allocate(dev); > > if (!ret) > - ret = > blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers, > + ret = > blocking_notifier_chain_register(&dev->power.qos->notifiers, > notifier); > > mutex_unlock(&dev_pm_qos_mtx); > @@ -514,7 +507,7 @@ int dev_pm_qos_remove_notifier(struct device *dev, > > /* Silently return if the constraints object is not present. */ > if (!IS_ERR_OR_NULL(dev->power.qos)) > - retval = > blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers, > + retval = > blocking_notifier_chain_unregister(&dev->power.qos->notifiers, > notifier); > > mutex_unlock(&dev_pm_qos_mtx); > diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h > index 032b55909145..bcae6abb3f21 100644 > --- a/include/linux/pm_qos.h > +++ b/include/linux/pm_qos.h > @@ -100,6 +100,7 @@ struct dev_pm_qos { > struct dev_pm_qos_request *resume_latency_req; > struct dev_pm_qos_request *latency_tolerance_req; > struct dev_pm_qos_request *flags_req; > + struct blocking_notifier_head notifiers; /* common for all > constraints */ > }; > > /* Action requested to pm_qos_update_target */ > @@ -114,6 +115,12 @@ static inline int dev_pm_qos_request_active(struct > dev_pm_qos_request *req) > return req->dev != NULL; > } > > +static inline bool dev_pm_qos_notifier_is_resume_latency(struct device *dev, A quite long name... Maybe we can remove "notifier", such as :dev_pm_qos_is_resume_latency()? > + struct pm_qos_constraints *c) > +{ > + return &dev->power.qos->resume_latency == c; > +} > + > int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node > *node, > enum pm_qos_req_action action, int value); > bool pm_qos_update_flags(struct pm_qos_flags *pqf, > diff --git a/kernel/power/qos.c b/kernel/power/qos.c > index 97b0df71303e..073324e0c3c8 100644 > --- a/kernel/power/qos.c > +++ b/kernel/power/qos.c > @@ -315,7 +315,7 @@ int pm_qos_update_target(struct pm_qos_constraints *c, > struct plist_node *node, > if (c->notifiers) > blocking_notifier_call_chain(c->notifiers, > (unsigned > long)curr_value, > - NULL); > + c); > } else { > ret = 0; > } > -- > 2.12.0.432.g71c3a4f4ba37 > Besides the nitpicks above, feel free to add: Acked-by: Ulf Hansson <ulf.hans...@linaro.org> Kind regards Uffe