Linux kernel的AER是怎么工作的
在Linux下,AER(Advanced ErrorReport)驱动都是注册给通用的Port Bus Driver,称之为service driver。除了AER,还有热插拔等驱动也是采用类似的注册方式。PICe Port Bus驱动的内容及具体实现我们后面再详细讲。
AER service和其他的PCIe service一样,都是注册给pci port bus driver。Port bus driver会调用aer_probe,aer_probe函数注册了中断服务函数和中断线程,然后调用aer_enable_rootport来使能中断。aer_enable_rootport其实就是清除error status reg,并且使能前面“Error message控制”提到的相关控制寄存器。简而言之,就是把所有该使能的地方都使能起来,确保错误能够正常的上报上去。
中断服务函数aer_irq就是读取AER CAP中的status和source id 寄存器来确定是否产生了AER,收到的第一个错误message的id是多少,把status和id推到fifo中,然后就启动线程。
线程aer_isr从Root Port 开始walk_bus遍历该root port下面的所有PCIe设备,读取设备aer status寄存器和aer mask寄存器,如果status对应bit为1且mask 对应bit为0,则加入struct aer_err_info *e_info的数据结构中等待处理。
由于kernel需要为大多数使用者负责,追求通用性,导致aer的处理乏善可陈,就不在这里介绍了。事实上,这个AER在实际的工程应用中,基本不可用。需要根据客户自己的实际环境,做大量的修改和优化。
AER处理方面,需要考虑产品可靠性要求不同、单板设计不同、芯片在系统中承担的角色等方面,通用性和可靠性不可兼得。Kernel要为所有硬件服务,因此选择了通用性。系统要想提高可靠性,就要适当牺牲通用性。