1 中断号与硬件相关_号码固定
当我们的系统中只有一两个中断控制器时,上面的方法很有用,可以给每一个中断预先确定好他的虚拟中断号,但是当中断控制器越来越多、当中断越来越多,上述方法(virq和hwirq固定绑定)有缺陷:
a. 增加工作量, 你需要给每一个中断确定它的中断号, 写出对应的宏, 可能有成百上千个
b. 你要确保每一个硬件中断对应的中断号互不重复
2 中断号与硬件无关_号码随机
那有什么方法可以改进上面的缺陷吗,方法就是把虚拟中断号和硬件中断号之间的固定联系给取消掉,当我想使用某一个硬件中断时,我来查找irq_desc数组,在这个数组中查找一个空缺的项,这个空缺项的位置就是这个硬件中断的虚拟中断号,我们在这个数组项里面放这个中断的处理函数,
怎么在数组中查找出空余项呢,最笨的方法就是我每次都从最左边开始一个一个的判断,这种方法效率太低了,内核不会使用这种方法,内核中有一个位图allocated_irqs,它里面的每一位就对应着irq_desc数组的每一项,当某一位等于1表示被占用,假如我们要是用硬件终端2,那我们就从位图的第2位开始查找,然后依次查找bit3 4 5,直到找到空闲位,则找到了虚拟中断号,那么虚拟中断号需要保存下来,这个虚拟中断号保存在irq_domain结构体的linear_revmap数组里面,
新中断体系中, 怎么使用中断:
a.以前是request_irq发起,
现在是先在设备树文件中声明想使用哪一个中断(哪一个中断控制器下的哪一个中断)
b. 内核解析设备树时,
会根据"中断控制器"确定irq_domain,
根据"哪一个中断"确定hwirq,
然后在irq_desc数组中找出一个空闲项, 它的位置就是virq
并且把virq和hwirq的关系保存在irq_domain中: irq_domain.linear_revmap[hwirq] = virq;
c. 驱动程序 request_irq(virq, my_handler)
d. 发生硬件中断时,
内核读取硬件信息, 确定hwirq, 确定 virq = irq_domain.linear_revmap[hwirq];
然后调用 irq_desc[virq].handle_irq, 最终会用到my_handler
假设要使用子中断控制器(subintc)的n号中断, 它发生时会导致父中断控制器(intc)的m号中断:
a. 设备树表明要使用<subintc n>
subintc表示要使用<intc m>
b. 解析设备树时,
会为<subintc n>找到空闲项 irq_desc[virq'], sub irq_domain.linear_revmap[n] = virq';
会为<intc m> 找到空闲项 irq_desc[virq], irq_domain.linear_revmap[m] = virq;
并且设置它的handle_irq为某个分析函数demux_func
c. 驱动程序 request_irq(virq', my_handler)
d. 发生硬件中断时,
内核读取intc硬件信息, 确定hwirq = m, 确定 virq = irq_domain.linear_revmap[m];
然后调用 irq_desc[m].handle_irq, 即demux_func
e. demux_func:
读取sub intc硬件信息, 确定hwirq = n, 确定 virq' = sub irq_domain.linear_revmap[n];
然后调用 irq_desc[n].handle_irq, 即my_handler