aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/cpuidle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle/cpuidle.c')
-rw-r--r--drivers/cpuidle/cpuidle.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 386888f10df0..bf5092455a8f 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -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,8 +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 trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
111} 117}
112 118
113/** 119/**
@@ -155,6 +161,45 @@ void cpuidle_resume_and_unlock(void)
155 161
156EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); 162EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
157 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
158/** 203/**
159 * cpuidle_enable_device - enables idle PM for a CPU 204 * cpuidle_enable_device - enables idle PM for a CPU
160 * @dev: the CPU 205 * @dev: the CPU
@@ -179,6 +224,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
179 return ret; 224 return ret;
180 } 225 }
181 226
227 poll_idle_init(dev);
228
182 if ((ret = cpuidle_add_state_sysfs(dev))) 229 if ((ret = cpuidle_add_state_sysfs(dev)))
183 return ret; 230 return ret;
184 231
@@ -233,45 +280,6 @@ void cpuidle_disable_device(struct cpuidle_device *dev)
233 280
234EXPORT_SYMBOL_GPL(cpuidle_disable_device); 281EXPORT_SYMBOL_GPL(cpuidle_disable_device);
235 282
236#ifdef CONFIG_ARCH_HAS_CPU_RELAX
237static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
238{
239 ktime_t t1, t2;
240 s64 diff;
241 int ret;
242
243 t1 = ktime_get();
244 local_irq_enable();
245 while (!need_resched())
246 cpu_relax();
247
248 t2 = ktime_get();
249 diff = ktime_to_us(ktime_sub(t2, t1));
250 if (diff > INT_MAX)
251 diff = INT_MAX;
252
253 ret = (int) diff;
254 return ret;
255}
256
257static void poll_idle_init(struct cpuidle_device *dev)
258{
259 struct cpuidle_state *state = &dev->states[0];
260
261 cpuidle_set_statedata(state, NULL);
262
263 snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
264 snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE");
265 state->exit_latency = 0;
266 state->target_residency = 0;
267 state->power_usage = -1;
268 state->flags = CPUIDLE_FLAG_POLL;
269 state->enter = poll_idle;
270}
271#else
272static void poll_idle_init(struct cpuidle_device *dev) {}
273#endif /* CONFIG_ARCH_HAS_CPU_RELAX */
274
275/** 283/**
276 * __cpuidle_register_device - internal register function called before register 284 * __cpuidle_register_device - internal register function called before register
277 * and enable routines 285 * and enable routines
@@ -292,8 +300,6 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
292 300
293 init_completion(&dev->kobj_unregister); 301 init_completion(&dev->kobj_unregister);
294 302
295 poll_idle_init(dev);
296
297 /* 303 /*
298 * cpuidle driver should set the dev->power_specified bit 304 * cpuidle driver should set the dev->power_specified bit
299 * before registering the device if the driver provides 305 * before registering the device if the driver provides