forked from luck/tmp_suning_uos_patched
Revert "[PATCH] i386: add idle notifier"
This reverts commit 2ff2d3d747
.
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: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
9654640d0a
commit
ea3d5226f5
@ -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)
|
|||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
#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
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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)
|
|||||||
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 @@
|
|||||||
#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);
|
|||||||
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);
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
__monitor((void *)¤t_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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
/*
|
/*
|
||||||
* 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();
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#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)
|
|||||||
: :"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
|
||||||
|
Loading…
Reference in New Issue
Block a user