On 20 March 2017 at 10:32, Viresh Kumar viresh.kumar@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.kumar@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.hansson@linaro.org
Kind regards Uffe