diff options
author | Deepthi Dharwar <deepthi@linux.vnet.ibm.com> | 2011-10-28 06:50:42 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-11-06 21:13:58 -0500 |
commit | 46bcfad7a819bd17ac4e831b04405152d59784ab (patch) | |
tree | 20041e788154d103edff2699f88d4a30320e3ee2 /drivers/cpuidle/driver.c | |
parent | 4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (diff) |
cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy)
instead of per-cpu. The statistics needed on per-cpu basis
by the governor are kept per-cpu. This simplifies the cpuidle
subsystem as state registration is done by single cpu only.
Having single copy of cpuidle_states saves memory. Rare case
of asymmetric C-states can be handled within the cpuidle driver
and architectures such as POWER do not have asymmetric C-states.
Having single/global registration of all the idle states,
dynamic C-state transitions on x86 are handled by
the boot cpu. Here, the boot cpu would disable all the devices,
re-populate the states and later enable all the devices,
irrespective of the cpu that would receive the notification first.
Reference:
https://lkml.org/lkml/2011/4/25/83
Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com>
Tested-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Acked-by: Arjan van de Ven <arjan@linux.intel.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/cpuidle/driver.c')
-rw-r--r-- | drivers/cpuidle/driver.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 3f7e3cedd133..284d7af5a9c8 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -17,6 +17,30 @@ | |||
17 | static struct cpuidle_driver *cpuidle_curr_driver; | 17 | static struct cpuidle_driver *cpuidle_curr_driver; |
18 | DEFINE_SPINLOCK(cpuidle_driver_lock); | 18 | DEFINE_SPINLOCK(cpuidle_driver_lock); |
19 | 19 | ||
20 | static void __cpuidle_register_driver(struct cpuidle_driver *drv) | ||
21 | { | ||
22 | int i; | ||
23 | /* | ||
24 | * cpuidle driver should set the drv->power_specified bit | ||
25 | * before registering if the driver provides | ||
26 | * power_usage numbers. | ||
27 | * | ||
28 | * If power_specified is not set, | ||
29 | * we fill in power_usage with decreasing values as the | ||
30 | * cpuidle code has an implicit assumption that state Cn | ||
31 | * uses less power than C(n-1). | ||
32 | * | ||
33 | * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned | ||
34 | * an power value of -1. So we use -2, -3, etc, for other | ||
35 | * c-states. | ||
36 | */ | ||
37 | if (!drv->power_specified) { | ||
38 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) | ||
39 | drv->states[i].power_usage = -1 - i; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | |||
20 | /** | 44 | /** |
21 | * cpuidle_register_driver - registers a driver | 45 | * cpuidle_register_driver - registers a driver |
22 | * @drv: the driver | 46 | * @drv: the driver |
@@ -34,6 +58,7 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) | |||
34 | spin_unlock(&cpuidle_driver_lock); | 58 | spin_unlock(&cpuidle_driver_lock); |
35 | return -EBUSY; | 59 | return -EBUSY; |
36 | } | 60 | } |
61 | __cpuidle_register_driver(drv); | ||
37 | cpuidle_curr_driver = drv; | 62 | cpuidle_curr_driver = drv; |
38 | spin_unlock(&cpuidle_driver_lock); | 63 | spin_unlock(&cpuidle_driver_lock); |
39 | 64 | ||