parisc: fix irq stack on UP and SMP
The logic to detect if the irq stack was already in use with raw_spin_trylock() is wrong, because it will generate a "trylock failure on UP" error message with CONFIG_SMP=n and CONFIG_DEBUG_SPINLOCK=y. arch_spin_trylock() can't be used either since in the CONFIG_SMP=n case no atomic protection is given and we are reentrant here. A mutex didn't worked either and brings more overhead by turning off interrupts. So, let's use the fastest path for parisc which is the ldcw instruction. Counting how often the irq stack was used is pretty useless, so just drop this piece of code. Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
parent
2c2d32bed1
commit
d96b51ec14
|
@ -17,13 +17,8 @@
|
|||
|
||||
typedef struct {
|
||||
unsigned int __softirq_pending;
|
||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||
unsigned int kernel_stack_usage;
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
unsigned int irq_stack_usage;
|
||||
unsigned int irq_stack_counter;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int irq_resched_count;
|
||||
unsigned int irq_call_count;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <asm/ptrace.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/percpu.h>
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
|
@ -58,26 +57,6 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* IRQ STACK - used for irq handler
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/spinlock_types.h>
|
||||
|
||||
#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */
|
||||
|
||||
union irq_stack_union {
|
||||
unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
|
||||
raw_spinlock_t lock;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(union irq_stack_union, irq_stack_union);
|
||||
|
||||
void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* Data detected about CPUs at boot time which is the same for all CPU's.
|
||||
* HP boxes are SMP - ie identical processors.
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/smp.h>
|
||||
#include <asm/ldcw.h>
|
||||
|
||||
#undef PARISC_IRQ_CR16_COUNTS
|
||||
|
||||
|
@ -172,10 +172,6 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->irq_stack_usage);
|
||||
seq_puts(p, " Interrupt stack usage\n");
|
||||
seq_printf(p, "%*s: ", prec, "ISC");
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->irq_stack_counter);
|
||||
seq_puts(p, " Interrupt stack usage counter\n");
|
||||
# endif
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -384,6 +380,24 @@ static inline int eirr_to_irq(unsigned long eirr)
|
|||
return (BITS_PER_LONG - bit) + TIMER_IRQ;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
/*
|
||||
* IRQ STACK - used for irq handler
|
||||
*/
|
||||
#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */
|
||||
|
||||
union irq_stack_union {
|
||||
unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
|
||||
volatile unsigned int slock[4];
|
||||
volatile unsigned int lock[1];
|
||||
};
|
||||
|
||||
DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
|
||||
.slock = { 1,1,1,1 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
int sysctl_panic_on_stackoverflow = 1;
|
||||
|
||||
static inline void stack_overflow_check(struct pt_regs *regs)
|
||||
|
@ -450,27 +464,26 @@ panic_check:
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
|
||||
.lock = __RAW_SPIN_LOCK_UNLOCKED((irq_stack_union).lock)
|
||||
};
|
||||
/* in entry.S: */
|
||||
void call_on_stack(unsigned long p1, void *func, unsigned long new_stack);
|
||||
|
||||
static void execute_on_irq_stack(void *func, unsigned long param1)
|
||||
{
|
||||
union irq_stack_union *union_ptr;
|
||||
unsigned long irq_stack;
|
||||
raw_spinlock_t *irq_stack_in_use;
|
||||
volatile unsigned int *irq_stack_in_use;
|
||||
|
||||
union_ptr = &per_cpu(irq_stack_union, smp_processor_id());
|
||||
irq_stack = (unsigned long) &union_ptr->stack;
|
||||
irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.lock),
|
||||
irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.slock),
|
||||
64); /* align for stack frame usage */
|
||||
|
||||
/* We may be called recursive. If we are already using the irq stack,
|
||||
* just continue to use it. Use spinlocks to serialize
|
||||
* the irq stack usage.
|
||||
*/
|
||||
irq_stack_in_use = &union_ptr->lock;
|
||||
if (!raw_spin_trylock(irq_stack_in_use)) {
|
||||
irq_stack_in_use = (volatile unsigned int *)__ldcw_align(union_ptr);
|
||||
if (!__ldcw(irq_stack_in_use)) {
|
||||
void (*direct_call)(unsigned long p1) = func;
|
||||
|
||||
/* We are using the IRQ stack already.
|
||||
|
@ -482,10 +495,8 @@ static void execute_on_irq_stack(void *func, unsigned long param1)
|
|||
/* This is where we switch to the IRQ stack. */
|
||||
call_on_stack(param1, func, irq_stack);
|
||||
|
||||
__inc_irq_stat(irq_stack_counter);
|
||||
|
||||
/* free up irq stack usage. */
|
||||
do_raw_spin_unlock(irq_stack_in_use);
|
||||
*irq_stack_in_use = 1;
|
||||
}
|
||||
|
||||
asmlinkage void do_softirq(void)
|
||||
|
|
Loading…
Reference in New Issue