diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/cpuidle | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 93 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 4 | ||||
-rw-r--r-- | drivers/cpuidle/sysfs.c | 2 |
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 | */ |
50 | static void cpuidle_idle_call(void) | 50 | static 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 | ||
155 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); | 162 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); |
156 | 163 | ||
164 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX | ||
165 | static 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 | |||
185 | static 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 | ||
200 | static 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 | ||
233 | EXPORT_SYMBOL_GPL(cpuidle_disable_device); | 281 | EXPORT_SYMBOL_GPL(cpuidle_disable_device); |
234 | 282 | ||
235 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX | ||
236 | static 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 | |||
256 | static 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 | ||
271 | static 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 | ||
303 | static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i) | 303 | static 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); |