提交 ea3d5226 编写于 作者: L Linus Torvalds

Revert "[PATCH] i386: add idle notifier"

This reverts commit 2ff2d3d7.

Uwe Bugla reports that he cannot mount a floppy drive any more, and Jiri
Slaby bisected it down to this commit.

Benjamin LaHaise also points out that this is a big hot-path, and that
interrupt delivery while idle is very common and should not go through
all these expensive gyrations.

Fix up conflicts in arch/i386/kernel/apic.c and arch/i386/kernel/irq.c
due to other unrelated irq changes.

Cc: Stephane Eranian <eranian@hpl.hp.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Andrew Morton <akpm@osdl.org>
Cc: Uwe Bugla <uwe.bugla@gmx.de>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 9654640d
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <asm/hpet.h> #include <asm/hpet.h>
#include <asm/i8253.h> #include <asm/i8253.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/idle.h>
#include <mach_apic.h> #include <mach_apic.h>
#include <mach_apicdef.h> #include <mach_apicdef.h>
...@@ -561,7 +560,6 @@ void fastcall smp_apic_timer_interrupt(struct pt_regs *regs) ...@@ -561,7 +560,6 @@ void fastcall smp_apic_timer_interrupt(struct pt_regs *regs)
* Besides, if we don't timer interrupts ignore the global * Besides, if we don't timer interrupts ignore the global
* interrupt lock, which is the WrongThing (tm) to do. * interrupt lock, which is the WrongThing (tm) to do.
*/ */
exit_idle();
irq_enter(); irq_enter();
local_apic_timer_interrupt(); local_apic_timer_interrupt();
irq_exit(); irq_exit();
...@@ -1221,7 +1219,6 @@ void smp_spurious_interrupt(struct pt_regs *regs) ...@@ -1221,7 +1219,6 @@ void smp_spurious_interrupt(struct pt_regs *regs)
{ {
unsigned long v; unsigned long v;
exit_idle();
irq_enter(); irq_enter();
/* /*
* Check if this really is a spurious interrupt and ACK it * Check if this really is a spurious interrupt and ACK it
...@@ -1245,7 +1242,6 @@ void smp_error_interrupt(struct pt_regs *regs) ...@@ -1245,7 +1242,6 @@ void smp_error_interrupt(struct pt_regs *regs)
{ {
unsigned long v, v1; unsigned long v, v1;
exit_idle();
irq_enter(); irq_enter();
/* First tickle the hardware, only then report what went on. -- REW */ /* First tickle the hardware, only then report what went on. -- REW */
v = apic_read(APIC_ESR); v = apic_read(APIC_ESR);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/idle.h>
#include <asm/therm_throt.h> #include <asm/therm_throt.h>
...@@ -60,7 +59,6 @@ static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_therm ...@@ -60,7 +59,6 @@ static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_therm
fastcall void smp_thermal_interrupt(struct pt_regs *regs) fastcall void smp_thermal_interrupt(struct pt_regs *regs)
{ {
exit_idle();
irq_enter(); irq_enter();
vendor_thermal_interrupt(regs); vendor_thermal_interrupt(regs);
irq_exit(); irq_exit();
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/idle.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -77,7 +75,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs) ...@@ -77,7 +75,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
union irq_ctx *curctx, *irqctx; union irq_ctx *curctx, *irqctx;
u32 *isp; u32 *isp;
#endif #endif
exit_idle();
if (unlikely((unsigned)irq >= NR_IRQS)) { if (unlikely((unsigned)irq >= NR_IRQS)) {
printk(KERN_EMERG "%s: cannot handle IRQ %d\n", printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/vm86.h> #include <asm/vm86.h>
#include <asm/idle.h>
#ifdef CONFIG_MATH_EMULATION #ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h> #include <asm/math_emu.h>
#endif #endif
...@@ -82,42 +81,6 @@ void (*pm_idle)(void); ...@@ -82,42 +81,6 @@ void (*pm_idle)(void);
EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_idle);
static DEFINE_PER_CPU(unsigned int, cpu_idle_state); static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
static ATOMIC_NOTIFIER_HEAD(idle_notifier);
void idle_notifier_register(struct notifier_block *n)
{
atomic_notifier_chain_register(&idle_notifier, n);
}
void idle_notifier_unregister(struct notifier_block *n)
{
atomic_notifier_chain_unregister(&idle_notifier, n);
}
static DEFINE_PER_CPU(volatile unsigned long, idle_state);
void enter_idle(void)
{
/* needs to be atomic w.r.t. interrupts, not against other CPUs */
__set_bit(0, &__get_cpu_var(idle_state));
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
static void __exit_idle(void)
{
/* needs to be atomic w.r.t. interrupts, not against other CPUs */
if (__test_and_clear_bit(0, &__get_cpu_var(idle_state)) == 0)
return;
atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
}
void exit_idle(void)
{
if (current->pid)
return;
__exit_idle();
}
void disable_hlt(void) void disable_hlt(void)
{ {
hlt_counter++; hlt_counter++;
...@@ -168,7 +131,6 @@ EXPORT_SYMBOL(default_idle); ...@@ -168,7 +131,6 @@ EXPORT_SYMBOL(default_idle);
*/ */
static void poll_idle (void) static void poll_idle (void)
{ {
local_irq_enable();
cpu_relax(); cpu_relax();
} }
...@@ -229,16 +191,7 @@ void cpu_idle(void) ...@@ -229,16 +191,7 @@ void cpu_idle(void)
play_dead(); play_dead();
__get_cpu_var(irq_stat).idle_timestamp = jiffies; __get_cpu_var(irq_stat).idle_timestamp = jiffies;
/*
* Idle routines should keep interrupts disabled
* from here on, until they go to idle.
* Otherwise, idle callbacks can misfire.
*/
local_irq_disable();
enter_idle();
idle(); idle();
__exit_idle();
} }
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
preempt_enable_no_resched(); preempt_enable_no_resched();
...@@ -293,11 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) ...@@ -293,11 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
__monitor((void *)&current_thread_info()->flags, 0, 0); __monitor((void *)&current_thread_info()->flags, 0, 0);
smp_mb(); smp_mb();
if (!need_resched()) if (!need_resched())
__sti_mwait(eax, ecx); __mwait(eax, ecx);
else
local_irq_enable();
} else {
local_irq_enable();
} }
} }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <asm/mtrr.h> #include <asm/mtrr.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/idle.h>
#include <mach_apic.h> #include <mach_apic.h>
/* /*
...@@ -624,7 +623,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs) ...@@ -624,7 +623,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs)
/* /*
* At this point the info structure may be out of scope unless wait==1 * At this point the info structure may be out of scope unless wait==1
*/ */
exit_idle();
irq_enter(); irq_enter();
(*func)(info); (*func)(info);
irq_exit(); irq_exit();
......
#ifndef _ASM_I386_IDLE_H
#define _ASM_I386_IDLE_H 1
#define IDLE_START 1
#define IDLE_END 2
struct notifier_block;
void idle_notifier_register(struct notifier_block *n);
void idle_notifier_unregister(struct notifier_block *n);
void exit_idle(void);
void enter_idle(void);
#endif
...@@ -257,14 +257,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) ...@@ -257,14 +257,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
: :"a" (eax), "c" (ecx)); : :"a" (eax), "c" (ecx));
} }
static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
{
/* "mwait %eax,%ecx;" */
asm volatile(
"sti; .byte 0x0f,0x01,0xc9;"
: :"a" (eax), "c" (ecx));
}
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
/* from system description table in BIOS. Mostly for MCA use, but /* from system description table in BIOS. Mostly for MCA use, but
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册