2005-04-16 15:20:36 -07:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 1994 , 95 , 96 , 97 , 98 , 99 , 2003 by Ralf Baechle
* Copyright ( C ) 1996 by Paul M . Antoine
* Copyright ( C ) 1999 Silicon Graphics
* Copyright ( C ) 2000 MIPS Technologies , Inc .
*/
2006-07-07 14:07:18 +01:00
# ifndef _ASM_IRQFLAGS_H
# define _ASM_IRQFLAGS_H
# ifndef __ASSEMBLY__
2005-04-16 15:20:36 -07:00
2007-03-29 23:42:42 +01:00
# include <linux/compiler.h>
2013-02-08 18:13:30 +01:00
# include <linux/stringify.h>
2005-04-16 15:20:36 -07:00
# include <asm/hazards.h>
2012-09-06 11:36:56 -04:00
# if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
2005-04-16 15:20:36 -07:00
2013-02-08 18:13:30 +01:00
static inline void arch_local_irq_disable ( void )
{
__asm__ __volatile__ (
2005-07-12 14:54:31 +00:00
" .set push \n "
" .set noat \n "
" di \n "
2013-02-08 18:13:30 +01:00
" " __stringify ( __irq_disable_hazard ) " \n "
2005-07-12 14:54:31 +00:00
" .set pop \n "
2013-02-08 18:13:30 +01:00
: /* no outputs */
: /* no inputs */
: " memory " ) ;
2005-04-16 15:20:36 -07:00
}
2013-02-08 18:13:30 +01:00
static inline unsigned long arch_local_irq_save ( void )
{
unsigned long flags ;
2005-04-16 15:20:36 -07:00
2013-02-08 18:13:30 +01:00
asm __volatile__ (
2005-07-12 14:54:31 +00:00
" .set push \n "
" .set reorder \n "
" .set noat \n "
2013-02-08 18:13:30 +01:00
" di %[flags] \n "
" andi %[flags], 1 \n "
" " __stringify ( __irq_disable_hazard ) " \n "
2005-07-12 14:54:31 +00:00
" .set pop \n "
2013-02-08 18:13:30 +01:00
: [ flags ] " =r " ( flags )
: /* no inputs */
: " memory " ) ;
2005-04-16 15:20:36 -07:00
2010-10-07 14:08:55 +01:00
return flags ;
}
2005-04-16 15:20:36 -07:00
2013-02-08 18:13:30 +01:00
static inline void arch_local_irq_restore ( unsigned long flags )
{
unsigned long __tmp1 ;
2012-09-06 11:36:56 -04:00
2013-02-08 18:13:30 +01:00
__asm__ __volatile__ (
2006-01-30 16:48:26 +00:00
" .set push \n "
2005-07-12 14:54:31 +00:00
" .set noreorder \n "
" .set noat \n "
2012-09-06 11:36:56 -04:00
# if defined(CONFIG_IRQ_CPU)
2005-07-12 14:54:31 +00:00
/*
2011-03-30 22:57:33 -03:00
* Slow , but doesn ' t suffer from a relatively unlikely race
2005-07-12 14:54:31 +00:00
* condition we ' re having since days 1.
*/
2013-02-08 18:13:30 +01:00
" beqz %[flags], 1f \n "
2012-09-06 11:36:56 -04:00
" di \n "
2005-07-12 14:54:31 +00:00
" ei \n "
" 1: \n "
2012-09-06 11:36:56 -04:00
# else
2005-07-12 14:54:31 +00:00
/*
* Fast , dangerous . Life is fun , life is good .
*/
" mfc0 $1, $12 \n "
2013-02-08 18:13:30 +01:00
" ins $1, %[flags], 0, 1 \n "
2005-07-12 14:54:31 +00:00
" mtc0 $1, $12 \n "
# endif
2013-02-08 18:13:30 +01:00
" " __stringify ( __irq_disable_hazard ) " \n "
2006-01-30 16:48:26 +00:00
" .set pop \n "
2013-02-08 18:13:30 +01:00
: [ flags ] " =r " ( __tmp1 )
: " 0 " ( flags )
: " memory " ) ;
2007-03-29 23:42:42 +01:00
}
2005-04-16 15:20:36 -07:00
2010-10-07 14:08:55 +01:00
static inline void __arch_local_irq_restore ( unsigned long flags )
2008-09-09 21:48:52 +02:00
{
__asm__ __volatile__ (
2013-02-08 18:13:30 +01:00
" .set push \n "
" .set noreorder \n "
" .set noat \n "
# if defined(CONFIG_IRQ_CPU)
/*
* Slow , but doesn ' t suffer from a relatively unlikely race
* condition we ' re having since days 1.
*/
" beqz %[flags], 1f \n "
" di \n "
" ei \n "
" 1: \n "
# else
/*
* Fast , dangerous . Life is fun , life is good .
*/
" mfc0 $1, $12 \n "
" ins $1, %[flags], 0, 1 \n "
" mtc0 $1, $12 \n "
# endif
" " __stringify ( __irq_disable_hazard ) " \n "
" .set pop \n "
: [ flags ] " =r " ( flags )
: " 0 " ( flags )
: " memory " ) ;
2008-09-09 21:48:52 +02:00
}
2012-09-06 11:36:56 -04:00
# else
/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
void arch_local_irq_disable ( void ) ;
unsigned long arch_local_irq_save ( void ) ;
void arch_local_irq_restore ( unsigned long flags ) ;
void __arch_local_irq_restore ( unsigned long flags ) ;
# endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
2013-02-08 18:13:30 +01:00
extern void smtc_ipi_replay ( void ) ;
static inline void arch_local_irq_enable ( void )
{
# ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC kernel needs to do a software replay of queued
* IPIs , at the cost of call overhead on each local_irq_enable ( )
*/
smtc_ipi_replay ( ) ;
# endif
__asm__ __volatile__ (
2012-09-06 11:36:56 -04:00
" .set push \n "
" .set reorder \n "
" .set noat \n "
# ifdef CONFIG_MIPS_MT_SMTC
" mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n "
" ori $1, 0x400 \n "
" xori $1, 0x400 \n "
" mtc0 $1, $2, 1 \n "
# elif defined(CONFIG_CPU_MIPSR2)
" ei \n "
# else
" mfc0 $1,$12 \n "
" ori $1,0x1f \n "
" xori $1,0x1e \n "
" mtc0 $1,$12 \n "
# endif
2013-02-08 18:13:30 +01:00
" " __stringify ( __irq_enable_hazard ) " \n "
2012-09-06 11:36:56 -04:00
" .set pop \n "
2013-02-08 18:13:30 +01:00
: /* no outputs */
: /* no inputs */
: " memory " ) ;
2012-09-06 11:36:56 -04:00
}
2013-02-08 18:13:30 +01:00
static inline unsigned long arch_local_save_flags ( void )
{
unsigned long flags ;
2012-09-06 11:36:56 -04:00
2013-02-08 18:13:30 +01:00
asm __volatile__ (
2012-09-06 11:36:56 -04:00
" .set push \n "
" .set reorder \n "
# ifdef CONFIG_MIPS_MT_SMTC
2013-02-08 18:13:30 +01:00
" mfc0 %[flags], $2, 1 \n "
2012-09-06 11:36:56 -04:00
# else
2013-02-08 18:13:30 +01:00
" mfc0 %[flags], $12 \n "
2012-09-06 11:36:56 -04:00
# endif
" .set pop \n "
2013-02-08 18:13:30 +01:00
: [ flags ] " =r " ( flags ) ) ;
2012-09-06 11:36:56 -04:00
return flags ;
}
2008-09-09 21:48:52 +02:00
2010-10-07 14:08:55 +01:00
static inline int arch_irqs_disabled_flags ( unsigned long flags )
2006-04-05 09:45:45 +01:00
{
# ifdef CONFIG_MIPS_MT_SMTC
/*
* SMTC model uses TCStatus . IXMT to disable interrupts for a thread / CPU
*/
2006-07-07 14:07:18 +01:00
return flags & 0x400 ;
2006-04-05 09:45:45 +01:00
# else
return ! ( flags & 1 ) ;
# endif
}
2005-04-16 15:20:36 -07:00
2012-09-06 11:36:56 -04:00
# endif /* #ifndef __ASSEMBLY__ */
2006-07-07 14:07:18 +01:00
/*
* Do the CPU ' s IRQ - state tracing from assembly code .
*/
# ifdef CONFIG_TRACE_IRQFLAGS
2006-09-26 23:43:40 +09:00
/* Reload some registers clobbered by trace_hardirqs_on */
# ifdef CONFIG_64BIT
# define TRACE_IRQS_RELOAD_REGS \
LONG_L $ 11 , PT_R11 ( sp ) ; \
LONG_L $ 10 , PT_R10 ( sp ) ; \
LONG_L $ 9 , PT_R9 ( sp ) ; \
LONG_L $ 8 , PT_R8 ( sp ) ; \
LONG_L $ 7 , PT_R7 ( sp ) ; \
LONG_L $ 6 , PT_R6 ( sp ) ; \
LONG_L $ 5 , PT_R5 ( sp ) ; \
LONG_L $ 4 , PT_R4 ( sp ) ; \
LONG_L $ 2 , PT_R2 ( sp )
# else
# define TRACE_IRQS_RELOAD_REGS \
LONG_L $ 7 , PT_R7 ( sp ) ; \
LONG_L $ 6 , PT_R6 ( sp ) ; \
LONG_L $ 5 , PT_R5 ( sp ) ; \
LONG_L $ 4 , PT_R4 ( sp ) ; \
LONG_L $ 2 , PT_R2 ( sp )
# endif
2006-07-07 14:07:18 +01:00
# define TRACE_IRQS_ON \
2006-09-26 23:43:40 +09:00
CLI ; /* make sure trace_hardirqs_on() is called in kernel level */ \
2006-07-07 14:07:18 +01:00
jal trace_hardirqs_on
2006-09-26 23:43:40 +09:00
# define TRACE_IRQS_ON_RELOAD \
TRACE_IRQS_ON ; \
TRACE_IRQS_RELOAD_REGS
2006-07-07 14:07:18 +01:00
# define TRACE_IRQS_OFF \
jal trace_hardirqs_off
# else
# define TRACE_IRQS_ON
2006-09-26 23:43:40 +09:00
# define TRACE_IRQS_ON_RELOAD
2006-07-07 14:07:18 +01:00
# define TRACE_IRQS_OFF
# endif
# endif /* _ASM_IRQFLAGS_H */