Commit d96b51ec authored by Helge Deller's avatar Helge Deller

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: default avatarHelge Deller <deller@gmx.de>
parent 2c2d32be
......@@ -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 @@ static inline void stack_overflow_check(struct pt_regs *regs)
}
#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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment