在很多驱动文件中可以发现,在request_thread_irq调用以后,probe函数里并没有显示的调用enable_irq。对于我们来说,要确认的一点的是,没有enable_irq的话,中断函数是不会被调用的。细细看下代码,只有request_thread_irq即在申请中断的时候,中断核心是不是会帮忙做了这件事呢?
从 request_thread_irq追到__setup_irq函数。在函数里可以看到下面的代码:
if(irq_setting_can_autoenable(desc))
irq_startup(desc, true);
else
desc->depth = 1;
1.irq_setting_can_autoenable
这个函数作为判断条件,追进去可以看到逻辑非常简单
static inline bool irq_setting_can_autoenable(struct irq_desc *desc)
{
return !(desc->status_use_accessors & _IRQ_NOAUTOEN);
}
如果我们手动设置了IRQ_NOAUTOEN,那么这里的返回值为false。如果没设置,返回true。
2.irq_startup(desc, true)
这个代码往下的具体实现我在代码没有实际找到,逻辑是如果chip有提供irq_startup回调那么调用它,否则会调用irq_enable。
irq_enable也是如此,调用chip提供的irq_enable回调。
3.我们常用的接口enable_irq实际是对__enable_irq的封装,内部逻辑如下:
desc会有一个count值叫做desc->depth,理论上调用一次disable_irq,这个值会加1,相反调用enable_irq会减1。
对于enable_irq来说,这里有两种特殊情况:
一个是depth为0的情况下调用enable_irq,会通过WARN输出警报,这个状态下不应该有enable_irq被调用。
一个是depth为1的情况下调用enable_irq,这个状态下本来应该处于disable状态,需要实际的打开这个中断。这里调用的也是irq_enable这个函数。
验证一个问题:
1.request_thread_irq如果帮我们打开了中断,我们在probe里再次enable_irq会产生什么效果?
实验发现在probe里加了enable_irq会导致WARN的输出,证明了确实是由request_thread_irq帮忙打开了中断