本节以hisi_sas驱动(drivers/scsi/hisi_sas/hisi_sas_v3_hw.c)的PCIE MSI中断为例,讲叙LPI中断的中断应用实例。
在开始之前再次对LPI中断的产生作介绍。当外设写GITS_TRANSLATER时,ITS将根据device id和event id将中断路由到特定的GICR上,最后发送到对应的GICC上。
1 中断的分配
hisi_sas驱动采用函数pci_alloc_irq_vectors()分配中断,这里分成两种情况:MSI中断和MSIX中断。这里我们只关注MSI中断。
对于MSI情况,具体执行情况如下:
步骤如下:
- 通过函数pci_msi_vec_count()从PCI_MSI_FLAGS读取MSI中断数目;
- 对于设置亲和性的情况,通过irq_calc_affinity_vectors()计算中断的亲和性;
- 通过函数pci_msi_enable(dev, 0)禁用MSI中断;
- 通过函数irq_create_affinity_mask()创建亲和性mask;
- 分配msi_desc,并根据eventid插入;
- 调用ops->msi_prepare()接口,对于ITS来说,分配its_device,建立device table表项(即执行MAPD命令);
- 调用函数__irq_domain_alloc_irqs()分配分配nr_vector个虚中断virq,这是中断分配的通用流程(实际上分配并映射虚拟中断,调用ops->alloc()设置irq_chip和中断处理函数);
- 对每个中断,调用ops->activate()接口对中断进行激活,对于ITS来说,激活中断,在ITT中建立deviceid/eventid与ite的映射(即执行MAPTI命令)。
2 中断请求及处理
hisi_sas驱动调用函数requeste_threaded_irq()申请中断并设置回调函数。该过程在GIC/ITS代码分析(4)中断的分配/映射及注册 已作详细介绍。
LPI中断的处理由中断异常发起,最终由函数handle_fasteoi_irq()进行处理,执行驱动注册的回调函数。详细过程见GIC/ITS代码分析(6)中断处理 。