From b5abb085f5540a612b0b7a6326ae2a07de2330dd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Aug 2012 01:06:11 +0200 Subject: PM / Domains: Make it possible to use domain names when adding devices Add a new helper function __pm_genpd_name_add_device() allowing a device to be added to a (registered) generic PM domain identified by name. Add a wrapper around it, pm_genpd_name_add_device(), passing NULL as the last argument and reorganize pm_domains.h for the new functions to be defined consistently with the existing ones. These functions are useful for adding devices to PM domains whose representations are stored in tables, when the caller doesn't know the index of the domain to add the device to, but it knows the domain's name. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5f4606f13be6..ac06d0280b42 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1465,6 +1465,33 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev, return __pm_genpd_add_device(genpd, dev, td); } + +/** + * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it. + * @domain_name: Name of the PM domain to add the device to. + * @dev: Device to be added. + * @td: Set of PM QoS timing parameters to attach to the device. + */ +int __pm_genpd_name_add_device(const char *domain_name, struct device *dev, + struct gpd_timing_data *td) +{ + struct generic_pm_domain *genpd = NULL, *gpd; + + if (IS_ERR_OR_NULL(domain_name) || IS_ERR_OR_NULL(dev)) + return -EINVAL; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(gpd, &gpd_list, gpd_list_node) { + if (!strcmp(gpd->name, domain_name)) { + genpd = gpd; + break; + } + } + mutex_unlock(&gpd_list_lock); + + return __pm_genpd_add_device(genpd, dev, td); +} + /** * pm_genpd_remove_device - Remove a device from an I/O PM domain. * @genpd: PM domain to remove the device from. -- cgit v1.2.3 From fb7268be9f72bed6ae48554f00f2dcb2ef333bfc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Aug 2012 01:08:37 +0200 Subject: PM / Domains: Make it possible to use names when adding subdomains Add a new helper function, pm_genpd_add_subdomain_names(), allowing the caller to add a subdomain to a generic PM domain using names for domain identification (both domains have to be initialized before). This function is useful for adding subdomains to PM domains whose representations are stored in tables, when the caller doesn't know the indices of the domain to add the subdomain to and of the subdomain itself, but it knows the domains' names. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 32 +++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 7 +++++++ 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index ac06d0280b42..cddf818f493c 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1584,7 +1584,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct gpd_link *link; int ret = 0; - if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) + if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain) + || genpd == subdomain) return -EINVAL; start: @@ -1630,6 +1631,35 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, return ret; } +/** + * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain. + * @master_name: Name of the master PM domain to add the subdomain to. + * @subdomain_name: Name of the subdomain to be added. + */ +int pm_genpd_add_subdomain_names(const char *master_name, + const char *subdomain_name) +{ + struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd; + + if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name)) + return -EINVAL; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(gpd, &gpd_list, gpd_list_node) { + if (!master && !strcmp(gpd->name, master_name)) + master = gpd; + + if (!subdomain && !strcmp(gpd->name, subdomain_name)) + subdomain = gpd; + + if (master && subdomain) + break; + } + mutex_unlock(&gpd_list_lock); + + return pm_genpd_add_subdomain(master, subdomain); +} + /** * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. * @genpd: Master PM domain to remove the subdomain from. diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 1991a92b0567..8dbf48b8336f 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -147,6 +147,8 @@ extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, extern void pm_genpd_dev_need_restore(struct device *dev, bool val); extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *new_subdomain); +extern int pm_genpd_add_subdomain_names(const char *master_name, + const char *subdomain_name); extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *target); extern int pm_genpd_add_callbacks(struct device *dev, @@ -202,6 +204,11 @@ static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, { return -ENOSYS; } +static inline int pm_genpd_add_subdomain_names(const char *master_name, + const char *subdomain_name) +{ + return -ENOSYS; +} static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *target) { -- cgit v1.2.3 From 8bc0251de2932e603f8ed73b76ba2d64b2dc1d18 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 7 Aug 2012 01:11:14 +0200 Subject: PM / Domains: Add power-on function using names to identify domains It sometimes is necessary to turn on a given PM domain when only the name of it is known and the domain pointer is not readily available. For this reason, add a new helper function, pm_genpd_name_poweron(), allowing the caller to turn on a PM domain using its name for identification. To avoid code duplication, move the domain lookup code to a separate function. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 46 ++++++++++++++++++++++++++++++--------------- include/linux/pm_domain.h | 5 +++++ 2 files changed, 36 insertions(+), 15 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index cddf818f493c..4d633406f375 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -53,6 +53,24 @@ static LIST_HEAD(gpd_list); static DEFINE_MUTEX(gpd_list_lock); +static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) +{ + struct generic_pm_domain *genpd = NULL, *gpd; + + if (IS_ERR_OR_NULL(domain_name)) + return NULL; + + mutex_lock(&gpd_list_lock); + list_for_each_entry(gpd, &gpd_list, gpd_list_node) { + if (!strcmp(gpd->name, domain_name)) { + genpd = gpd; + break; + } + } + mutex_unlock(&gpd_list_lock); + return genpd; +} + #ifdef CONFIG_PM struct generic_pm_domain *dev_to_genpd(struct device *dev) @@ -262,6 +280,18 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd) return ret; } +/** + * pm_genpd_name_poweron - Restore power to a given PM domain and its masters. + * @domain_name: Name of the PM domain to power up. + */ +int pm_genpd_name_poweron(const char *domain_name) +{ + struct generic_pm_domain *genpd; + + genpd = pm_genpd_lookup_name(domain_name); + return genpd ? pm_genpd_poweron(genpd) : -EINVAL; +} + #endif /* CONFIG_PM */ #ifdef CONFIG_PM_RUNTIME @@ -1475,21 +1505,7 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev, int __pm_genpd_name_add_device(const char *domain_name, struct device *dev, struct gpd_timing_data *td) { - struct generic_pm_domain *genpd = NULL, *gpd; - - if (IS_ERR_OR_NULL(domain_name) || IS_ERR_OR_NULL(dev)) - return -EINVAL; - - mutex_lock(&gpd_list_lock); - list_for_each_entry(gpd, &gpd_list, gpd_list_node) { - if (!strcmp(gpd->name, domain_name)) { - genpd = gpd; - break; - } - } - mutex_unlock(&gpd_list_lock); - - return __pm_genpd_add_device(genpd, dev, td); + return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td); } /** diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 8dbf48b8336f..d9d60835c29b 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -161,6 +161,7 @@ extern void pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); extern int pm_genpd_poweron(struct generic_pm_domain *genpd); +extern int pm_genpd_name_poweron(const char *domain_name); extern bool default_stop_ok(struct device *dev); @@ -240,6 +241,10 @@ static inline int pm_genpd_poweron(struct generic_pm_domain *genpd) { return -ENOSYS; } +static inline int pm_genpd_name_poweron(const char *domain_name) +{ + return -ENOSYS; +} static inline bool default_stop_ok(struct device *dev) { return false; -- cgit v1.2.3 From 40114447a7f89860b46a64e5504f313656cb5f27 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 20:32:43 +0200 Subject: PM / Domains: Document cpuidle-related functions and change their names The names of the cpuidle-related functions in drivers/base/power/domain.c are inconsistent with the names of the other exported functions in that file (the "pm_" prefix is missing from them) and they are missing kerneldoc comments. Fix that by adding the missing "pm_" prefix to the names of those functions and add kerneldoc comments documenting them. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 20 ++++++++++++++++++-- include/linux/pm_domain.h | 8 ++++---- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4d633406f375..e44e1a8e8376 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1829,7 +1829,16 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td) } EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks); -int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) +/** + * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle. + * @genpd: PM domain to be connected with cpuidle. + * @state: cpuidle state this domain can disable/enable. + * + * Make a PM domain behave as though it contained a CPU core, that is, instead + * of calling its power down routine it will enable the given cpuidle state so + * that the cpuidle subsystem can power it down (if possible and desirable). + */ +int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) { struct cpuidle_driver *cpuidle_drv; struct gpd_cpu_data *cpu_data; @@ -1878,7 +1887,14 @@ int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) goto out; } -int genpd_detach_cpuidle(struct generic_pm_domain *genpd) +/** + * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain. + * @genpd: PM domain to remove the cpuidle connection from. + * + * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the + * given PM domain. + */ +int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) { struct gpd_cpu_data *cpu_data; struct cpuidle_state *idle_state; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index d9d60835c29b..f2a633a913e7 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -155,8 +155,8 @@ extern int pm_genpd_add_callbacks(struct device *dev, struct gpd_dev_ops *ops, struct gpd_timing_data *td); extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td); -extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state); -extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd); +extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state); +extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd); extern void pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); @@ -225,11 +225,11 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td) { return -ENOSYS; } -static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st) +static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st) { return -ENOSYS; } -static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd) +static inline int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) { return -ENOSYS; } -- cgit v1.2.3 From 74a2799ab51acec9410f467fef8678ebb1125d7d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Aug 2012 20:32:59 +0200 Subject: PM / Domains: Operations related to cpuidle using domain names Make it possible to use domain names in operations connecting cpuidle to and disconnecting it from a PM domain. This is useful on platforms where PM domain objects are organized in such a way that the names of the domains are easier to use than the addresses of those objects. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 19 +++++++++++++++++++ include/linux/pm_domain.h | 10 ++++++++++ 2 files changed, 29 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e44e1a8e8376..12ad070c244f 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1887,6 +1887,16 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) goto out; } +/** + * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it. + * @name: Name of the domain to connect to cpuidle. + * @state: cpuidle state this domain can manipulate. + */ +int pm_genpd_name_attach_cpuidle(const char *name, int state) +{ + return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state); +} + /** * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain. * @genpd: PM domain to remove the cpuidle connection from. @@ -1925,6 +1935,15 @@ int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) return ret; } +/** + * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it. + * @name: Name of the domain to disconnect cpuidle from. + */ +int pm_genpd_name_detach_cpuidle(const char *name) +{ + return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name)); +} + /* Default device callbacks for generic PM domains. */ /** diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index f2a633a913e7..7c1d252b20c0 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -156,7 +156,9 @@ extern int pm_genpd_add_callbacks(struct device *dev, struct gpd_timing_data *td); extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td); extern int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state); +extern int pm_genpd_name_attach_cpuidle(const char *name, int state); extern int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd); +extern int pm_genpd_name_detach_cpuidle(const char *name); extern void pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); @@ -229,10 +231,18 @@ static inline int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int s { return -ENOSYS; } +static inline int pm_genpd_name_attach_cpuidle(const char *name, int state) +{ + return -ENOSYS; +} static inline int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd) { return -ENOSYS; } +static inline int pm_genpd_name_detach_cpuidle(const char *name) +{ + return -ENOSYS; +} static inline void pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off) { -- cgit v1.2.3 From b3d3b9fb6016e6eacd3ae49fb786806d00c43e7b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 6 Sep 2012 08:18:57 +0000 Subject: PM / Domains: Fix compilation warning related to genpd_start_dev_no_timing() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function genpd_start_dev_no_timing was accessed inside CONFIG_PM_RUNTIME macro but defined outside it. When the above macro was not defined the compiler gave the following warning: drivers/base/power/domain.c:96:12: warning: ‘genpd_start_dev_no_timing’ defined but not used [-Wunused-function] Signed-off-by: Sachin Kamat Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 12ad070c244f..c22b869245d9 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -93,12 +93,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev) start_latency_ns, "start"); } -static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd, - struct device *dev) -{ - return GENPD_DEV_CALLBACK(genpd, int, start, dev); -} - static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) { bool ret = false; @@ -296,6 +290,12 @@ int pm_genpd_name_poweron(const char *domain_name) #ifdef CONFIG_PM_RUNTIME +static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd, + struct device *dev) +{ + return GENPD_DEV_CALLBACK(genpd, int, start, dev); +} + static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) { return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev, -- cgit v1.2.3