Skip to content

Commit

Permalink
cpuidle: prepare the cpuidle core to handle multiple drivers
Browse files Browse the repository at this point in the history
This patch is a preparation for the multiple cpuidle drivers support.

As the next patch will introduce the multiple drivers with the Kconfig
option and we want to keep the code clean and understandable, this patch
defines a set of functions for encapsulating some common parts and splits
what should be done under a lock from the rest.

[rjw: Modified the subject and changelog slightly.]
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Daniel Lezcano authored and Rafael J. Wysocki committed Nov 14, 2012
1 parent 4168203 commit 13dd52f
Showing 1 changed file with 42 additions and 18 deletions.
60 changes: 42 additions & 18 deletions drivers/cpuidle/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,59 @@ 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;

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);

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);

Expand Down

0 comments on commit 13dd52f

Please sign in to comment.