summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2002-07-21 02:11:12 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-07-21 02:11:12 -0700
commitae86a80aed1e269d435c70f6e85deb80e8f8be98 (patch)
treec0c5b816da7b3a3102f159c335745ae9b01883c1
parent3d37e1e6171f8cbd81e442524d4dd231b8cbf5d1 (diff)
[PATCH] "big IRQ lock" removal, IRQ cleanups
This is a massive cleanup of the IRQ subsystem. It's losely based on Linus' original idea and DaveM's original implementation, to fold our various irq, softirq and bh counters into the preemption counter. with this approach it was possible: - to remove the 'big IRQ lock' on SMP - on which sti() and cli() relied. - to streamline/simplify arch/i386/kernel/irq.c significantly. - to simplify the softirq code. - to remove the preemption count increase/decrease code from the lowlevel IRQ assembly code. - to speed up schedule() a bit. Global sti() and cli() is gone forever on SMP, there is no more globally synchronizing irq-disabling capability. All code that relied on sti() and cli() and restore_flags() must use other locking mechanisms from now on (spinlocks and __cli()/__sti()). obviously this patch breaks massive amounts of code, so only limited .configs are working at the moment (UP is expected to be unaffected, but SMP will require various driver updates). The patch was developed and tested on SMP systems, and while the code is still a bit rough in places, the base IRQ code appears to be pretty robust and clean. while it boots already so the worst is over, there is lots of work left: eg. to fix the serial layer to not use cli()/sti() and bhs ...
-rw-r--r--arch/i386/kernel/apic.c4
-rw-r--r--arch/i386/kernel/apm.c42
-rw-r--r--arch/i386/kernel/entry.S9
-rw-r--r--arch/i386/kernel/i386_ksyms.c8
-rw-r--r--arch/i386/kernel/io_apic.c2
-rw-r--r--arch/i386/kernel/irq.c277
-rw-r--r--arch/i386/kernel/mca.c26
-rw-r--r--arch/i386/kernel/nmi.c2
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/smpboot.c1
-rw-r--r--arch/i386/kernel/vm86.c19
-rw-r--r--arch/i386/mm/fault.c30
-rw-r--r--drivers/block/genhd.c1
-rw-r--r--drivers/block/ll_rw_blk.c3
-rw-r--r--drivers/char/n_tty.c4
-rw-r--r--drivers/char/tty_io.c13
-rw-r--r--drivers/char/tty_ioctl.c4
-rw-r--r--drivers/char/vt.c6
-rw-r--r--drivers/ide/main.c10
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--include/asm-generic/smplock.h3
-rw-r--r--include/asm-i386/hardirq.h76
-rw-r--r--include/asm-i386/smplock.h14
-rw-r--r--include/asm-i386/softirq.h55
-rw-r--r--include/asm-i386/system.h26
-rw-r--r--include/linux/irq_cpustat.h2
-rw-r--r--include/linux/preempt.h46
-rw-r--r--include/linux/smp_lock.h2
-rw-r--r--include/linux/spinlock.h37
-rw-r--r--init/main.c2
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/panic.c2
-rw-r--r--kernel/sched.c9
-rw-r--r--kernel/softirq.c16
-rw-r--r--net/core/skbuff.c2
-rw-r--r--sound/pci/intel8x0.c4
36 files changed, 209 insertions, 556 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index c86358a1249f..15ba757d2d6b 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1084,9 +1084,9 @@ void smp_apic_timer_interrupt(struct pt_regs regs)
* Besides, if we don't timer interrupts ignore the global
* interrupt lock, which is the WrongThing (tm) to do.
*/
- irq_enter(cpu, 0);
+ irq_enter();
smp_local_timer_interrupt(&regs);
- irq_exit(cpu, 0);
+ irq_exit();
if (softirq_pending(cpu))
do_softirq();
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 11c3c42185cd..7202bc4ac19d 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -222,6 +222,8 @@
#include <linux/sysrq.h>
+extern rwlock_t xtime_lock;
+extern spinlock_t i8253_lock;
extern unsigned long get_cmos_time(void);
extern void machine_real_restart(unsigned char *, int);
@@ -1141,40 +1143,25 @@ out:
static void set_time(void)
{
- unsigned long flags;
-
- if (got_clock_diff) { /* Must know time zone in order to set clock */
- save_flags(flags);
- cli();
+ if (got_clock_diff) /* Must know time zone in order to set clock */
CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
- restore_flags(flags);
- }
}
static void get_time_diff(void)
{
#ifndef CONFIG_APM_RTC_IS_GMT
- unsigned long flags;
-
/*
* Estimate time zone so that set_time can update the clock
*/
- save_flags(flags);
clock_cmos_diff = -get_cmos_time();
- cli();
clock_cmos_diff += CURRENT_TIME;
got_clock_diff = 1;
- restore_flags(flags);
#endif
}
-static void reinit_timer(void)
+static inline void reinit_timer(void)
{
#ifdef INIT_TIMER_AFTER_SUSPEND
- unsigned long flags;
-
- save_flags(flags);
- cli();
/* set the clock to 100 Hz */
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
@@ -1182,7 +1169,6 @@ static void reinit_timer(void)
udelay(10);
outb(LATCH >> 8 , 0x40); /* MSB */
udelay(10);
- restore_flags(flags);
#endif
}
@@ -1203,13 +1189,21 @@ static int suspend(int vetoable)
}
printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
}
+ /* serialize with the timer interrupt */
+ write_lock_irq(&xtime_lock);
+
+ /* protect against access to timer chip registers */
+ spin_lock(&i8253_lock);
+
get_time_diff();
- cli();
err = set_system_power_state(APM_STATE_SUSPEND);
reinit_timer();
set_time();
ignore_normal_resume = 1;
- sti();
+
+ spin_unlock(&i8253_lock);
+ write_unlock_irq(&xtime_lock);
+
if (err == APM_NO_ERROR)
err = APM_SUCCESS;
if (err != APM_SUCCESS)
@@ -1232,8 +1226,12 @@ static void standby(void)
{
int err;
+ /* serialize with the timer interrupt */
+ write_lock_irq(&xtime_lock);
/* If needed, notify drivers here */
get_time_diff();
+ write_unlock_irq(&xtime_lock);
+
err = set_system_power_state(APM_STATE_STANDBY);
if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
apm_error("standby", err);
@@ -1321,7 +1319,9 @@ static void check_events(void)
ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
+ write_lock_irq(&xtime_lock);
set_time();
+ write_unlock_irq(&xtime_lock);
pm_send_all(PM_RESUME, (void *)0);
queue_event(event, NULL);
}
@@ -1336,7 +1336,9 @@ static void check_events(void)
break;
case APM_UPDATE_TIME:
+ write_lock_irq(&xtime_lock);
set_time();
+ write_unlock_irq(&xtime_lock);
break;
case APM_CRITICAL_SUSPEND:
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index c068803128c8..e5f506df8533 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -72,12 +72,8 @@ VM_MASK = 0x00020000
#ifdef CONFIG_PREEMPT
#define preempt_stop cli
-#define INC_PRE_COUNT(reg) incl TI_PRE_COUNT(reg);
-#define DEC_PRE_COUNT(reg) decl TI_PRE_COUNT(reg);
#else
#define preempt_stop
-#define INC_PRE_COUNT(reg)
-#define DEC_PRE_COUNT(reg)
#define resume_kernel restore_all
#endif
@@ -191,7 +187,6 @@ ENTRY(ret_from_fork)
ALIGN
ret_from_intr:
preempt_stop
- DEC_PRE_COUNT(%ebx)
ret_from_exception:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
@@ -338,9 +333,8 @@ vector=vector+1
ALIGN
common_interrupt:
SAVE_ALL
- GET_THREAD_INFO(%ebx)
- INC_PRE_COUNT(%ebx)
call do_IRQ
+ GET_THREAD_INFO(%ebx)
jmp ret_from_intr
#define BUILD_INTERRUPT(name, nr) \
@@ -348,7 +342,6 @@ ENTRY(name) \
pushl $nr-256; \
SAVE_ALL \
GET_THREAD_INFO(%ebx); \
- INC_PRE_COUNT(%ebx) \
call smp_/**/name; \
jmp ret_from_intr;
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 86ce6170a11d..04bbafb264ec 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -132,13 +132,7 @@ EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL_NOVERS(__write_lock_failed);
EXPORT_SYMBOL_NOVERS(__read_lock_failed);
-/* Global SMP irq stuff */
-EXPORT_SYMBOL(synchronize_irq);
-EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
+/* Global SMP stuff */
EXPORT_SYMBOL(smp_call_function);
/* TLB flushing */
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index d09e00d867da..2862186fbd07 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1219,7 +1219,7 @@ static int __init timer_irq_works(void)
{
unsigned int t1 = jiffies;
- sti();
+ __sti();
/* Let ten ticks pass... */
mdelay((10 * 1000) / HZ);
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 4265cb038a5a..0f61d288c37e 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -184,250 +184,12 @@ int show_interrupts(struct seq_file *p, void *v)
return 0;
}
-/*
- * Global interrupt locks for SMP. Allow interrupts to come in on any
- * CPU, yet make cli/sti act globally to protect critical regions..
- */
-
-#ifdef CONFIG_SMP
-unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */
-
-extern void show_stack(unsigned long* esp);
-
-static void show(char * str)
-{
- int i;
- int cpu = smp_processor_id();
-
- printk("\n%s, CPU %d:\n", str, cpu);
- printk("irq: %d [",irqs_running());
- for(i=0;i < NR_CPUS;i++)
- printk(" %d",local_irq_count(i));
- printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
- for(i=0;i < NR_CPUS;i++)
- printk(" %d",local_bh_count(i));
-
- printk(" ]\nStack dumps:");
- for(i = 0; i < NR_CPUS; i++) {
- unsigned long esp;
- if (i == cpu)
- continue;
- printk("\nCPU %d:",i);
- esp = init_tss[i].esp0;
- if (!esp) {
- /* tss->esp0 is set to NULL in cpu_init(),
- * it's initialized when the cpu returns to user
- * space. -- manfreds
- */
- printk(" <unknown> ");
- continue;
- }
- esp &= ~(THREAD_SIZE-1);
- esp += sizeof(struct thread_info);
- show_stack((void*)esp);
- }
- printk("\nCPU %d:",cpu);
- show_stack(NULL);
- printk("\n");
-}
-
-#define MAXCOUNT 100000000
-
-/*
- * I had a lockup scenario where a tight loop doing
- * spin_unlock()/spin_lock() on CPU#1 was racing with
- * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
- * apparently the spin_unlock() information did not make it
- * through to CPU#0 ... nasty, is this by design, do we have to limit
- * 'memory update oscillation frequency' artificially like here?
- *
- * Such 'high frequency update' races can be avoided by careful design, but
- * some of our major constructs like spinlocks use similar techniques,
- * it would be nice to clarify this issue. Set this define to 0 if you
- * want to check whether your system freezes. I suspect the delay done
- * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
- * i thought that such things are guaranteed by design, since we use
- * the 'LOCK' prefix.
- */
-#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0
-
-#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
-# define SYNC_OTHER_CORES(x) udelay(x+1)
-#else
-/*
- * We have to allow irqs to arrive between __sti and __cli
- */
-# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
-#endif
-
-static inline void wait_on_irq(int cpu)
-{
- int count = MAXCOUNT;
-
- for (;;) {
-
- /*
- * Wait until all interrupts are gone. Wait
- * for bottom half handlers unless we're
- * already executing in one..
- */
- if (!irqs_running())
- if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
- break;
-
- /* Duh, we have to loop. Release the lock to avoid deadlocks */
- clear_bit(0,&global_irq_lock);
-
- for (;;) {
- if (!--count) {
- show("wait_on_irq");
- count = ~0;
- }
- __sti();
- SYNC_OTHER_CORES(cpu);
- __cli();
- if (irqs_running())
- continue;
- if (global_irq_lock)
- continue;
- if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
- continue;
- if (!test_and_set_bit(0,&global_irq_lock))
- break;
- }
- }
-}
-
-/*
- * This is called when we want to synchronize with
- * interrupts. We may for example tell a device to
- * stop sending interrupts: but to make sure there
- * are no interrupts that are executing on another
- * CPU we need to call this function.
- */
-void synchronize_irq(void)
-{
- if (irqs_running()) {
- /* Stupid approach */
- cli();
- sti();
- }
-}
-
-static inline void get_irqlock(int cpu)
-{
- if (test_and_set_bit(0,&global_irq_lock)) {
- /* do we already hold the lock? */
- if ((unsigned char) cpu == global_irq_holder)
- return;
- /* Uhhuh.. Somebody else got it. Wait.. */
- do {
- do {
- rep_nop();
- } while (test_bit(0,&global_irq_lock));
- } while (test_and_set_bit(0,&global_irq_lock));
- }
- /*
- * We also to make sure that nobody else is running
- * in an interrupt context.
- */
- wait_on_irq(cpu);
-
- /*
- * Ok, finally..
- */
- global_irq_holder = cpu;
-}
-
-#define EFLAGS_IF_SHIFT 9
-
-/*
- * A global "cli()" while in an interrupt context
- * turns into just a local cli(). Interrupts
- * should use spinlocks for the (very unlikely)
- * case that they ever want to protect against
- * each other.
- *
- * If we already have local interrupts disabled,
- * this will not turn a local disable into a
- * global one (problems with spinlocks: this makes
- * save_flags+cli+sti usable inside a spinlock).
- */
-void __global_cli(void)
-{
- unsigned int flags;
-
- __save_flags(flags);
- if (flags & (1 << EFLAGS_IF_SHIFT)) {
- int cpu;
- __cli();
- cpu = smp_processor_id();
- if (!local_irq_count(cpu))
- get_irqlock(cpu);
- }
-}
-
-void __global_sti(void)
-{
- int cpu = get_cpu();
-
- if (!local_irq_count(cpu))
- release_irqlock(cpu);
- __sti();
- put_cpu();
-}
-
-/*
- * SMP flags value to restore to:
- * 0 - global cli
- * 1 - global sti
- * 2 - local cli
- * 3 - local sti
- */
-unsigned long __global_save_flags(void)
-{
- int retval;
- int local_enabled;
- unsigned long flags;
- int cpu = smp_processor_id();
-
- __save_flags(flags);
- local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
- /* default to local */
- retval = 2 + local_enabled;
-
- /* check for global flags if we're not in an interrupt */
- if (!local_irq_count(cpu)) {
- if (local_enabled)
- retval = 1;
- if (global_irq_holder == cpu)
- retval = 0;
- }
- return retval;
-}
-
-void __global_restore_flags(unsigned long flags)
+#if CONFIG_SMP
+inline void synchronize_irq(unsigned int irq)
{
- switch (flags) {
- case 0:
- __global_cli();
- break;
- case 1:
- __global_sti();
- break;
- case 2:
- __cli();
- break;
- case 3:
- __sti();
- break;
- default:
- printk("global_restore_flags: %08lx (%08lx)\n",
- flags, (&flags)[-1]);
- }
+ while (irq_desc[irq].status & IRQ_INPROGRESS)
+ cpu_relax();
}
-
#endif
/*
@@ -439,12 +201,7 @@ void __global_restore_flags(unsigned long flags)
*/
int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
{
- int status;
- int cpu = smp_processor_id();
-
- irq_enter(cpu, irq);
-
- status = 1; /* Force the "do bottom halves" bit */
+ int status = 1; /* Force the "do bottom halves" bit */
if (!(action->flags & SA_INTERRUPT))
__sti();
@@ -458,8 +215,6 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction *
add_interrupt_randomness(irq);
__cli();
- irq_exit(cpu, irq);
-
return status;
}
@@ -511,13 +266,7 @@ inline void disable_irq_nosync(unsigned int irq)
void disable_irq(unsigned int irq)
{
disable_irq_nosync(irq);
-
- if (!local_irq_count(smp_processor_id())) {
- do {
- barrier();
- cpu_relax();
- } while (irq_desc[irq].status & IRQ_INPROGRESS);
- }
+ synchronize_irq(irq);
}
/**
@@ -581,6 +330,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
struct irqaction * action;
unsigned int status;
+ irq_enter();
kstat.irqs[cpu][irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
@@ -640,6 +390,8 @@ out:
desc->handler->end(irq);
spin_unlock(&desc->lock);
+ irq_exit();
+
if (softirq_pending(cpu))
do_softirq();
return 1;
@@ -768,13 +520,8 @@ void free_irq(unsigned int irq, void *dev_id)
}
spin_unlock_irqrestore(&desc->lock,flags);
-#ifdef CONFIG_SMP
/* Wait to make sure it's not being used on another CPU */
- while (desc->status & IRQ_INPROGRESS) {
- barrier();
- cpu_relax();
- }
-#endif
+ synchronize_irq(irq);
kfree(action);
return;
}
@@ -826,7 +573,7 @@ unsigned long probe_irq_on(void)
/* Wait for longstanding interrupts to trigger. */
for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
- /* about 20ms delay */ synchronize_irq();
+ /* about 20ms delay */ barrier();
/*
* enable any unassigned irqs
@@ -849,7 +596,7 @@ unsigned long probe_irq_on(void)
* Wait for spurious interrupts to trigger
*/
for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
- /* about 100ms delay */ synchronize_irq();
+ /* about 100ms delay */ barrier();
/*
* Now filter out any obviously spurious interrupts
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index dc7db1cdce4c..067dafca3a6c 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -102,6 +102,12 @@ struct MCA_info {
static struct MCA_info* mca_info = NULL;
+/*
+ * Motherboard register spinlock. Untested on SMP at the moment, but
+ * are there any MCA SMP boxes?
+ */
+static spinlock_t mca_lock = SPIN_LOCK_UNLOCKED;
+
/* MCA registers */
#define MCA_MOTHERBOARD_SETUP_REG 0x94
@@ -213,8 +219,11 @@ void __init mca_init(void)
}
memset(mca_info, 0, sizeof(struct MCA_info));
- save_flags(flags);
- cli();
+ /*
+ * We do not expect many MCA interrupts during initialization,
+ * but let us be safe:
+ */
+ spin_lock_irq(&mca_lock);
/* Make sure adapter setup is off */
@@ -300,8 +309,7 @@ void __init mca_init(void)
outb_p(0, MCA_ADAPTER_SETUP_REG);
/* Enable interrupts and return memory start */
-
- restore_flags(flags);
+ spin_unlock_irq(&mca_lock);
for (i = 0; i < MCA_STANDARD_RESOURCES; i++)
request_resource(&ioport_resource, mca_standard_resources + i);
@@ -514,8 +522,7 @@ unsigned char mca_read_pos(int slot, int reg)
if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0;
if(reg < 0 || reg >= 8) return 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&mca_lock, flags);
/* Make sure motherboard setup is off */
@@ -566,7 +573,7 @@ unsigned char mca_read_pos(int slot, int reg)
mca_info->slot[slot].pos[reg] = byte;
- restore_flags(flags);
+ spin_unlock_irqrestore(&mca_lock, flags);
return byte;
} /* mca_read_pos() */
@@ -610,8 +617,7 @@ void mca_write_pos(int slot, int reg, unsigned char byte)
if(mca_info == NULL)
return;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&mca_lock, flags);
/* Make sure motherboard setup is off */
@@ -623,7 +629,7 @@ void mca_write_pos(int slot, int reg, unsigned char byte)
outb_p(byte, MCA_POS_REG(reg));
outb_p(0, MCA_ADAPTER_SETUP_REG);
- restore_flags(flags);
+ spin_unlock_irqrestore(&mca_lock, flags);
/* Update the global register list, while we have the byte */
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index a2447287092d..679e63e9d2cb 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -78,7 +78,7 @@ int __init check_nmi_watchdog (void)
printk(KERN_INFO "testing NMI watchdog ... ");
memcpy(tmp, irq_stat, sizeof(tmp));
- sti();
+ __sti();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
for (cpu = 0; cpu < NR_CPUS; cpu++) {
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 57bc712dbc66..24aed22022a3 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -290,7 +290,7 @@ void machine_real_restart(unsigned char *code, int length)
{
unsigned long flags;
- cli();
+ __cli();
/* Write zero to CMOS register number 0x0f, which the BIOS POST
routine will recognize as telling it to do a proper reboot. (Well
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index d77a1fb38d0f..178e3431ab9e 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1060,7 +1060,6 @@ void __init smp_boot_cpus(void)
boot_cpu_logical_apicid = logical_smp_processor_id();
map_cpu_to_boot_apicid(0, boot_cpu_apicid);
- global_irq_holder = NO_PROC_ID;
current_thread_info()->cpu = 0;
smp_tune_scheduling();
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 195a2b943908..7c60b661f713 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -571,6 +571,8 @@ static struct vm86_irqs {
struct task_struct *tsk;
int sig;
} vm86_irqs[16];
+
+static spinlock_t irqbits_lock = SPIN_LOCK_UNLOCKED;
static int irqbits;
#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
@@ -580,9 +582,8 @@ static int irqbits;
static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
int irq_bit;
unsigned long flags;
-
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&irqbits_lock, flags);
irq_bit = 1 << intno;
if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
goto out;
@@ -591,14 +592,19 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
/* else user will poll for IRQs */
out:
- restore_flags(flags);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
}
static inline void free_vm86_irq(int irqnumber)
{
+ unsigned long flags;
+
free_irq(irqnumber,0);
vm86_irqs[irqnumber].tsk = 0;
+
+ spin_lock_irqsave(&irqbits_lock, flags);
irqbits &= ~(1 << irqnumber);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
}
static inline int task_valid(struct task_struct *tsk)
@@ -635,11 +641,10 @@ static inline int get_and_reset_irq(int irqnumber)
if ( (irqnumber<3) || (irqnumber>15) ) return 0;
if (vm86_irqs[irqnumber].tsk != current) return 0;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&irqbits_lock, flags);
bit = irqbits & (1 << irqnumber);
irqbits &= ~bit;
- restore_flags(flags);
+ spin_unlock_irqrestore(&irqbits_lock, flags);
return bit;
}
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 474009886b35..8c4328690ebe 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -107,27 +107,25 @@ extern spinlock_t timerlist_lock;
*/
void bust_spinlocks(int yes)
{
+ int loglevel_save = console_loglevel;
+
spin_lock_init(&timerlist_lock);
if (yes) {
oops_in_progress = 1;
-#ifdef CONFIG_SMP
- global_irq_lock = 0; /* Many serial drivers do __global_cli() */
-#endif
- } else {
- int loglevel_save = console_loglevel;
+ return;
+ }
#ifdef CONFIG_VT
- unblank_screen();
+ unblank_screen();
#endif
- oops_in_progress = 0;
- /*
- * OK, the message is on the console. Now we call printk()
- * without oops_in_progress set so that printk will give klogd
- * a poke. Hold onto your hats...
- */
- console_loglevel = 15; /* NMI oopser may have shut the console up */
- printk(" ");
- console_loglevel = loglevel_save;
- }
+ oops_in_progress = 0;
+ /*
+ * OK, the message is on the console. Now we call printk()
+ * without oops_in_progress set so that printk will give klogd
+ * a poke. Hold onto your hats...
+ */
+ console_loglevel = 15; /* NMI oopser may have shut the console up */
+ printk(" ");
+ console_loglevel = loglevel_save;
}
asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 6bb06af38980..0fc011f610d1 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -184,7 +184,6 @@ int __init device_init(void)
{
rwlock_init(&gendisk_lock);
blk_dev_init();
- sti();
#ifdef CONFIG_I2O
i2o_init();
#endif
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 8ada278181c8..c23f57a0ed16 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2041,9 +2041,6 @@ int __init blk_dev_init(void)
#if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD)
hd_init();
#endif
-#if defined(__i386__) /* Do we even need this? */
- outb_p(0xc, 0x3f2);
-#endif
return 0;
};
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index d748d499da60..7cf8fb5cfcb5 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -807,7 +807,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
I_PARMRK(tty)) {
- cli();
+ __cli(); // FIXME: is this safe?
memset(tty->process_char_map, 0, 256/8);
if (I_IGNCR(tty) || I_ICRNL(tty))
@@ -843,7 +843,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
set_bit(SUSP_CHAR(tty), tty->process_char_map);
}
clear_bit(__DISABLED_CHAR, tty->process_char_map);
- sti();
+ __sti(); // FIXME: is this safe?
tty->raw = 0;
tty->real_raw = 0;
} else {
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6789e5ecf6b5..59567e8b8fa6 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -456,11 +456,12 @@ void do_tty_hangup(void *data)
}
file_list_unlock();
- /* FIXME! What are the locking issues here? This may me overdoing things.. */
+ /* FIXME! What are the locking issues here? This may me overdoing things..
+ * this question is especially important now that we've removed the irqlock. */
{
unsigned long flags;
- save_flags(flags); cli();
+ __save_flags(flags); __cli(); // FIXME: is this safe?
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
if (tty->driver.flush_buffer)
@@ -468,7 +469,7 @@ void do_tty_hangup(void *data)
if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
- restore_flags(flags);
+ __restore_flags(flags); // FIXME: is this safe?
}
wake_up_interruptible(&tty->write_wait);
@@ -1900,7 +1901,7 @@ static void flush_to_ldisc(void *private_)
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
tty->flip.buf_num = 0;
- save_flags(flags); cli();
+ __save_flags(flags); __cli(); // FIXME: is this safe?
tty->flip.char_buf_ptr = tty->flip.char_buf;
tty->flip.flag_buf_ptr = tty->flip.flag_buf;
} else {
@@ -1908,13 +1909,13 @@ static void flush_to_ldisc(void *private_)
fp = tty->flip.flag_buf;
tty->flip.buf_num = 1;
- save_flags(flags); cli();
+ __save_flags(flags); __cli(); // FIXME: is this safe?
tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
}
count = tty->flip.count;
tty->flip.count = 0;
- restore_flags(flags);
+ __restore_flags(flags); // FIXME: is this safe?
tty->ldisc.receive_buf(tty, cp, fp, count);
}
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 6fe1ef20e409..68662c975de4 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -97,7 +97,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
int canon_change;
struct termios old_termios = *tty->termios;
- cli();
+ __cli(); // FIXME: is this safe?
*tty->termios = *new_termios;
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
@@ -107,7 +107,7 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
tty->canon_data = 0;
tty->erasing = 0;
}
- sti();
+ __sti(); // FIXME: is this safe?
if (canon_change && !L_ICANON(tty) && tty->read_cnt)
/* Get characters left over from canonical mode. */
wake_up_interruptible(&tty->read_wait);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e59c0cef09e7..87a0b5904263 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -113,8 +113,8 @@ _kd_mksound(unsigned int hz, unsigned int ticks)
if (hz > 20 && hz < 32767)
count = 1193180 / hz;
- save_flags(flags);
- cli();
+ __save_flags(flags); // FIXME: is this safe?
+ __cli();
del_timer(&sound_timer);
if (count) {
/* enable counter 2 */
@@ -131,7 +131,7 @@ _kd_mksound(unsigned int hz, unsigned int ticks)
}
} else
kd_nosound(0);
- restore_flags(flags);
+ __restore_flags(flags);
return;
}
diff --git a/drivers/ide/main.c b/drivers/ide/main.c
index 2f5f34953263..6c09337f334f 100644
--- a/drivers/ide/main.c
+++ b/drivers/ide/main.c
@@ -1082,18 +1082,18 @@ int ide_unregister_subdriver(struct ata_device *drive)
{
unsigned long flags;
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
+ __save_flags(flags); // FIXME: is this safe?
+ __cli();
#if 0
if (__MOD_IN_USE(ata_ops(drive)->owner)) {
- restore_flags(flags);
+ __restore_flags(flags); // FIXME: is this safe?
return 1;
}
#endif
if (drive->usage || drive->busy || !ata_ops(drive)) {
- restore_flags(flags); /* all CPUs */
+ __restore_flags(flags); // FIXME: is this safe?
return 1;
}
@@ -1102,7 +1102,7 @@ int ide_unregister_subdriver(struct ata_device *drive)
#endif
drive->driver = NULL;
- restore_flags(flags); /* all CPUs */
+ __restore_flags(flags); // FIXME: is this safe?
return 0;
}
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index cd6524d58341..485a0a319a98 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1354,7 +1354,7 @@ static void speedo_tx_timeout(struct net_device *dev)
udelay(10);
/* Disable interrupts. */
outw(SCBMaskAll, ioaddr + SCBCmd);
- synchronize_irq();
+ synchronize_irq(dev->irq);
speedo_tx_buffer_gc(dev);
/* Free as much as possible.
It helps to recover from a hang because of out-of-memory.
diff --git a/include/asm-generic/smplock.h b/include/asm-generic/smplock.h
index 96565069c988..d77431f2cb25 100644
--- a/include/asm-generic/smplock.h
+++ b/include/asm-generic/smplock.h
@@ -13,11 +13,10 @@ extern spinlock_t kernel_flag;
/*
* Release global kernel lock and global interrupt lock
*/
-#define release_kernel_lock(task, cpu) \
+#define release_kernel_lock(task) \
do { \
if (task->lock_depth >= 0) \
spin_unlock(&kernel_flag); \
- release_irqlock(cpu); \
__sti(); \
} while (0)
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index ed73b0444f6b..cbd78d1dcaa1 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -8,8 +8,6 @@
/* assembly code in softirq.h is sensitive to the offsets of these fields */
typedef struct {
unsigned int __softirq_pending;
- unsigned int __local_irq_count;
- unsigned int __local_bh_count;
unsigned int __syscall_count;
struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
unsigned long idle_timestamp;
@@ -18,77 +16,27 @@ typedef struct {
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#define IRQ_OFFSET 64
+
/*
* Are we in an interrupt context? Either doing bottom half
* or hardware interrupt processing?
*/
-#define in_interrupt() ({ int __cpu = smp_processor_id(); \
- (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
-
-#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-
-#ifndef CONFIG_SMP
-
-#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
-#define hardirq_endlock(cpu) do { } while (0)
+#define in_interrupt() \
+ ((preempt_count() & ~PREEMPT_ACTIVE) >= IRQ_OFFSET)
-#define irq_enter(cpu, irq) (local_irq_count(cpu)++)
-#define irq_exit(cpu, irq) (local_irq_count(cpu)--)
+#define in_irq in_interrupt
-#define synchronize_irq() barrier()
+#define hardirq_trylock() (!in_interrupt())
+#define hardirq_endlock() do { } while (0)
-#define release_irqlock(cpu) do { } while (0)
+#define irq_enter() (preempt_count() += IRQ_OFFSET)
+#define irq_exit() (preempt_count() -= IRQ_OFFSET)
+#ifndef CONFIG_SMP
+# define synchronize_irq(irq) barrier()
#else
-
-#include <asm/atomic.h>
-#include <asm/smp.h>
-
-extern unsigned char global_irq_holder;
-extern unsigned volatile long global_irq_lock; /* long for set_bit -RR */
-
-static inline int irqs_running (void)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; i++)
- if (local_irq_count(i))
- return 1;
- return 0;
-}
-
-static inline void release_irqlock(int cpu)
-{
- /* if we didn't own the irq lock, just ignore.. */
- if (global_irq_holder == (unsigned char) cpu) {
- global_irq_holder = NO_PROC_ID;
- clear_bit(0,&global_irq_lock);
- }
-}
-
-static inline void irq_enter(int cpu, int irq)
-{
- ++local_irq_count(cpu);
-
- while (test_bit(0,&global_irq_lock)) {
- cpu_relax();
- }
-}
-
-static inline void irq_exit(int cpu, int irq)
-{
- --local_irq_count(cpu);
-}
-
-static inline int hardirq_trylock(int cpu)
-{
- return !local_irq_count(cpu) && !test_bit(0,&global_irq_lock);
-}
-
-#define hardirq_endlock(cpu) do { } while (0)
-
-extern void synchronize_irq(void);
-
+ extern void synchronize_irq(unsigned int irq);
#endif /* CONFIG_SMP */
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-i386/smplock.h b/include/asm-i386/smplock.h
index 888a7b82f103..8bee3fd434c0 100644
--- a/include/asm-i386/smplock.h
+++ b/include/asm-i386/smplock.h
@@ -12,15 +12,9 @@ extern spinlock_t kernel_flag;
#ifdef CONFIG_SMP
#define kernel_locked() spin_is_locked(&kernel_flag)
-#define check_irq_holder(cpu) \
-do { \
- if (global_irq_holder == (cpu)) \
- BUG(); \
-} while(0)
#else
#ifdef CONFIG_PREEMPT
-#define kernel_locked() preempt_get_count()
-#define check_irq_holder(cpu) do { } while(0)
+#define kernel_locked() preempt_count()
#else
#define kernel_locked() 1
#endif
@@ -29,12 +23,10 @@ do { \
/*
* Release global kernel lock and global interrupt lock
*/
-#define release_kernel_lock(task, cpu) \
+#define release_kernel_lock(task) \
do { \
- if (unlikely(task->lock_depth >= 0)) { \
+ if (unlikely(task->lock_depth >= 0)) \
spin_unlock(&kernel_flag); \
- check_irq_holder(cpu); \
- } \
} while (0)
/*
diff --git a/include/asm-i386/softirq.h b/include/asm-i386/softirq.h
index c62cbece6ce7..c28019d821af 100644
--- a/include/asm-i386/softirq.h
+++ b/include/asm-i386/softirq.h
@@ -1,50 +1,27 @@
#ifndef __ASM_SOFTIRQ_H
#define __ASM_SOFTIRQ_H
-#include <asm/atomic.h>
+#include <linux/preempt.h>
#include <asm/hardirq.h>
-#define __cpu_bh_enable(cpu) \
- do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
-#define cpu_bh_disable(cpu) \
- do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
+#define local_bh_disable() \
+ do { preempt_count() += IRQ_OFFSET; barrier(); } while (0)
+#define __local_bh_enable() \
+ do { barrier(); preempt_count() -= IRQ_OFFSET; } while (0)
-#define local_bh_disable() cpu_bh_disable(smp_processor_id())
-#define __local_bh_enable() __cpu_bh_enable(smp_processor_id())
-
-#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
-
-/*
- * NOTE: this assembly code assumes:
- *
- * (char *)&local_bh_count - 8 == (char *)&softirq_pending
- *
- * If you change the offsets in irq_stat then you have to
- * update this code as well.
- */
-#define _local_bh_enable() \
+#define local_bh_enable() \
do { \
- unsigned int *ptr = &local_bh_count(smp_processor_id()); \
- \
- barrier(); \
- if (!--*ptr) \
- __asm__ __volatile__ ( \
- "cmpl $0, -8(%0);" \
- "jnz 2f;" \
- "1:;" \
- \
- LOCK_SECTION_START("") \
- "2: pushl %%eax; pushl %%ecx; pushl %%edx;" \
- "call %c1;" \
- "popl %%edx; popl %%ecx; popl %%eax;" \
- "jmp 1b;" \
- LOCK_SECTION_END \
- \
- : /* no output */ \
- : "r" (ptr), "i" (do_softirq) \
- /* no registers clobbered */ ); \
+ if (unlikely((preempt_count() == IRQ_OFFSET) && \
+ softirq_pending(smp_processor_id()))) { \
+ __local_bh_enable(); \
+ do_softirq(); \
+ preempt_check_resched(); \
+ } else { \
+ __local_bh_enable(); \
+ preempt_check_resched(); \
+ } \
} while (0)
-#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
+#define in_softirq() in_interrupt()
#endif /* __ASM_SOFTIRQ_H */
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 851f090e4394..7d9fa1282e26 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -324,24 +324,14 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
-#ifdef CONFIG_SMP
-
-extern void __global_cli(void);
-extern void __global_sti(void);
-extern unsigned long __global_save_flags(void);
-extern void __global_restore_flags(unsigned long);
-#define cli() __global_cli()
-#define sti() __global_sti()
-#define save_flags(x) ((x)=__global_save_flags())
-#define restore_flags(x) __global_restore_flags(x)
-
-#else
-
-#define cli() __cli()
-#define sti() __sti()
-#define save_flags(x) __save_flags(x)
-#define restore_flags(x) __restore_flags(x)
-
+/*
+ * Compatibility macros - they will be removed after some time.
+ */
+#if !CONFIG_SMP
+# define sti() __sti()
+# define cli() __cli()
+# define save_flags(flags) __save_flags(flags)
+# define restore_flags(flags) __restore_flags(flags)
#endif
/*
diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h
index dfd73c5ec60d..6eab29be1d61 100644
--- a/include/linux/irq_cpustat.h
+++ b/include/linux/irq_cpustat.h
@@ -29,8 +29,6 @@ extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
/* arch independent irq_stat fields */
#define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending)
-#define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count)
-#define local_bh_count(cpu) __IRQ_STAT((cpu), __local_bh_count)
#define syscall_count(cpu) __IRQ_STAT((cpu), __syscall_count)
#define ksoftirqd_task(cpu) __IRQ_STAT((cpu), __ksoftirqd_task)
/* arch dependent irq_stat fields */
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
new file mode 100644
index 000000000000..172471f0dbde
--- /dev/null
+++ b/include/linux/preempt.h
@@ -0,0 +1,46 @@
+#ifndef __LINUX_PREEMPT_H
+#define __LINUX_PREEMPT_H
+
+#include <linux/config.h>
+
+#define preempt_count() (current_thread_info()->preempt_count)
+
+#ifdef CONFIG_PREEMPT
+
+extern void preempt_schedule(void);
+
+#define preempt_disable() \
+do { \
+ preempt_count()++; \
+ barrier(); \
+} while (0)
+
+#define preempt_enable_no_resched() \
+do { \
+ preempt_count()--; \
+ barrier(); \
+} while (0)
+
+#define preempt_enable() \
+do { \
+ preempt_enable_no_resched(); \
+ if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
+ preempt_schedule(); \
+} while (0)
+
+#define preempt_check_resched() \
+do { \
+ if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
+ preempt_schedule(); \
+} while (0)
+
+#else
+
+#define preempt_disable() do { } while (0)
+#define preempt_enable_no_resched() do {} while(0)
+#define preempt_enable() do { } while (0)
+#define preempt_check_resched() do { } while (0)
+
+#endif
+
+#endif /* __LINUX_PREEMPT_H */
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index 13d8c7ace0bb..cfb23f363e61 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -7,7 +7,7 @@
#define lock_kernel() do { } while(0)
#define unlock_kernel() do { } while(0)
-#define release_kernel_lock(task, cpu) do { } while(0)
+#define release_kernel_lock(task) do { } while(0)
#define reacquire_kernel_lock(task) do { } while(0)
#define kernel_locked() 1
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 194541968c6a..d9f4af4103e4 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -2,6 +2,7 @@
#define __LINUX_SPINLOCK_H
#include <linux/config.h>
+#include <linux/preempt.h>
#include <linux/linkage.h>
#include <linux/compiler.h>
#include <linux/thread_info.h>
@@ -120,36 +121,6 @@
#ifdef CONFIG_PREEMPT
-asmlinkage void preempt_schedule(void);
-
-#define preempt_get_count() (current_thread_info()->preempt_count)
-
-#define preempt_disable() \
-do { \
- ++current_thread_info()->preempt_count; \
- barrier(); \
-} while (0)
-
-#define preempt_enable_no_resched() \
-do { \
- --current_thread_info()->preempt_count; \
- barrier(); \
-} while (0)
-
-#define preempt_enable() \
-do { \
- --current_thread_info()->preempt_count; \
- barrier(); \
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
- preempt_schedule(); \
-} while (0)
-
-#define preempt_check_resched() \
-do { \
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
- preempt_schedule(); \
-} while (0)
-
#define spin_lock(lock) \
do { \
preempt_disable(); \
@@ -179,12 +150,6 @@ do { \
#else
-#define preempt_get_count() (0)
-#define preempt_disable() do { } while (0)
-#define preempt_enable_no_resched() do {} while(0)
-#define preempt_enable() do { } while (0)
-#define preempt_check_resched() do { } while (0)
-
#define spin_lock(lock) _raw_spin_lock(lock)
#define spin_trylock(lock) _raw_spin_trylock(lock)
#define spin_unlock(lock) _raw_spin_unlock(lock)
diff --git a/init/main.c b/init/main.c
index 2133b32001de..3bef5a614a45 100644
--- a/init/main.c
+++ b/init/main.c
@@ -373,7 +373,7 @@ asmlinkage void __init start_kernel(void)
}
kmem_cache_init();
- sti();
+ __sti();
calibrate_delay();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
diff --git a/kernel/exit.c b/kernel/exit.c
index f727a3c511c8..71d017f2fd8f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -530,10 +530,10 @@ NORET_TYPE void do_exit(long code)
tsk->flags |= PF_EXITING;
del_timer_sync(&tsk->real_timer);
- if (unlikely(preempt_get_count()))
+ if (unlikely(preempt_count()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
current->comm, current->pid,
- preempt_get_count());
+ preempt_count());
fake_volatile:
acct_process(code);
diff --git a/kernel/panic.c b/kernel/panic.c
index 5281e7cce9f8..9661ad669363 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -94,7 +94,7 @@ NORET_TYPE void panic(const char * fmt, ...)
#if defined(CONFIG_ARCH_S390)
disabled_wait(caller);
#endif
- sti();
+ __sti();
for(;;) {
CHECK_EMERGENCY_SYNC
}
diff --git a/kernel/sched.c b/kernel/sched.c
index c8a11b29794e..3d275a38109e 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -727,7 +727,8 @@ void scheduler_tick(int user_tick, int system)
task_t *p = current;
if (p == rq->idle) {
- if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
+ /* note: this timer irq context must be accounted for as well */
+ if (preempt_count() >= 2*IRQ_OFFSET)
kstat.per_cpu_system[cpu] += system;
#if CONFIG_SMP
idle_tick();
@@ -816,7 +817,7 @@ need_resched:
prev = current;
rq = this_rq();
- release_kernel_lock(prev, smp_processor_id());
+ release_kernel_lock(prev);
prepare_arch_schedule(prev);
prev->sleep_timestamp = jiffies;
spin_lock_irq(&rq->lock);
@@ -825,7 +826,7 @@ need_resched:
* if entering off of a kernel preemption go straight
* to picking the next task.
*/
- if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
+ if (unlikely(preempt_count() & PREEMPT_ACTIVE))
goto pick_next_task;
switch (prev->state) {
@@ -1694,7 +1695,9 @@ void __init init_idle(task_t *idle, int cpu)
__restore_flags(flags);
/* Set the preempt count _outside_ the spinlocks! */
+#if CONFIG_PREEMPT
idle->thread_info->preempt_count = (idle->lock_depth >= 0);
+#endif
}
extern void init_timervecs(void);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index e0093420e169..a53dd2828cb5 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -61,17 +61,17 @@ static inline void wakeup_softirqd(unsigned cpu)
asmlinkage void do_softirq()
{
- int cpu;
__u32 pending;
long flags;
__u32 mask;
+ int cpu;
if (in_interrupt())
return;
local_irq_save(flags);
-
cpu = smp_processor_id();
+
pending = softirq_pending(cpu);
if (pending) {
@@ -111,7 +111,7 @@ restart:
}
/*
- * This function must run with irq disabled!
+ * This function must run with irqs disabled!
*/
inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
{
@@ -126,7 +126,7 @@ inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
* Otherwise we wake up ksoftirqd to make sure we
* schedule the softirq soon.
*/
- if (!(local_irq_count(cpu) | local_bh_count(cpu)))
+ if (!in_interrupt())
wakeup_softirqd(cpu);
}
@@ -290,22 +290,16 @@ spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
static void bh_action(unsigned long nr)
{
- int cpu = smp_processor_id();
-
if (!spin_trylock(&global_bh_lock))
goto resched;
- if (!hardirq_trylock(cpu))
- goto resched_unlock;
-
if (bh_base[nr])
bh_base[nr]();
- hardirq_endlock(cpu);
+ hardirq_endlock();
spin_unlock(&global_bh_lock);
return;
-resched_unlock:
spin_unlock(&global_bh_lock);
resched:
mark_bh(nr);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 74cbdeb53734..0f327d594231 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -318,7 +318,7 @@ void __kfree_skb(struct sk_buff *skb)
dst_release(skb->dst);
if(skb->destructor) {
- if (in_irq())
+ if (0 && in_irq())
printk(KERN_WARNING "Warning: kfree_skb on "
"hard IRQ %p\n", NET_CALLER(skb));
skb->destructor(skb);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index f67cc0f4e9fa..fed9bb159112 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1104,7 +1104,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
outb(ICH_RESETREGS, ICHREG(chip, PO_CR));
outb(ICH_RESETREGS, ICHREG(chip, MC_CR));
/* --- */
- synchronize_irq();
+ synchronize_irq(chip->irq);
__hw_end:
if (chip->bdbars)
snd_free_pci_pages(chip->pci, 3 * sizeof(u32) * ICH_MAX_FRAGS * 2, chip->bdbars, chip->bdbars_addr);
@@ -1335,7 +1335,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
}
chip->irq = pci->irq;
pci_set_master(pci);
- synchronize_irq();
+ synchronize_irq(chip->irq);
/* initialize offsets */
chip->reg_pi_sr = ICH_REG_PI_SR;