aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/cpuidle
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/cpuidle.c93
-rw-r--r--drivers/cpuidle/governors/menu.c4
-rw-r--r--drivers/cpuidle/sysfs.c2
3 files changed, 54 insertions, 45 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index a50710843378..bf5092455a8f 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -49,7 +49,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
49 */ 49 */
50static void cpuidle_idle_call(void) 50static void cpuidle_idle_call(void)
51{ 51{
52 struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices); 52 struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
53 struct cpuidle_state *target_state; 53 struct cpuidle_state *target_state;
54 int next_state; 54 int next_state;
55 55
@@ -96,7 +96,15 @@ static void cpuidle_idle_call(void)
96 96
97 /* enter the state and update stats */ 97 /* enter the state and update stats */
98 dev->last_state = target_state; 98 dev->last_state = target_state;
99
100 trace_power_start(POWER_CSTATE, next_state, dev->cpu);
101 trace_cpu_idle(next_state, dev->cpu);
102
99 dev->last_residency = target_state->enter(dev, target_state); 103 dev->last_residency = target_state->enter(dev, target_state);
104
105 trace_power_end(dev->cpu);
106 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
107
100 if (dev->last_state) 108 if (dev->last_state)
101 target_state = dev->last_state; 109 target_state = dev->last_state;
102 110
@@ -106,7 +114,6 @@ static void cpuidle_idle_call(void)
106 /* give the governor an opportunity to reflect on the outcome */ 114 /* give the governor an opportunity to reflect on the outcome */
107 if (cpuidle_curr_governor->reflect) 115 if (cpuidle_curr_governor->reflect)
108 cpuidle_curr_governor->reflect(dev); 116 cpuidle_curr_governor->reflect(dev);
109 trace_power_end(smp_processor_id());
110} 117}
111 118
112/** 119/**
@@ -154,6 +161,45 @@ void cpuidle_resume_and_unlock(void)
154 161
155EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); 162EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
156 163
164#ifdef CONFIG_ARCH_HAS_CPU_RELAX
165static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
166{
167 ktime_t t1, t2;
168 s64 diff;
169 int ret;
170
171 t1 = ktime_get();
172 local_irq_enable();
173 while (!need_resched())
174 cpu_relax();
175
176 t2 = ktime_get();
177 diff = ktime_to_us(ktime_sub(t2, t1));
178 if (diff > INT_MAX)
179 diff = INT_MAX;
180
181 ret = (int) diff;
182 return ret;
183}
184
185static void poll_idle_init(struct cpuidle_device *dev)
186{
187 struct cpuidle_state *state = &dev->states[0];
188
189 cpuidle_set_statedata(state, NULL);
190
191 snprintf(state->name, CPUIDLE_NAME_LEN, "POLL");
192 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
193 state->exit_latency = 0;
194 state->target_residency = 0;
195 state->power_usage = -1;
196 state->flags = 0;
197 state->enter = poll_idle;
198}
199#else
200static void poll_idle_init(struct cpuidle_device *dev) {}
201#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
202
157/** 203/**
158 * cpuidle_enable_device - enables idle PM for a CPU 204 * cpuidle_enable_device - enables idle PM for a CPU
159 * @dev: the CPU 205 * @dev: the CPU
@@ -178,6 +224,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
178 return ret; 224 return ret;
179 } 225 }
180 226
227 poll_idle_init(dev);
228
181 if ((ret = cpuidle_add_state_sysfs(dev))) 229 if ((ret = cpuidle_add_state_sysfs(dev)))
182 return ret; 230 return ret;
183 231
@@ -232,45 +280,6 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
232 280
233EXPORT_SYMBOL_GPL(cpuidle_disable_device); 281EXPORT_SYMBOL_GPL(cpuidle_disable_device);
234 282
235#ifdef CONFIG_ARCH_HAS_CPU_RELAX
236static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
237{
238 ktime_t t1, t2;
239 s64 diff;
240 int ret;
241
242 t1 = ktime_get();
243 local_irq_enable();
244 while (!need_resched())
245 cpu_relax();
246
247 t2 = ktime_get();
248 diff = ktime_to_us(ktime_sub(t2, t1));
249 if (diff > INT_MAX)
250 diff = INT_MAX;
251
252 ret = (int) diff;
253 return ret;
254}
255
256static void poll_idle_init(struct cpuidle_device *dev)
257{
258 struct cpuidle_state *state = &dev->states[0];
259
260 cpuidle_set_statedata(state, NULL);
261
262 snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
263 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
264 state->exit_latency = 0;
265 state->target_residency = 0;
266 state->power_usage = -1;
267 state->flags = CPUIDLE_FLAG_POLL;
268 state->enter = poll_idle;
269}
270#else
271static void poll_idle_init(struct cpuidle_device *dev) {}
272#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
273
274/** 283/**
275 * __cpuidle_register_device - internal register function called before register 284 * __cpuidle_register_device - internal register function called before register
276 * and enable routines 285 * and enable routines
@@ -291,8 +300,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
291 300
292 init_completion(&dev->kobj_unregister); 301 init_completion(&dev->kobj_unregister);
293 302
294 poll_idle_init(dev);
295
296 /* 303 /*
297 * cpuidle driver should set the dev->power_specified bit 304 * cpuidle driver should set the dev->power_specified bit
298 * before registering the device if the driver provides 305 * before registering the device if the driver provides
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index f508690eb958..c47f3d09c1ee 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -237,6 +237,7 @@ static int menu_select(struct cpuidle_device *dev)
237 unsigned int power_usage = -1; 237 unsigned int power_usage = -1;
238 int i; 238 int i;
239 int multiplier; 239 int multiplier;
240 struct timespec t;
240 241
241 if (data->needs_update) { 242 if (data->needs_update) {
242 menu_update(dev); 243 menu_update(dev);
@@ -251,8 +252,9 @@ static int menu_select(struct cpuidle_device *dev)
251 return 0; 252 return 0;
252 253
253 /* determine the expected residency time, round up */ 254 /* determine the expected residency time, round up */
255 t = ktime_to_timespec(tick_nohz_get_sleep_length());
254 data->expected_us = 256 data->expected_us =
255 DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000); 257 t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
256 258
257 259
258 data->bucket = which_bucket(data->expected_us); 260 data->bucket = which_bucket(data->expected_us);
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 0310ffaec9df..be7917ec40c9 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -300,7 +300,7 @@ static struct kobj_type ktype_state_cpuidle = {
300 .release = cpuidle_state_sysfs_release, 300 .release = cpuidle_state_sysfs_release,
301}; 301};
302 302
303static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i) 303static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
304{ 304{
305 kobject_put(&device->kobjs[i]->kobj); 305 kobject_put(&device->kobjs[i]->kobj);
306 wait_for_completion(&device->kobjs[i]->kobj_unregister); 306 wait_for_completion(&device->kobjs[i]->kobj_unregister);