diff options
| -rw-r--r-- | arch/x86/kernel/apm_32.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 117 | ||||
| -rw-r--r-- | arch/x86/kernel/process_32.c | 118 | ||||
| -rw-r--r-- | arch/x86/kernel/process_64.c | 123 | ||||
| -rw-r--r-- | drivers/acpi/processor_idle.c | 19 | ||||
| -rw-r--r-- | include/asm-x86/processor.h | 1 |
6 files changed, 137 insertions, 244 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index f0030a0999c7..e4ea362e8480 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
| @@ -904,6 +904,7 @@ recalc: | |||
| 904 | original_pm_idle(); | 904 | original_pm_idle(); |
| 905 | else | 905 | else |
| 906 | default_idle(); | 906 | default_idle(); |
| 907 | local_irq_disable(); | ||
| 907 | jiffies_since_last_check = jiffies - last_jiffies; | 908 | jiffies_since_last_check = jiffies - last_jiffies; |
| 908 | if (jiffies_since_last_check > idle_period) | 909 | if (jiffies_since_last_check > idle_period) |
| 909 | goto recalc; | 910 | goto recalc; |
| @@ -911,6 +912,8 @@ recalc: | |||
| 911 | 912 | ||
| 912 | if (apm_idle_done) | 913 | if (apm_idle_done) |
| 913 | apm_do_busy(); | 914 | apm_do_busy(); |
| 915 | |||
| 916 | local_irq_enable(); | ||
| 914 | } | 917 | } |
| 915 | 918 | ||
| 916 | /** | 919 | /** |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 3004d716539d..67e9b4a1e89d 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #include <linux/smp.h> | 4 | #include <linux/smp.h> |
| 5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
| 6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/pm.h> | ||
| 7 | 9 | ||
| 8 | struct kmem_cache *task_xstate_cachep; | 10 | struct kmem_cache *task_xstate_cachep; |
| 9 | 11 | ||
| @@ -42,3 +44,118 @@ void arch_task_cache_init(void) | |||
| 42 | __alignof__(union thread_xstate), | 44 | __alignof__(union thread_xstate), |
| 43 | SLAB_PANIC, NULL); | 45 | SLAB_PANIC, NULL); |
| 44 | } | 46 | } |
| 47 | |||
| 48 | static void do_nothing(void *unused) | ||
| 49 | { | ||
| 50 | } | ||
| 51 | |||
| 52 | /* | ||
| 53 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
| 54 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
| 55 | * handler on SMP systems. | ||
| 56 | * | ||
| 57 | * Caller must have changed pm_idle to the new value before the call. Old | ||
| 58 | * pm_idle value will not be used by any CPU after the return of this function. | ||
| 59 | */ | ||
| 60 | void cpu_idle_wait(void) | ||
| 61 | { | ||
| 62 | smp_mb(); | ||
| 63 | /* kick all the CPUs so that they exit out of pm_idle */ | ||
| 64 | smp_call_function(do_nothing, NULL, 0, 1); | ||
| 65 | } | ||
| 66 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, | ||
| 70 | * which can obviate IPI to trigger checking of need_resched. | ||
| 71 | * We execute MONITOR against need_resched and enter optimized wait state | ||
| 72 | * through MWAIT. Whenever someone changes need_resched, we would be woken | ||
| 73 | * up from MWAIT (without an IPI). | ||
| 74 | * | ||
| 75 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
| 76 | * capability. | ||
| 77 | */ | ||
| 78 | void mwait_idle_with_hints(unsigned long ax, unsigned long cx) | ||
| 79 | { | ||
| 80 | if (!need_resched()) { | ||
| 81 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 82 | smp_mb(); | ||
| 83 | if (!need_resched()) | ||
| 84 | __mwait(ax, cx); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 89 | static void mwait_idle(void) | ||
| 90 | { | ||
| 91 | if (!need_resched()) { | ||
| 92 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 93 | smp_mb(); | ||
| 94 | if (!need_resched()) | ||
| 95 | __sti_mwait(0, 0); | ||
| 96 | else | ||
| 97 | local_irq_enable(); | ||
| 98 | } else | ||
| 99 | local_irq_enable(); | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) | ||
| 104 | { | ||
| 105 | if (force_mwait) | ||
| 106 | return 1; | ||
| 107 | /* Any C1 states supported? */ | ||
| 108 | return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | /* | ||
| 112 | * On SMP it's slightly faster (but much more power-consuming!) | ||
| 113 | * to poll the ->work.need_resched flag instead of waiting for the | ||
| 114 | * cross-CPU IPI to arrive. Use this option with caution. | ||
| 115 | */ | ||
| 116 | static void poll_idle(void) | ||
| 117 | { | ||
| 118 | local_irq_enable(); | ||
| 119 | cpu_relax(); | ||
| 120 | } | ||
| 121 | |||
| 122 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | ||
| 123 | { | ||
| 124 | static int selected; | ||
| 125 | |||
| 126 | if (selected) | ||
| 127 | return; | ||
| 128 | #ifdef CONFIG_X86_SMP | ||
| 129 | if (pm_idle == poll_idle && smp_num_siblings > 1) { | ||
| 130 | printk(KERN_WARNING "WARNING: polling idle and HT enabled," | ||
| 131 | " performance may degrade.\n"); | ||
| 132 | } | ||
| 133 | #endif | ||
| 134 | if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) { | ||
| 135 | /* | ||
| 136 | * Skip, if setup has overridden idle. | ||
| 137 | * One CPU supports mwait => All CPUs supports mwait | ||
| 138 | */ | ||
| 139 | if (!pm_idle) { | ||
| 140 | printk(KERN_INFO "using mwait in idle threads.\n"); | ||
| 141 | pm_idle = mwait_idle; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | selected = 1; | ||
| 145 | } | ||
| 146 | |||
| 147 | static int __init idle_setup(char *str) | ||
| 148 | { | ||
| 149 | if (!strcmp(str, "poll")) { | ||
| 150 | printk("using polling idle threads.\n"); | ||
| 151 | pm_idle = poll_idle; | ||
| 152 | } else if (!strcmp(str, "mwait")) | ||
| 153 | force_mwait = 1; | ||
| 154 | else | ||
| 155 | return -1; | ||
| 156 | |||
| 157 | boot_option_idle_override = 1; | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | early_param("idle", idle_setup); | ||
| 161 | |||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 77de848bd1fb..f8476dfbb60d 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -111,12 +111,10 @@ void default_idle(void) | |||
| 111 | */ | 111 | */ |
| 112 | smp_mb(); | 112 | smp_mb(); |
| 113 | 113 | ||
| 114 | local_irq_disable(); | 114 | if (!need_resched()) |
| 115 | if (!need_resched()) { | ||
| 116 | safe_halt(); /* enables interrupts racelessly */ | 115 | safe_halt(); /* enables interrupts racelessly */ |
| 117 | local_irq_disable(); | 116 | else |
| 118 | } | 117 | local_irq_enable(); |
| 119 | local_irq_enable(); | ||
| 120 | current_thread_info()->status |= TS_POLLING; | 118 | current_thread_info()->status |= TS_POLLING; |
| 121 | } else { | 119 | } else { |
| 122 | local_irq_enable(); | 120 | local_irq_enable(); |
| @@ -128,17 +126,6 @@ void default_idle(void) | |||
| 128 | EXPORT_SYMBOL(default_idle); | 126 | EXPORT_SYMBOL(default_idle); |
| 129 | #endif | 127 | #endif |
| 130 | 128 | ||
| 131 | /* | ||
| 132 | * On SMP it's slightly faster (but much more power-consuming!) | ||
| 133 | * to poll the ->work.need_resched flag instead of waiting for the | ||
| 134 | * cross-CPU IPI to arrive. Use this option with caution. | ||
| 135 | */ | ||
| 136 | static void poll_idle(void) | ||
| 137 | { | ||
| 138 | local_irq_enable(); | ||
| 139 | cpu_relax(); | ||
| 140 | } | ||
| 141 | |||
| 142 | #ifdef CONFIG_HOTPLUG_CPU | 129 | #ifdef CONFIG_HOTPLUG_CPU |
| 143 | #include <asm/nmi.h> | 130 | #include <asm/nmi.h> |
| 144 | /* We don't actually take CPU down, just spin without interrupts. */ | 131 | /* We don't actually take CPU down, just spin without interrupts. */ |
| @@ -196,6 +183,7 @@ void cpu_idle(void) | |||
| 196 | if (cpu_is_offline(cpu)) | 183 | if (cpu_is_offline(cpu)) |
| 197 | play_dead(); | 184 | play_dead(); |
| 198 | 185 | ||
| 186 | local_irq_disable(); | ||
| 199 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; | 187 | __get_cpu_var(irq_stat).idle_timestamp = jiffies; |
| 200 | idle(); | 188 | idle(); |
| 201 | } | 189 | } |
| @@ -206,104 +194,6 @@ void cpu_idle(void) | |||
| 206 | } | 194 | } |
| 207 | } | 195 | } |
| 208 | 196 | ||
| 209 | static void do_nothing(void *unused) | ||
| 210 | { | ||
| 211 | } | ||
| 212 | |||
| 213 | /* | ||
| 214 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
| 215 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
| 216 | * handler on SMP systems. | ||
| 217 | * | ||
| 218 | * Caller must have changed pm_idle to the new value before the call. Old | ||
| 219 | * pm_idle value will not be used by any CPU after the return of this function. | ||
| 220 | */ | ||
| 221 | void cpu_idle_wait(void) | ||
| 222 | { | ||
| 223 | smp_mb(); | ||
| 224 | /* kick all the CPUs so that they exit out of pm_idle */ | ||
| 225 | smp_call_function(do_nothing, NULL, 0, 1); | ||
| 226 | } | ||
| 227 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | ||
| 228 | |||
| 229 | /* | ||
| 230 | * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, | ||
| 231 | * which can obviate IPI to trigger checking of need_resched. | ||
| 232 | * We execute MONITOR against need_resched and enter optimized wait state | ||
| 233 | * through MWAIT. Whenever someone changes need_resched, we would be woken | ||
| 234 | * up from MWAIT (without an IPI). | ||
| 235 | * | ||
| 236 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
| 237 | * capability. | ||
| 238 | */ | ||
| 239 | void mwait_idle_with_hints(unsigned long ax, unsigned long cx) | ||
| 240 | { | ||
| 241 | if (!need_resched()) { | ||
| 242 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 243 | smp_mb(); | ||
| 244 | if (!need_resched()) | ||
| 245 | __sti_mwait(ax, cx); | ||
| 246 | else | ||
| 247 | local_irq_enable(); | ||
| 248 | } else | ||
| 249 | local_irq_enable(); | ||
| 250 | } | ||
| 251 | |||
| 252 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 253 | static void mwait_idle(void) | ||
| 254 | { | ||
| 255 | local_irq_enable(); | ||
| 256 | mwait_idle_with_hints(0, 0); | ||
| 257 | } | ||
| 258 | |||
| 259 | static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) | ||
| 260 | { | ||
| 261 | if (force_mwait) | ||
| 262 | return 1; | ||
| 263 | /* Any C1 states supported? */ | ||
| 264 | return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | ||
| 268 | { | ||
| 269 | static int selected; | ||
| 270 | |||
| 271 | if (selected) | ||
| 272 | return; | ||
| 273 | #ifdef CONFIG_X86_SMP | ||
| 274 | if (pm_idle == poll_idle && smp_num_siblings > 1) { | ||
| 275 | printk(KERN_WARNING "WARNING: polling idle and HT enabled," | ||
| 276 | " performance may degrade.\n"); | ||
| 277 | } | ||
| 278 | #endif | ||
| 279 | if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) { | ||
| 280 | /* | ||
| 281 | * Skip, if setup has overridden idle. | ||
| 282 | * One CPU supports mwait => All CPUs supports mwait | ||
| 283 | */ | ||
| 284 | if (!pm_idle) { | ||
| 285 | printk(KERN_INFO "using mwait in idle threads.\n"); | ||
| 286 | pm_idle = mwait_idle; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | selected = 1; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int __init idle_setup(char *str) | ||
| 293 | { | ||
| 294 | if (!strcmp(str, "poll")) { | ||
| 295 | printk("using polling idle threads.\n"); | ||
| 296 | pm_idle = poll_idle; | ||
| 297 | } else if (!strcmp(str, "mwait")) | ||
| 298 | force_mwait = 1; | ||
| 299 | else | ||
| 300 | return -1; | ||
| 301 | |||
| 302 | boot_option_idle_override = 1; | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | early_param("idle", idle_setup); | ||
| 306 | |||
| 307 | void __show_registers(struct pt_regs *regs, int all) | 197 | void __show_registers(struct pt_regs *regs, int all) |
| 308 | { | 198 | { |
| 309 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; | 199 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 131c2ee7ac56..e2319f39988b 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -106,26 +106,13 @@ void default_idle(void) | |||
| 106 | * test NEED_RESCHED: | 106 | * test NEED_RESCHED: |
| 107 | */ | 107 | */ |
| 108 | smp_mb(); | 108 | smp_mb(); |
| 109 | local_irq_disable(); | 109 | if (!need_resched()) |
| 110 | if (!need_resched()) { | ||
| 111 | safe_halt(); /* enables interrupts racelessly */ | 110 | safe_halt(); /* enables interrupts racelessly */ |
| 112 | local_irq_disable(); | 111 | else |
| 113 | } | 112 | local_irq_enable(); |
| 114 | local_irq_enable(); | ||
| 115 | current_thread_info()->status |= TS_POLLING; | 113 | current_thread_info()->status |= TS_POLLING; |
| 116 | } | 114 | } |
| 117 | 115 | ||
| 118 | /* | ||
| 119 | * On SMP it's slightly faster (but much more power-consuming!) | ||
| 120 | * to poll the ->need_resched flag instead of waiting for the | ||
| 121 | * cross-CPU IPI to arrive. Use this option with caution. | ||
| 122 | */ | ||
| 123 | static void poll_idle(void) | ||
| 124 | { | ||
| 125 | local_irq_enable(); | ||
| 126 | cpu_relax(); | ||
| 127 | } | ||
| 128 | |||
| 129 | #ifdef CONFIG_HOTPLUG_CPU | 116 | #ifdef CONFIG_HOTPLUG_CPU |
| 130 | DECLARE_PER_CPU(int, cpu_state); | 117 | DECLARE_PER_CPU(int, cpu_state); |
| 131 | 118 | ||
| @@ -192,110 +179,6 @@ void cpu_idle(void) | |||
| 192 | } | 179 | } |
| 193 | } | 180 | } |
| 194 | 181 | ||
| 195 | static void do_nothing(void *unused) | ||
| 196 | { | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | ||
| 201 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | ||
| 202 | * handler on SMP systems. | ||
| 203 | * | ||
| 204 | * Caller must have changed pm_idle to the new value before the call. Old | ||
| 205 | * pm_idle value will not be used by any CPU after the return of this function. | ||
| 206 | */ | ||
| 207 | void cpu_idle_wait(void) | ||
| 208 | { | ||
| 209 | smp_mb(); | ||
| 210 | /* kick all the CPUs so that they exit out of pm_idle */ | ||
| 211 | smp_call_function(do_nothing, NULL, 0, 1); | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | ||
| 214 | |||
| 215 | /* | ||
| 216 | * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, | ||
| 217 | * which can obviate IPI to trigger checking of need_resched. | ||
| 218 | * We execute MONITOR against need_resched and enter optimized wait state | ||
| 219 | * through MWAIT. Whenever someone changes need_resched, we would be woken | ||
| 220 | * up from MWAIT (without an IPI). | ||
| 221 | * | ||
| 222 | * New with Core Duo processors, MWAIT can take some hints based on CPU | ||
| 223 | * capability. | ||
| 224 | */ | ||
| 225 | void mwait_idle_with_hints(unsigned long ax, unsigned long cx) | ||
| 226 | { | ||
| 227 | if (!need_resched()) { | ||
| 228 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 229 | smp_mb(); | ||
| 230 | if (!need_resched()) | ||
| 231 | __mwait(ax, cx); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 236 | static void mwait_idle(void) | ||
| 237 | { | ||
| 238 | if (!need_resched()) { | ||
| 239 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 240 | smp_mb(); | ||
| 241 | if (!need_resched()) | ||
| 242 | __sti_mwait(0, 0); | ||
| 243 | else | ||
| 244 | local_irq_enable(); | ||
| 245 | } else { | ||
| 246 | local_irq_enable(); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | static int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) | ||
| 252 | { | ||
| 253 | if (force_mwait) | ||
| 254 | return 1; | ||
| 255 | /* Any C1 states supported? */ | ||
| 256 | return c->cpuid_level >= 5 && ((cpuid_edx(5) >> 4) & 0xf) > 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | ||
| 260 | { | ||
| 261 | static int selected; | ||
| 262 | |||
| 263 | if (selected) | ||
| 264 | return; | ||
| 265 | #ifdef CONFIG_X86_SMP | ||
| 266 | if (pm_idle == poll_idle && smp_num_siblings > 1) { | ||
| 267 | printk(KERN_WARNING "WARNING: polling idle and HT enabled," | ||
| 268 | " performance may degrade.\n"); | ||
| 269 | } | ||
| 270 | #endif | ||
| 271 | if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) { | ||
| 272 | /* | ||
| 273 | * Skip, if setup has overridden idle. | ||
| 274 | * One CPU supports mwait => All CPUs supports mwait | ||
| 275 | */ | ||
| 276 | if (!pm_idle) { | ||
| 277 | printk(KERN_INFO "using mwait in idle threads.\n"); | ||
| 278 | pm_idle = mwait_idle; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | selected = 1; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int __init idle_setup(char *str) | ||
| 285 | { | ||
| 286 | if (!strcmp(str, "poll")) { | ||
| 287 | printk("using polling idle threads.\n"); | ||
| 288 | pm_idle = poll_idle; | ||
| 289 | } else if (!strcmp(str, "mwait")) | ||
| 290 | force_mwait = 1; | ||
| 291 | else | ||
| 292 | return -1; | ||
| 293 | |||
| 294 | boot_option_idle_override = 1; | ||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | early_param("idle", idle_setup); | ||
| 298 | |||
| 299 | /* Prints also some state that isn't saved in the pt_regs */ | 182 | /* Prints also some state that isn't saved in the pt_regs */ |
| 300 | void __show_regs(struct pt_regs * regs) | 183 | void __show_regs(struct pt_regs * regs) |
| 301 | { | 184 | { |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da9781f80..0d90ff5fd117 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -418,13 +418,12 @@ static void acpi_processor_idle(void) | |||
| 418 | 418 | ||
| 419 | cx = pr->power.state; | 419 | cx = pr->power.state; |
| 420 | if (!cx || acpi_idle_suspend) { | 420 | if (!cx || acpi_idle_suspend) { |
| 421 | if (pm_idle_save) | 421 | if (pm_idle_save) { |
| 422 | pm_idle_save(); | 422 | pm_idle_save(); /* enables IRQs */ |
| 423 | else | 423 | } else { |
| 424 | acpi_safe_halt(); | 424 | acpi_safe_halt(); |
| 425 | |||
| 426 | if (irqs_disabled()) | ||
| 427 | local_irq_enable(); | 425 | local_irq_enable(); |
| 426 | } | ||
| 428 | 427 | ||
| 429 | return; | 428 | return; |
| 430 | } | 429 | } |
| @@ -520,10 +519,12 @@ static void acpi_processor_idle(void) | |||
| 520 | * Use the appropriate idle routine, the one that would | 519 | * Use the appropriate idle routine, the one that would |
| 521 | * be used without acpi C-states. | 520 | * be used without acpi C-states. |
| 522 | */ | 521 | */ |
| 523 | if (pm_idle_save) | 522 | if (pm_idle_save) { |
| 524 | pm_idle_save(); | 523 | pm_idle_save(); /* enables IRQs */ |
| 525 | else | 524 | } else { |
| 526 | acpi_safe_halt(); | 525 | acpi_safe_halt(); |
| 526 | local_irq_enable(); | ||
| 527 | } | ||
| 527 | 528 | ||
| 528 | /* | 529 | /* |
| 529 | * TBD: Can't get time duration while in C1, as resumes | 530 | * TBD: Can't get time duration while in C1, as resumes |
| @@ -534,8 +535,6 @@ static void acpi_processor_idle(void) | |||
| 534 | * skew otherwise. | 535 | * skew otherwise. |
| 535 | */ | 536 | */ |
| 536 | sleep_ticks = 0xFFFFFFFF; | 537 | sleep_ticks = 0xFFFFFFFF; |
| 537 | if (irqs_disabled()) | ||
| 538 | local_irq_enable(); | ||
| 539 | 538 | ||
| 540 | break; | 539 | break; |
| 541 | 540 | ||
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 117343b0c271..2e7974ec77ec 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h | |||
| @@ -722,6 +722,7 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) | |||
| 722 | 722 | ||
| 723 | static inline void __sti_mwait(unsigned long eax, unsigned long ecx) | 723 | static inline void __sti_mwait(unsigned long eax, unsigned long ecx) |
| 724 | { | 724 | { |
| 725 | trace_hardirqs_on(); | ||
| 725 | /* "mwait %eax, %ecx;" */ | 726 | /* "mwait %eax, %ecx;" */ |
| 726 | asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" | 727 | asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" |
| 727 | :: "a" (eax), "c" (ecx)); | 728 | :: "a" (eax), "c" (ecx)); |
