diff options
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r-- | arch/x86/kernel/process_32.c | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index be3c7a299f02..43930e73f657 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -82,7 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
82 | */ | 82 | */ |
83 | void (*pm_idle)(void); | 83 | void (*pm_idle)(void); |
84 | EXPORT_SYMBOL(pm_idle); | 84 | EXPORT_SYMBOL(pm_idle); |
85 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); | ||
86 | 85 | ||
87 | void disable_hlt(void) | 86 | void disable_hlt(void) |
88 | { | 87 | { |
@@ -190,9 +189,6 @@ void cpu_idle(void) | |||
190 | while (!need_resched()) { | 189 | while (!need_resched()) { |
191 | void (*idle)(void); | 190 | void (*idle)(void); |
192 | 191 | ||
193 | if (__get_cpu_var(cpu_idle_state)) | ||
194 | __get_cpu_var(cpu_idle_state) = 0; | ||
195 | |||
196 | check_pgt_cache(); | 192 | check_pgt_cache(); |
197 | rmb(); | 193 | rmb(); |
198 | idle = pm_idle; | 194 | idle = pm_idle; |
@@ -220,40 +216,19 @@ static void do_nothing(void *unused) | |||
220 | { | 216 | { |
221 | } | 217 | } |
222 | 218 | ||
219 | /* | ||
220 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
221 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
222 | * handler on SMP systems. | ||
223 | * | ||
224 | * Caller must have changed pm_idle to the new value before the call. Old | ||
225 | * pm_idle value will not be used by any CPU after the return of this function. | ||
226 | */ | ||
223 | void cpu_idle_wait(void) | 227 | void cpu_idle_wait(void) |
224 | { | 228 | { |
225 | unsigned int cpu, this_cpu = get_cpu(); | 229 | smp_mb(); |
226 | cpumask_t map, tmp = current->cpus_allowed; | 230 | /* kick all the CPUs so that they exit out of pm_idle */ |
227 | 231 | smp_call_function(do_nothing, NULL, 0, 1); | |
228 | set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); | ||
229 | put_cpu(); | ||
230 | |||
231 | cpus_clear(map); | ||
232 | for_each_online_cpu(cpu) { | ||
233 | per_cpu(cpu_idle_state, cpu) = 1; | ||
234 | cpu_set(cpu, map); | ||
235 | } | ||
236 | |||
237 | __get_cpu_var(cpu_idle_state) = 0; | ||
238 | |||
239 | wmb(); | ||
240 | do { | ||
241 | ssleep(1); | ||
242 | for_each_online_cpu(cpu) { | ||
243 | if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu)) | ||
244 | cpu_clear(cpu, map); | ||
245 | } | ||
246 | cpus_and(map, map, cpu_online_map); | ||
247 | /* | ||
248 | * We waited 1 sec, if a CPU still did not call idle | ||
249 | * it may be because it is in idle and not waking up | ||
250 | * because it has nothing to do. | ||
251 | * Give all the remaining CPUS a kick. | ||
252 | */ | ||
253 | smp_call_function_mask(map, do_nothing, NULL, 0); | ||
254 | } while (!cpus_empty(map)); | ||
255 | |||
256 | set_cpus_allowed(current, tmp); | ||
257 | } | 232 | } |
258 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | 233 | EXPORT_SYMBOL_GPL(cpu_idle_wait); |
259 | 234 | ||