diff options
Diffstat (limited to 'drivers/base/power/domain.c')
| -rw-r--r-- | drivers/base/power/domain.c | 70 | 
1 files changed, 49 insertions, 21 deletions
| diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 45937f88e77c..2327613d4539 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -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); @@ -173,8 +202,8 @@ static int genpd_power_on(struct generic_pm_domain *genpd)  	genpd->power_on_latency_ns = elapsed_ns;  	genpd->max_off_time_changed = true;  	genpd_recalc_cpu_exit_latency(genpd); -	pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", -		genpd->name, "on", elapsed_ns); +	pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", +		 genpd->name, "on", elapsed_ns);  	return ret;  } @@ -199,8 +228,8 @@ static int genpd_power_off(struct generic_pm_domain *genpd)  	genpd->power_off_latency_ns = elapsed_ns;  	genpd->max_off_time_changed = true; -	pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", -		genpd->name, "off", elapsed_ns); +	pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", +		 genpd->name, "off", elapsed_ns);  	return ret;  } @@ -1513,9 +1542,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,  	dev_dbg(dev, "%s()\n", __func__); -	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev) -	    ||  IS_ERR_OR_NULL(dev->pm_domain) -	    ||  pd_to_genpd(dev->pm_domain) != genpd) +	if (!genpd || genpd != pm_genpd_lookup_dev(dev))  		return -EINVAL;  	/* The above validation also means we have existing domain_data. */ @@ -2093,21 +2120,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; @@ -2130,6 +2146,17 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)  	genpd_queue_power_off_work(pd);  } +static void genpd_dev_pm_sync(struct device *dev) +{ +	struct generic_pm_domain *pd; + +	pd = dev_to_genpd(dev); +	if (IS_ERR(pd)) +		return; + +	genpd_queue_power_off_work(pd); +} +  /**   * genpd_dev_pm_attach - Attach a device to its PM domain using DT.   * @dev: Device to attach. @@ -2196,6 +2223,7 @@ int genpd_dev_pm_attach(struct device *dev)  	}  	dev->pm_domain->detach = genpd_dev_pm_detach; +	dev->pm_domain->sync = genpd_dev_pm_sync;  	pm_genpd_poweron(pd);  	return 0; |