aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>2011-10-28 06:50:42 -0400
committerLen Brown <len.brown@intel.com>2011-11-06 21:13:58 -0500
commit46bcfad7a819bd17ac4e831b04405152d59784ab (patch)
tree20041e788154d103edff2699f88d4a30320e3ee2 /drivers/cpuidle
parent4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (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')
-rw-r--r--drivers/cpuidle/cpuidle.c45
-rw-r--r--drivers/cpuidle/driver.c25
-rw-r--r--drivers/cpuidle/governors/ladder.c28
-rw-r--r--drivers/cpuidle/governors/menu.c20
-rw-r--r--drivers/cpuidle/sysfs.c3
5 files changed, 68 insertions, 53 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 7127e92fa8a1..7a57b11eaa8d 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -61,6 +61,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
61int cpuidle_idle_call(void) 61int cpuidle_idle_call(void)
62{ 62{
63 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); 63 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
64 struct cpuidle_driver *drv = cpuidle_get_driver();
64 struct cpuidle_state *target_state; 65 struct cpuidle_state *target_state;
65 int next_state, entered_state; 66 int next_state, entered_state;
66 67
@@ -84,18 +85,18 @@ int cpuidle_idle_call(void)
84#endif 85#endif
85 86
86 /* ask the governor for the next state */ 87 /* ask the governor for the next state */
87 next_state = cpuidle_curr_governor->select(dev); 88 next_state = cpuidle_curr_governor->select(drv, dev);
88 if (need_resched()) { 89 if (need_resched()) {
89 local_irq_enable(); 90 local_irq_enable();
90 return 0; 91 return 0;
91 } 92 }
92 93
93 target_state = &dev->states[next_state]; 94 target_state = &drv->states[next_state];
94 95
95 trace_power_start(POWER_CSTATE, next_state, dev->cpu); 96 trace_power_start(POWER_CSTATE, next_state, dev->cpu);
96 trace_cpu_idle(next_state, dev->cpu); 97 trace_cpu_idle(next_state, dev->cpu);
97 98
98 entered_state = target_state->enter(dev, next_state); 99 entered_state = target_state->enter(dev, drv, next_state);
99 100
100 trace_power_end(dev->cpu); 101 trace_power_end(dev->cpu);
101 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); 102 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
@@ -163,7 +164,8 @@ void cpuidle_resume_and_unlock(void)
163EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); 164EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
164 165
165#ifdef CONFIG_ARCH_HAS_CPU_RELAX 166#ifdef CONFIG_ARCH_HAS_CPU_RELAX
166static int poll_idle(struct cpuidle_device *dev, int index) 167static int poll_idle(struct cpuidle_device *dev,
168 struct cpuidle_driver *drv, int index)
167{ 169{
168 ktime_t t1, t2; 170 ktime_t t1, t2;
169 s64 diff; 171 s64 diff;
@@ -183,12 +185,9 @@ static int poll_idle(struct cpuidle_device *dev, int index)
183 return index; 185 return index;
184} 186}
185 187
186static void poll_idle_init(struct cpuidle_device *dev) 188static void poll_idle_init(struct cpuidle_driver *drv)
187{ 189{
188 struct cpuidle_state *state = &dev->states[0]; 190 struct cpuidle_state *state = &drv->states[0];
189 struct cpuidle_state_usage *state_usage = &dev->states_usage[0];
190
191 cpuidle_set_statedata(state_usage, NULL);
192 191
193 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); 192 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
194 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); 193 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
@@ -199,7 +198,7 @@ static void poll_idle_init(struct cpuidle_device *dev)
199 state->enter = poll_idle; 198 state->enter = poll_idle;
200} 199}
201#else 200#else
202static void poll_idle_init(struct cpuidle_device *dev) {} 201static void poll_idle_init(struct cpuidle_driver *drv) {}
203#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ 202#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
204 203
205/** 204/**
@@ -226,13 +225,13 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
226 return ret; 225 return ret;
227 } 226 }
228 227
229 poll_idle_init(dev); 228 poll_idle_init(cpuidle_get_driver());
230 229
231 if ((ret = cpuidle_add_state_sysfs(dev))) 230 if ((ret = cpuidle_add_state_sysfs(dev)))
232 return ret; 231 return ret;
233 232
234 if (cpuidle_curr_governor->enable && 233 if (cpuidle_curr_governor->enable &&
235 (ret = cpuidle_curr_governor->enable(dev))) 234 (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
236 goto fail_sysfs; 235 goto fail_sysfs;
237 236
238 for (i = 0; i < dev->state_count; i++) { 237 for (i = 0; i < dev->state_count; i++) {
@@ -273,7 +272,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
273 dev->enabled = 0; 272 dev->enabled = 0;
274 273
275 if (cpuidle_curr_governor->disable) 274 if (cpuidle_curr_governor->disable)
276 cpuidle_curr_governor->disable(dev); 275 cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
277 276
278 cpuidle_remove_state_sysfs(dev); 277 cpuidle_remove_state_sysfs(dev);
279 enabled_devices--; 278 enabled_devices--;
@@ -301,26 +300,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
301 300
302 init_completion(&dev->kobj_unregister); 301 init_completion(&dev->kobj_unregister);
303 302
304 /*
305 * cpuidle driver should set the dev->power_specified bit
306 * before registering the device if the driver provides
307 * power_usage numbers.
308 *
309 * For those devices whose ->power_specified is not set,
310 * we fill in power_usage with decreasing values as the
311 * cpuidle code has an implicit assumption that state Cn
312 * uses less power than C(n-1).
313 *
314 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
315 * an power value of -1. So we use -2, -3, etc, for other
316 * c-states.
317 */
318 if (!dev->power_specified) {
319 int i;
320 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
321 dev->states[i].power_usage = -1 - i;
322 }
323
324 per_cpu(cpuidle_devices, dev->cpu) = dev; 303 per_cpu(cpuidle_devices, dev->cpu) = dev;
325 list_add(&dev->device_list, &cpuidle_detected_devices); 304 list_add(&dev->device_list, &cpuidle_detected_devices);
326 if ((ret = cpuidle_add_sysfs(sys_dev))) { 305 if ((ret = cpuidle_add_sysfs(sys_dev))) {
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 @@
17static struct cpuidle_driver *cpuidle_curr_driver; 17static struct cpuidle_driver *cpuidle_curr_driver;
18DEFINE_SPINLOCK(cpuidle_driver_lock); 18DEFINE_SPINLOCK(cpuidle_driver_lock);
19 19
20static 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
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 6a686a76711f..ef6b9e4727a7 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -60,9 +60,11 @@ static inline void ladder_do_selection(struct ladder_device *ldev,
60 60
61/** 61/**
62 * ladder_select_state - selects the next state to enter 62 * ladder_select_state - selects the next state to enter
63 * @drv: cpuidle driver
63 * @dev: the CPU 64 * @dev: the CPU
64 */ 65 */
65static int ladder_select_state(struct cpuidle_device *dev) 66static int ladder_select_state(struct cpuidle_driver *drv,
67 struct cpuidle_device *dev)
66{ 68{
67 struct ladder_device *ldev = &__get_cpu_var(ladder_devices); 69 struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
68 struct ladder_device_state *last_state; 70 struct ladder_device_state *last_state;
@@ -77,15 +79,17 @@ static int ladder_select_state(struct cpuidle_device *dev)
77 79
78 last_state = &ldev->states[last_idx]; 80 last_state = &ldev->states[last_idx];
79 81
80 if (dev->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) 82 if (drv->states[last_idx].flags & CPUIDLE_FLAG_TIME_VALID) {
81 last_residency = cpuidle_get_last_residency(dev) - dev->states[last_idx].exit_latency; 83 last_residency = cpuidle_get_last_residency(dev) - \
84 drv->states[last_idx].exit_latency;
85 }
82 else 86 else
83 last_residency = last_state->threshold.promotion_time + 1; 87 last_residency = last_state->threshold.promotion_time + 1;
84 88
85 /* consider promotion */ 89 /* consider promotion */
86 if (last_idx < dev->state_count - 1 && 90 if (last_idx < drv->state_count - 1 &&
87 last_residency > last_state->threshold.promotion_time && 91 last_residency > last_state->threshold.promotion_time &&
88 dev->states[last_idx + 1].exit_latency <= latency_req) { 92 drv->states[last_idx + 1].exit_latency <= latency_req) {
89 last_state->stats.promotion_count++; 93 last_state->stats.promotion_count++;
90 last_state->stats.demotion_count = 0; 94 last_state->stats.demotion_count = 0;
91 if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) { 95 if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
@@ -96,11 +100,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
96 100
97 /* consider demotion */ 101 /* consider demotion */
98 if (last_idx > CPUIDLE_DRIVER_STATE_START && 102 if (last_idx > CPUIDLE_DRIVER_STATE_START &&
99 dev->states[last_idx].exit_latency > latency_req) { 103 drv->states[last_idx].exit_latency > latency_req) {
100 int i; 104 int i;
101 105
102 for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { 106 for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
103 if (dev->states[i].exit_latency <= latency_req) 107 if (drv->states[i].exit_latency <= latency_req)
104 break; 108 break;
105 } 109 }
106 ladder_do_selection(ldev, last_idx, i); 110 ladder_do_selection(ldev, last_idx, i);
@@ -123,9 +127,11 @@ static int ladder_select_state(struct cpuidle_device *dev)
123 127
124/** 128/**
125 * ladder_enable_device - setup for the governor 129 * ladder_enable_device - setup for the governor
130 * @drv: cpuidle driver
126 * @dev: the CPU 131 * @dev: the CPU
127 */ 132 */
128static int ladder_enable_device(struct cpuidle_device *dev) 133static int ladder_enable_device(struct cpuidle_driver *drv,
134 struct cpuidle_device *dev)
129{ 135{
130 int i; 136 int i;
131 struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu); 137 struct ladder_device *ldev = &per_cpu(ladder_devices, dev->cpu);
@@ -134,8 +140,8 @@ static int ladder_enable_device(struct cpuidle_device *dev)
134 140
135 ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START; 141 ldev->last_state_idx = CPUIDLE_DRIVER_STATE_START;
136 142
137 for (i = 0; i < dev->state_count; i++) { 143 for (i = 0; i < drv->state_count; i++) {
138 state = &dev->states[i]; 144 state = &drv->states[i];
139 lstate = &ldev->states[i]; 145 lstate = &ldev->states[i];
140 146
141 lstate->stats.promotion_count = 0; 147 lstate->stats.promotion_count = 0;
@@ -144,7 +150,7 @@ static int ladder_enable_device(struct cpuidle_device *dev)
144 lstate->threshold.promotion_count = PROMOTION_COUNT; 150 lstate->threshold.promotion_count = PROMOTION_COUNT;
145 lstate->threshold.demotion_count = DEMOTION_COUNT; 151 lstate->threshold.demotion_count = DEMOTION_COUNT;
146 152
147 if (i < dev->state_count - 1) 153 if (i < drv->state_count - 1)
148 lstate->threshold.promotion_time = state->exit_latency; 154 lstate->threshold.promotion_time = state->exit_latency;
149 if (i > 0) 155 if (i > 0)
150 lstate->threshold.demotion_time = state->exit_latency; 156 lstate->threshold.demotion_time = state->exit_latency;
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index af724e823c8e..bcbe88142135 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -182,7 +182,7 @@ static inline int performance_multiplier(void)
182 182
183static DEFINE_PER_CPU(struct menu_device, menu_devices); 183static DEFINE_PER_CPU(struct menu_device, menu_devices);
184 184
185static void menu_update(struct cpuidle_device *dev); 185static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
186 186
187/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ 187/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */
188static u64 div_round64(u64 dividend, u32 divisor) 188static u64 div_round64(u64 dividend, u32 divisor)
@@ -228,9 +228,10 @@ static void detect_repeating_patterns(struct menu_device *data)
228 228
229/** 229/**
230 * menu_select - selects the next idle state to enter 230 * menu_select - selects the next idle state to enter
231 * @drv: cpuidle driver containing state data
231 * @dev: the CPU 232 * @dev: the CPU
232 */ 233 */
233static int menu_select(struct cpuidle_device *dev) 234static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
234{ 235{
235 struct menu_device *data = &__get_cpu_var(menu_devices); 236 struct menu_device *data = &__get_cpu_var(menu_devices);
236 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); 237 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
@@ -240,7 +241,7 @@ static int menu_select(struct cpuidle_device *dev)
240 struct timespec t; 241 struct timespec t;
241 242
242 if (data->needs_update) { 243 if (data->needs_update) {
243 menu_update(dev); 244 menu_update(drv, dev);
244 data->needs_update = 0; 245 data->needs_update = 0;
245 } 246 }
246 247
@@ -285,8 +286,8 @@ static int menu_select(struct cpuidle_device *dev)
285 * Find the idle state with the lowest power while satisfying 286 * Find the idle state with the lowest power while satisfying
286 * our constraints. 287 * our constraints.
287 */ 288 */
288 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { 289 for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
289 struct cpuidle_state *s = &dev->states[i]; 290 struct cpuidle_state *s = &drv->states[i];
290 291
291 if (s->target_residency > data->predicted_us) 292 if (s->target_residency > data->predicted_us)
292 continue; 293 continue;
@@ -323,14 +324,15 @@ static void menu_reflect(struct cpuidle_device *dev, int index)
323 324
324/** 325/**
325 * menu_update - attempts to guess what happened after entry 326 * menu_update - attempts to guess what happened after entry
327 * @drv: cpuidle driver containing state data
326 * @dev: the CPU 328 * @dev: the CPU
327 */ 329 */
328static void menu_update(struct cpuidle_device *dev) 330static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
329{ 331{
330 struct menu_device *data = &__get_cpu_var(menu_devices); 332 struct menu_device *data = &__get_cpu_var(menu_devices);
331 int last_idx = data->last_state_idx; 333 int last_idx = data->last_state_idx;
332 unsigned int last_idle_us = cpuidle_get_last_residency(dev); 334 unsigned int last_idle_us = cpuidle_get_last_residency(dev);
333 struct cpuidle_state *target = &dev->states[last_idx]; 335 struct cpuidle_state *target = &drv->states[last_idx];
334 unsigned int measured_us; 336 unsigned int measured_us;
335 u64 new_factor; 337 u64 new_factor;
336 338
@@ -384,9 +386,11 @@ static void menu_update(struct cpuidle_device *dev)
384 386
385/** 387/**
386 * menu_enable_device - scans a CPU's states and does setup 388 * menu_enable_device - scans a CPU's states and does setup
389 * @drv: cpuidle driver
387 * @dev: the CPU 390 * @dev: the CPU
388 */ 391 */
389static int menu_enable_device(struct cpuidle_device *dev) 392static int menu_enable_device(struct cpuidle_driver *drv,
393 struct cpuidle_device *dev)
390{ 394{
391 struct menu_device *data = &per_cpu(menu_devices, dev->cpu); 395 struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
392 396
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 8a1ace104476..1e756e160dca 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -322,13 +322,14 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
322{ 322{
323 int i, ret = -ENOMEM; 323 int i, ret = -ENOMEM;
324 struct cpuidle_state_kobj *kobj; 324 struct cpuidle_state_kobj *kobj;
325 struct cpuidle_driver *drv = cpuidle_get_driver();
325 326
326 /* state statistics */ 327 /* state statistics */
327 for (i = 0; i < device->state_count; i++) { 328 for (i = 0; i < device->state_count; i++) {
328 kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); 329 kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
329 if (!kobj) 330 if (!kobj)
330 goto error_state; 331 goto error_state;
331 kobj->state = &device->states[i]; 332 kobj->state = &drv->states[i];
332 kobj->state_usage = &device->states_usage[i]; 333 kobj->state_usage = &device->states_usage[i];
333 init_completion(&kobj->kobj_unregister); 334 init_completion(&kobj->kobj_unregister);
334 335