diff options
Diffstat (limited to 'drivers/cpuidle/driver.c')
| -rw-r--r-- | drivers/cpuidle/driver.c | 60 | 
1 files changed, 42 insertions, 18 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 3e590756923..8246662f594 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -39,11 +39,20 @@ static void set_power_states(struct cpuidle_driver *drv)  		drv->states[i].power_usage = -1 - i;  } -/** - * cpuidle_register_driver - registers a driver - * @drv: the driver - */ -int cpuidle_register_driver(struct cpuidle_driver *drv) +static void __cpuidle_driver_init(struct cpuidle_driver *drv) +{ +	drv->refcnt = 0; + +	if (!drv->power_specified) +		set_power_states(drv); +} + +static void cpuidle_set_driver(struct cpuidle_driver *drv) +{ +	cpuidle_curr_driver = drv; +} + +static int __cpuidle_register_driver(struct cpuidle_driver *drv)  {  	if (!drv || !drv->state_count)  		return -EINVAL; @@ -51,22 +60,38 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)  	if (cpuidle_disabled())  		return -ENODEV; -	spin_lock(&cpuidle_driver_lock); -	if (cpuidle_curr_driver) { -		spin_unlock(&cpuidle_driver_lock); +	if (cpuidle_get_driver())  		return -EBUSY; -	} -	if (!drv->power_specified) -		set_power_states(drv); +	__cpuidle_driver_init(drv); -	drv->refcnt = 0; +	cpuidle_set_driver(drv); -	cpuidle_curr_driver = drv; +	return 0; +} + +static void __cpuidle_unregister_driver(struct cpuidle_driver *drv) +{ +	if (drv != cpuidle_get_driver()) +		return; + +	if (!WARN_ON(drv->refcnt > 0)) +		cpuidle_set_driver(NULL); +} +/** + * cpuidle_register_driver - registers a driver + * @drv: the driver + */ +int cpuidle_register_driver(struct cpuidle_driver *drv) +{ +	int ret; + +	spin_lock(&cpuidle_driver_lock); +	ret = __cpuidle_register_driver(drv);  	spin_unlock(&cpuidle_driver_lock); -	return 0; +	return ret;  }  EXPORT_SYMBOL_GPL(cpuidle_register_driver); @@ -86,8 +111,7 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);  void cpuidle_unregister_driver(struct cpuidle_driver *drv)  {  	spin_lock(&cpuidle_driver_lock); -	if (drv == cpuidle_curr_driver && !WARN_ON(drv->refcnt > 0)) -		cpuidle_curr_driver = NULL; +	__cpuidle_unregister_driver(drv);  	spin_unlock(&cpuidle_driver_lock);  }  EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); @@ -98,7 +122,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)  	spin_lock(&cpuidle_driver_lock); -	drv = cpuidle_curr_driver; +	drv = cpuidle_get_driver();  	drv->refcnt++;  	spin_unlock(&cpuidle_driver_lock); @@ -107,7 +131,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)  void cpuidle_driver_unref(void)  { -	struct cpuidle_driver *drv = cpuidle_curr_driver; +	struct cpuidle_driver *drv = cpuidle_get_driver();  	spin_lock(&cpuidle_driver_lock);  |