local_irq_disable与irq_disable的本质是将本cpu的cpsr寄存器中的I(第7)bit置1,用来屏蔽当前CPU上的所有中断,通过操作arm核心中的寄存器来屏蔽到达CPU上的中断,此时中断控制器中所有送往该CPU上的中断信号都将被忽略。
disable_irq在全局范围内屏蔽某一个中断号(irq num)。该irq num对应的irq handler不会在任何一个CPU上执行。这个操作是通过设置中断控制器中的寄存器来对指定中断进行屏蔽,而其他未屏蔽的中断依然可以正常送往CPU。(这篇文章分析的很详细:http://blog.csdn.net/rikeyone/article/details/51554868)
1.local_irq_disable
#define local_irq_enable() do { raw_local_irq_enable(); } while (0)
#define local_irq_disable() do { raw_local_irq_disable(); } while (0)
#define raw_local_irq_disable() arch_local_irq_disable()
#define raw_local_irq_enable() arch_local_irq_enable()
#define local_fiq_enable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ stf\n" \
" bic %0, %0, #64\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
/*
* Disable FIQs
*/
#define local_fiq_disable() \
({ \
unsigned long temp; \
__asm__ __volatile__( \
"mrs %0, cpsr @ clf\n" \
" orr %0, %0, #64\n" \
" msr cpsr_c, %0" \
: "=r" (temp) \
: \
: "memory", "cc"); \
})
2’.irqs_disabled
#define irqs_disabled() (raw_irqs_disabled())
#define raw_irqs_disabled() (arch_irqs_disabled())
static inline int arch_irqs_disabled(void)
{
return arch_irqs_disabled_flags(arch_local_save_flags());
}
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return flags & PSR_I_BIT;
}
static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
asm volatile(
" mrs %0, cpsr @ local_save_flags"
: "=r" (flags) : : "memory", "cc");
return flags;
}
3.disable_irq
这里我们不需要完全看懂这个函数 ,我们看到这个函数里面有msi_desc数据结构。msi是arm 内部外设的范畴。而arm中中断控制有一部份工作就是在arm内部外设msi中完成的。如关闭某个中断线,或设置中断线优先级等等。这个函数我猜应该就是通过控制msi中的寄存器来完成屏蔽某个中断线的。
void disable_irq(unsigned int irq)
{
struct msi_desc *msi = irq_get_msi_desc(irq);
zpci_msi_set_mask_bits(msi, 1, 1);
}