diff options
Diffstat (limited to 'arch/powerpc/include/asm/hw_irq.h')
| -rw-r--r-- | arch/powerpc/include/asm/hw_irq.h | 82 | 
1 files changed, 71 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index ff08b70b36d..10be1dd01c6 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -11,7 +11,31 @@  #include <asm/ptrace.h>  #include <asm/processor.h> +#ifdef CONFIG_PPC64 + +/* + * PACA flags in paca->irq_happened. + * + * This bits are set when interrupts occur while soft-disabled + * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS + * is set whenever we manually hard disable. + */ +#define PACA_IRQ_HARD_DIS	0x01 +#define PACA_IRQ_DBELL		0x02 +#define PACA_IRQ_EE		0x04 +#define PACA_IRQ_DEC		0x08 /* Or FIT */ +#define PACA_IRQ_EE_EDGE	0x10 /* BookE only */ + +#endif /* CONFIG_PPC64 */ + +#ifndef __ASSEMBLY__ + +extern void __replay_interrupt(unsigned int vector); +  extern void timer_interrupt(struct pt_regs *); +extern void performance_monitor_exception(struct pt_regs *regs); +extern void WatchdogException(struct pt_regs *regs); +extern void unknown_exception(struct pt_regs *regs);  #ifdef CONFIG_PPC64  #include <asm/paca.h> @@ -42,7 +66,6 @@ static inline unsigned long arch_local_irq_disable(void)  }  extern void arch_local_irq_restore(unsigned long); -extern void iseries_handle_interrupts(void);  static inline void arch_local_irq_enable(void)  { @@ -65,19 +88,46 @@ static inline bool arch_irqs_disabled(void)  }  #ifdef CONFIG_PPC_BOOK3E -#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory"); -#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory"); +#define __hard_irq_enable()	asm volatile("wrteei 1" : : : "memory") +#define __hard_irq_disable()	asm volatile("wrteei 0" : : : "memory")  #else -#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1) -#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1) +#define __hard_irq_enable()	__mtmsrd(local_paca->kernel_msr | MSR_EE, 1) +#define __hard_irq_disable()	__mtmsrd(local_paca->kernel_msr, 1)  #endif -#define  hard_irq_disable()			\ -	do {					\ -		__hard_irq_disable();		\ -		get_paca()->soft_enabled = 0;	\ -		get_paca()->hard_enabled = 0;	\ -	} while(0) +#define hard_irq_disable()	do {			\ +	u8 _was_enabled;				\ +	__hard_irq_disable();				\ +	_was_enabled = local_paca->soft_enabled;	\ +	local_paca->soft_enabled = 0;			\ +	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;	\ +	if (_was_enabled)				\ +		trace_hardirqs_off();			\ +} while(0) + +static inline bool lazy_irq_pending(void) +{ +	return !!(get_paca()->irq_happened & ~PACA_IRQ_HARD_DIS); +} + +/* + * This is called by asynchronous interrupts to conditionally + * re-enable hard interrupts when soft-disabled after having + * cleared the source of the interrupt + */ +static inline void may_hard_irq_enable(void) +{ +	get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS; +	if (!(get_paca()->irq_happened & PACA_IRQ_EE)) +		__hard_irq_enable(); +} + +static inline bool arch_irq_disabled_regs(struct pt_regs *regs) +{ +	return !regs->softe; +} + +extern bool prep_irq_for_idle(void);  #else /* CONFIG_PPC64 */ @@ -139,13 +189,23 @@ static inline bool arch_irqs_disabled(void)  #define hard_irq_disable()		arch_local_irq_disable() +static inline bool arch_irq_disabled_regs(struct pt_regs *regs) +{ +	return !(regs->msr & MSR_EE); +} + +static inline void may_hard_irq_enable(void) { } +  #endif /* CONFIG_PPC64 */ +#define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST +  /*   * interrupt-retrigger: should we handle this via lost interrupts and IPIs   * or should we not care like we do now ? --BenH.   */  struct irq_chip; +#endif  /* __ASSEMBLY__ */  #endif	/* __KERNEL__ */  #endif	/* _ASM_POWERPC_HW_IRQ_H */  | 
