Commit 354f4492 authored by Paul Mackerras's avatar Paul Mackerras

PPC32: update hard/soft IRQ stuff along the lines of the i386 code.

parent a832c38b
...@@ -507,9 +507,8 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -507,9 +507,8 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
} }
#ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_pic.c */ #ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_pic.c */
int do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs)
{ {
int cpu = smp_processor_id();
int irq, first = 1; int irq, first = 1;
irq_enter(); irq_enter();
...@@ -529,10 +528,6 @@ int do_IRQ(struct pt_regs *regs) ...@@ -529,10 +528,6 @@ int do_IRQ(struct pt_regs *regs)
/* That's not SMP safe ... but who cares ? */ /* That's not SMP safe ... but who cares ? */
ppc_spurious_interrupts++; ppc_spurious_interrupts++;
irq_exit(); irq_exit();
if (softirq_pending(cpu))
do_softirq();
return 1; /* lets ret_from_int know we can do checks */
} }
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
...@@ -566,6 +561,10 @@ void __init init_IRQ(void) ...@@ -566,6 +561,10 @@ void __init init_IRQ(void)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void synchronize_irq(unsigned int irq) void synchronize_irq(unsigned int irq)
{ {
/* is there anything to synchronize with? */
if (!irq_desc[irq].action)
return;
while (irq_desc[irq].status & IRQ_INPROGRESS) while (irq_desc[irq].status & IRQ_INPROGRESS)
barrier(); barrier();
} }
......
...@@ -202,8 +202,7 @@ void __switch_to(struct task_struct *prev, struct task_struct *new) ...@@ -202,8 +202,7 @@ void __switch_to(struct task_struct *prev, struct task_struct *new)
struct thread_struct *new_thread, *old_thread; struct thread_struct *new_thread, *old_thread;
unsigned long s; unsigned long s;
local_save_flags(s); local_irq_save(s);
local_irq_disable();
#if CHECK_STACK #if CHECK_STACK
check_stack(prev); check_stack(prev);
check_stack(new); check_stack(new);
......
...@@ -151,7 +151,7 @@ static inline void ppc_do_profile (unsigned long nip) ...@@ -151,7 +151,7 @@ static inline void ppc_do_profile (unsigned long nip)
* with interrupts disabled. * with interrupts disabled.
* We set it up to overflow again in 1/HZ seconds. * We set it up to overflow again in 1/HZ seconds.
*/ */
int timer_interrupt(struct pt_regs * regs) void timer_interrupt(struct pt_regs * regs)
{ {
int next_dec; int next_dec;
unsigned long cpu = smp_processor_id(); unsigned long cpu = smp_processor_id();
...@@ -215,11 +215,6 @@ int timer_interrupt(struct pt_regs * regs) ...@@ -215,11 +215,6 @@ int timer_interrupt(struct pt_regs * regs)
ppc_md.heartbeat(); ppc_md.heartbeat();
irq_exit(); irq_exit();
if (softirq_pending(cpu))
do_softirq();
return 1; /* lets ret_from_int know we can do checks */
} }
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
......
...@@ -42,7 +42,7 @@ extern void __no_lpq_restore_flags(unsigned long flags); ...@@ -42,7 +42,7 @@ extern void __no_lpq_restore_flags(unsigned long flags);
extern void iSeries_smp_message_recv( struct pt_regs * ); extern void iSeries_smp_message_recv( struct pt_regs * );
unsigned lpEvent_count = 0; unsigned lpEvent_count = 0;
int do_IRQ(struct pt_regs *regs) void do_IRQ(struct pt_regs *regs)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
unsigned long flags; unsigned long flags;
...@@ -65,8 +65,7 @@ int do_IRQ(struct pt_regs *regs) ...@@ -65,8 +65,7 @@ int do_IRQ(struct pt_regs *regs)
lpq = paca->lpQueuePtr; lpq = paca->lpQueuePtr;
if ( lpq ) { if ( lpq ) {
local_save_flags( flags ); local_irq_save(flags);
local_irq_disable();
lpEvent_count += ItLpQueue_process( lpq, regs ); lpEvent_count += ItLpQueue_process( lpq, regs );
local_irq_restore( flags ); local_irq_restore( flags );
} }
...@@ -78,8 +77,4 @@ int do_IRQ(struct pt_regs *regs) ...@@ -78,8 +77,4 @@ int do_IRQ(struct pt_regs *regs)
/* Signal a fake decrementer interrupt */ /* Signal a fake decrementer interrupt */
timer_interrupt( regs ); timer_interrupt( regs );
} }
if (softirq_pending(cpu))
do_softirq();
return 1; /* lets ret_from_int know we can do checks */
} }
...@@ -102,7 +102,7 @@ int timerRetEnabled = 0; ...@@ -102,7 +102,7 @@ int timerRetEnabled = 0;
int timerRetDisabled = 0; int timerRetDisabled = 0;
extern unsigned long iSeries_dec_value; extern unsigned long iSeries_dec_value;
int timer_interrupt(struct pt_regs * regs) void timer_interrupt(struct pt_regs * regs)
{ {
long next_dec; long next_dec;
struct Paca * paca; struct Paca * paca;
...@@ -150,8 +150,4 @@ int timer_interrupt(struct pt_regs * regs) ...@@ -150,8 +150,4 @@ int timer_interrupt(struct pt_regs * regs)
set_dec( (unsigned)next_dec ); set_dec( (unsigned)next_dec );
irq_exit(); irq_exit();
if (softirq_pending(cpu))
do_softirq();
return 1;
} }
...@@ -24,25 +24,86 @@ typedef struct { ...@@ -24,25 +24,86 @@ typedef struct {
#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp) #define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
#define IRQ_OFFSET 64 /*
* We put the hardirq and softirq counter into the preemption
* counter. The bitmask has the following meaning:
*
* - bits 0-7 are the preemption count (max preemption depth: 256)
* - bits 8-15 are the softirq count (max # of softirqs: 256)
* - bits 16-23 are the hardirq count (max # of hardirqs: 256)
*
* - ( bit 26 is the PREEMPT_ACTIVE flag. )
*
* PREEMPT_MASK: 0x000000ff
* HARDIRQ_MASK: 0x0000ff00
* SOFTIRQ_MASK: 0x00ff0000
*/
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
#define HARDIRQ_BITS 8
#define PREEMPT_SHIFT 0
#define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
#define __MASK(x) ((1UL << (x))-1)
#define PREEMPT_MASK (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
#define HARDIRQ_MASK (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define SOFTIRQ_MASK (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
/* /*
* Are we in an interrupt context? Either doing bottom half * The hardirq mask has to be large enough to have
* or hardware interrupt processing? * space for potentially all IRQ sources in the system
* nesting on a single CPU:
*/ */
#define in_interrupt() ((preempt_count() & ~PREEMPT_ACTIVE) >= IRQ_OFFSET) #if (1 << HARDIRQ_BITS) < NR_IRQS
#define in_irq in_interrupt # error HARDIRQ_BITS is too low!
#endif
#define irq_enter() (preempt_count() += IRQ_OFFSET) /*
#define irq_exit() (preempt_count() -= IRQ_OFFSET) * Are we doing bottom half or hardware interrupt processing?
* Are we in a softirq context? Interrupt context?
*/
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#ifndef CONFIG_SMP
#define synchronize_irq(irq) barrier()
#else /* CONFIG_SMP */ #define hardirq_trylock() (!in_interrupt())
extern void synchronize_irq(unsigned int irq); #define hardirq_endlock() do { } while (0)
#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
#if CONFIG_PREEMPT
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
#define irq_exit() \
do { \
preempt_count() -= IRQ_EXIT_OFFSET; \
if (!in_interrupt() && softirq_pending(smp_processor_id())) \
do_softirq(); \
preempt_enable_no_resched(); \
} while (0)
#ifndef CONFIG_SMP
# define synchronize_irq(irq) barrier()
#else
extern void synchronize_irq(unsigned int irq);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
extern void show_stack(unsigned long *sp);
#endif /* __ASM_HARDIRQ_H */ #endif /* __ASM_HARDIRQ_H */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
...@@ -8,21 +8,18 @@ ...@@ -8,21 +8,18 @@
#ifndef _PPC_HW_IRQ_H #ifndef _PPC_HW_IRQ_H
#define _PPC_HW_IRQ_H #define _PPC_HW_IRQ_H
extern unsigned long timer_interrupt_intercept; extern void timer_interrupt(struct pt_regs *);
extern unsigned long do_IRQ_intercept;
extern int timer_interrupt(struct pt_regs *);
extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
#define INLINE_IRQS #define INLINE_IRQS
#ifdef INLINE_IRQS
#define mfmsr() ({unsigned int rval; \ #define mfmsr() ({unsigned int rval; \
asm volatile("mfmsr %0" : "=r" (rval)); rval;}) asm volatile("mfmsr %0" : "=r" (rval)); rval;})
#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v)) #define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
#define local_save_flags(flags) ((flags) = mfmsr()) #define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
#define local_irq_restore(flags) mtmsr(flags)
#ifdef INLINE_IRQS
static inline void local_irq_disable(void) static inline void local_irq_disable(void)
{ {
...@@ -40,7 +37,7 @@ static inline void local_irq_enable(void) ...@@ -40,7 +37,7 @@ static inline void local_irq_enable(void)
mtmsr(msr | MSR_EE); mtmsr(msr | MSR_EE);
} }
static inline void __do_save_and_cli(unsigned long *flags) static inline void local_irq_save_ptr(unsigned long *flags)
{ {
unsigned long msr; unsigned long msr;
msr = mfmsr(); msr = mfmsr();
...@@ -49,7 +46,9 @@ static inline void __do_save_and_cli(unsigned long *flags) ...@@ -49,7 +46,9 @@ static inline void __do_save_and_cli(unsigned long *flags)
__asm__ __volatile__("": : :"memory"); __asm__ __volatile__("": : :"memory");
} }
#define local_irq_save(flags) __do_save_and_cli(&flags) #define local_save_flags(flags) ((flags) = mfmsr())
#define local_irq_save(flags) local_irq_save_ptr(&flags)
#define local_irq_restore(flags) mtmsr(flags)
#else #else
...@@ -57,9 +56,8 @@ extern void local_irq_enable(void); ...@@ -57,9 +56,8 @@ extern void local_irq_enable(void);
extern void local_irq_disable(void); extern void local_irq_disable(void);
extern void local_irq_restore(unsigned long); extern void local_irq_restore(unsigned long);
extern void local_save_flags_ptr(unsigned long *); extern void local_save_flags_ptr(unsigned long *);
extern unsigned long local_irq_enable_end, local_irq_disable_end, local_irq_restore_end, local_save_flags_ptr_end;
#define local_save_flags(flags) local_save_flags_ptr((unsigned long *)&flags) #define local_save_flags(flags) local_save_flags_ptr(&flags)
#define local_irq_save(flags) ({local_save_flags(flags);local_irq_disable();}) #define local_irq_save(flags) ({local_save_flags(flags);local_irq_disable();})
#endif #endif
......
...@@ -5,32 +5,30 @@ ...@@ -5,32 +5,30 @@
#ifndef __ASM_SOFTIRQ_H #ifndef __ASM_SOFTIRQ_H
#define __ASM_SOFTIRQ_H #define __ASM_SOFTIRQ_H
#include <asm/atomic.h> #include <linux/preempt.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#define local_bh_disable() \ #define local_bh_disable() \
do { \ do { \
preempt_count() += IRQ_OFFSET; \ preempt_count() += SOFTIRQ_OFFSET; \
barrier(); \ barrier(); \
} while (0) } while (0)
#define __local_bh_enable() \ #define __local_bh_enable() \
do { \ do { \
barrier(); \ barrier(); \
preempt_count() -= IRQ_OFFSET; \ preempt_count() -= SOFTIRQ_OFFSET; \
} while (0) } while (0)
#define local_bh_enable() \ #define local_bh_enable() \
do { \ do { \
barrier(); \ __local_bh_enable(); \
if ((preempt_count() -= IRQ_OFFSET) < IRQ_OFFSET \ if (unlikely(!in_interrupt() \
&& softirq_pending(smp_processor_id())) \ && softirq_pending(smp_processor_id()))) \
do_softirq(); \ do_softirq(); \
if (preempt_count() == 0) \ if (preempt_count() == 0) \
preempt_check_resched(); \ preempt_check_resched(); \
} while (0) } while (0)
#define in_softirq() in_interrupt()
#endif /* __ASM_SOFTIRQ_H */ #endif /* __ASM_SOFTIRQ_H */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
...@@ -96,19 +96,6 @@ extern unsigned int rtas_data; ...@@ -96,19 +96,6 @@ extern unsigned int rtas_data;
struct pt_regs; struct pt_regs;
extern void dump_regs(struct pt_regs *); extern void dump_regs(struct pt_regs *);
#ifndef CONFIG_SMP
/*
* Compatibility macros, to be removed in future...
*/
#define cli() local_irq_disable()
#define sti() local_irq_enable()
#define save_flags(flags) local_save_flags(flags)
#define restore_flags(flags) local_irq_restore(flags)
#define save_and_cli(flags) local_irq_save(flags)
#endif /* !CONFIG_SMP */
static __inline__ unsigned long static __inline__ unsigned long
xchg_u32(volatile void *p, unsigned long val) xchg_u32(volatile void *p, unsigned long val)
{ {
......
...@@ -22,25 +22,25 @@ struct thread_info { ...@@ -22,25 +22,25 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */ int cpu; /* cpu we're on */
int preempt_count; /* not used at present */ int preempt_count;
int softirq_count;
int hardirq_count;
}; };
/*
* macros/functions for gaining access to the thread information structure
*/
#define INIT_THREAD_INFO(tsk) \ #define INIT_THREAD_INFO(tsk) \
{ \ { \
task: &tsk, \ .task = &tsk, \
exec_domain: &default_exec_domain, \ .exec_domain = &default_exec_domain, \
flags: 0, \ .flags = 0, \
cpu: 0, \ .cpu = 0, \
.preempt_count = 1 \
} }
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack) #define init_stack (init_thread_union.stack)
/*
* macros/functions for gaining access to the thread information structure
*/
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void) static inline struct thread_info *current_thread_info(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