forked from Minki/linux
fc850f39ea
If the state_count is not initialized for the device use the driver's state count as the default. That will prevent to add it manually in the cpuidle driver initialization routine and will save us from duplicate line of code. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Len Brown <len.brown@intel.com>
97 lines
2.2 KiB
C
97 lines
2.2 KiB
C
/*
|
|
* driver.c - driver support
|
|
*
|
|
* (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
|
|
* Shaohua Li <shaohua.li@intel.com>
|
|
* Adam Belay <abelay@novell.com>
|
|
*
|
|
* This code is licenced under the GPL.
|
|
*/
|
|
|
|
#include <linux/mutex.h>
|
|
#include <linux/module.h>
|
|
#include <linux/cpuidle.h>
|
|
|
|
#include "cpuidle.h"
|
|
|
|
static struct cpuidle_driver *cpuidle_curr_driver;
|
|
DEFINE_SPINLOCK(cpuidle_driver_lock);
|
|
|
|
static void __cpuidle_register_driver(struct cpuidle_driver *drv)
|
|
{
|
|
int i;
|
|
/*
|
|
* cpuidle driver should set the drv->power_specified bit
|
|
* before registering if the driver provides
|
|
* power_usage numbers.
|
|
*
|
|
* If power_specified is not set,
|
|
* we fill in power_usage with decreasing values as the
|
|
* cpuidle code has an implicit assumption that state Cn
|
|
* uses less power than C(n-1).
|
|
*
|
|
* With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
|
|
* an power value of -1. So we use -2, -3, etc, for other
|
|
* c-states.
|
|
*/
|
|
if (!drv->power_specified) {
|
|
for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
|
|
drv->states[i].power_usage = -1 - i;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* cpuidle_register_driver - registers a driver
|
|
* @drv: the driver
|
|
*/
|
|
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);
|
|
return -EBUSY;
|
|
}
|
|
__cpuidle_register_driver(drv);
|
|
cpuidle_curr_driver = drv;
|
|
spin_unlock(&cpuidle_driver_lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(cpuidle_register_driver);
|
|
|
|
/**
|
|
* cpuidle_get_driver - return the current driver
|
|
*/
|
|
struct cpuidle_driver *cpuidle_get_driver(void)
|
|
{
|
|
return cpuidle_curr_driver;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpuidle_get_driver);
|
|
|
|
/**
|
|
* cpuidle_unregister_driver - unregisters a driver
|
|
* @drv: the driver
|
|
*/
|
|
void cpuidle_unregister_driver(struct cpuidle_driver *drv)
|
|
{
|
|
if (drv != cpuidle_curr_driver) {
|
|
WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
|
|
drv->name);
|
|
return;
|
|
}
|
|
|
|
spin_lock(&cpuidle_driver_lock);
|
|
cpuidle_curr_driver = NULL;
|
|
spin_unlock(&cpuidle_driver_lock);
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
|