···5252#include "sigframe.h"53535454void (*ia64_mark_idle)(int);5555-static DEFINE_PER_CPU(unsigned int, cpu_idle_state);56555756unsigned long boot_option_idle_override = 0;5857EXPORT_SYMBOL(boot_option_idle_override);···253254}254255#endif /* CONFIG_HOTPLUG_CPU */255256257257+static void do_nothing(void *unused)258258+{259259+}260260+261261+/*262262+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of263263+ * pm_idle and update to new pm_idle value. Required while changing pm_idle264264+ * handler on SMP systems.265265+ *266266+ * Caller must have changed pm_idle to the new value before the call. Old267267+ * pm_idle value will not be used by any CPU after the return of this function.268268+ */256269void cpu_idle_wait(void)257270{258258- unsigned int cpu, this_cpu = get_cpu();259259- cpumask_t map;260260- cpumask_t tmp = current->cpus_allowed;261261-262262- set_cpus_allowed(current, cpumask_of_cpu(this_cpu));263263- put_cpu();264264-265265- cpus_clear(map);266266- for_each_online_cpu(cpu) {267267- per_cpu(cpu_idle_state, cpu) = 1;268268- cpu_set(cpu, map);269269- }270270-271271- __get_cpu_var(cpu_idle_state) = 0;272272-273273- wmb();274274- do {275275- ssleep(1);276276- for_each_online_cpu(cpu) {277277- if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))278278- cpu_clear(cpu, map);279279- }280280- cpus_and(map, map, cpu_online_map);281281- } while (!cpus_empty(map));282282- set_cpus_allowed(current, tmp);271271+ smp_mb();272272+ /* kick all the CPUs so that they exit out of pm_idle */273273+ smp_call_function(do_nothing, NULL, 0, 1);283274}284275EXPORT_SYMBOL_GPL(cpu_idle_wait);285276···297308#ifdef CONFIG_SMP298309 min_xtp();299310#endif300300- if (__get_cpu_var(cpu_idle_state))301301- __get_cpu_var(cpu_idle_state) = 0;302302-303311 rmb();304312 if (mark_idle)305313 (*mark_idle)(1);