PM / domains: factor out code to get the generic PM domain from a struct device
authorRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 20 Mar 2015 17:20:33 +0000 (17:20 +0000)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 22 Mar 2015 21:19:12 +0000 (22:19 +0100)
The PM domain code contains two methods to get the generic PM domain
for a struct device.  One is dev_to_genpd() which is only safe when
we know for certain that the device has a generic PM domain attached.
The other is coded into genpd_dev_pm_detach() which ensures that the
PM domain in the struct device is a generic PM domain (and so is safer).

This commit factors out the safer version, documents it, and hides the
unsafe dev_to_genpd().

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/base/power/domain.c
include/linux/pm_domain.h

index 2e2e6af..da25c06 100644 (file)
@@ -68,7 +68,36 @@ static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
        return genpd;
 }
 
-struct generic_pm_domain *dev_to_genpd(struct device *dev)
+/*
+ * Get the generic PM domain for a particular struct device.
+ * This validates the struct device pointer, the PM domain pointer,
+ * and checks that the PM domain pointer is a real generic PM domain.
+ * Any failure results in NULL being returned.
+ */
+struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
+{
+       struct generic_pm_domain *genpd = NULL, *gpd;
+
+       if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain))
+               return NULL;
+
+       mutex_lock(&gpd_list_lock);
+       list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+               if (&gpd->domain == dev->pm_domain) {
+                       genpd = gpd;
+                       break;
+               }
+       }
+       mutex_unlock(&gpd_list_lock);
+
+       return genpd;
+}
+
+/*
+ * This should only be used where we are certain that the pm_domain
+ * attached to the device is a genpd domain.
+ */
+static struct generic_pm_domain *dev_to_genpd(struct device *dev)
 {
        if (IS_ERR_OR_NULL(dev->pm_domain))
                return ERR_PTR(-EINVAL);
@@ -2093,21 +2122,10 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
  */
 static void genpd_dev_pm_detach(struct device *dev, bool power_off)
 {
-       struct generic_pm_domain *pd = NULL, *gpd;
+       struct generic_pm_domain *pd;
        int ret = 0;
 
-       if (!dev->pm_domain)
-               return;
-
-       mutex_lock(&gpd_list_lock);
-       list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
-               if (&gpd->domain == dev->pm_domain) {
-                       pd = gpd;
-                       break;
-               }
-       }
-       mutex_unlock(&gpd_list_lock);
-
+       pd = pm_genpd_lookup_dev(dev);
        if (!pd)
                return;
 
index 080e778..681ccb0 100644 (file)
@@ -127,7 +127,7 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
        return to_gpd_data(dev->power.subsys_data->domain_data);
 }
 
-extern struct generic_pm_domain *dev_to_genpd(struct device *dev);
+extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
 extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
                                 struct device *dev,
                                 struct gpd_timing_data *td);
@@ -163,9 +163,9 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
 {
        return ERR_PTR(-ENOSYS);
 }
-static inline struct generic_pm_domain *dev_to_genpd(struct device *dev)
+static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
 {
-       return ERR_PTR(-ENOSYS);
+       return NULL;
 }
 static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
                                        struct device *dev,