主机侧初始化
msi-map = <0x0 &its 0x0 0x1000>;
设备侧获取软件中断号
设备驱动调用如下函数获取软件中断号.因为是pci设备,所以不能从设备树中获取硬件中断号.
pci_enable_msix_range
申请软件中断号,申请好了,会填充entry 参数的 vector 成员 为软件中断号
驱动可能会调用如下函数来获取MSI/MSI-X软件中断号,最终都会调用到 __pci_enable_msix_range
pci_alloc_irq_vectors
pci_alloc_irq_vectors_affinity
pci_enable_msix_range
pci_enable_msi
__pci_enable_msix_range->__pci_enable_msix->msix_capability_init->
pci_msi_setup_msi_irqs
msi_domain_alloc_irqs
ops->domain_alloc_irqs/__msi_domain_alloc_irqs
msi_domain_prepare_irqs
ops->msi_prepare/its_pci_msi_prepare
info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);
msi_info->ops->msi_prepare/its_msi_prepare
dev_id = info->scratchpad[0].ul
its_dev = its_create_device(its, dev_id, nvec, true);
its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
dev->event_map.lpi_base = lpi_base;
dev->event_map.nr_lpis = nr_lpis;
its_send_mapd(dev, 1);
for_each_msi_entry(desc, dev)
__irq_domain_alloc_irqs
virq = irq_domain_alloc_descs
irq_domain_alloc_irqs_hierarchy
domain->ops->alloc/its_irq_domain_alloc
its_alloc_device_irq
idx = bitmap_find_free_region(...);
*hwirq = dev->event_map.lpi_base + idx;
for (i = 0; i < nr_irqs; i++) {
its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, &its_irq_chip, its_dev);
irq_data->hwirq = hwirq;
}
for_each_msi_vector(desc, i, dev)
irq_domain_activate_irq
__irq_domain_activate_irq
domain->ops->activate/msi_domain_activate
irq_chip_compose_msi_msg
pos->chip->irq_compose_msi_msg /its_irq_compose_msi_msg
irq_chip_write_msi_msg(irq_data, msg)
data->chip->irq_write_msi_msg /pci_msi_domain_write_msg
irq-gic-v3-its.c 提供了
1. static const struct irq_domain_ops its_domain_ops
2. struct irq_chip its_irq_chip.its_irq_compose_msi_msg
3. struct msi_domain_ops its_msi_domain_ops.msi_prepare
irq-gic-v3-its-pci-msi.c 提供了
1. static struct msi_domain_ops its_pci_msi_ops.msi_prepare
2. static struct irq_chip its_msi_irq_chip.irq_write_msi_msg
plic-sw 或者其msi节点需要提供irq-gic-v3-its.c 中的内容
1. msi_prepare
2. 组 <addr,value>
plic-sw-pci-msi.c 需要提供 irq-gic-v3-its-pci-msi.c 的内容
1. msi_prepare
2. irq_write_msi_msg
设备访问 中断信息, 并发生中断的过程要不要 设置 inbound
cdns_pcie_host_bar_ib_config
Linux PCIe 启动流程
1. PCIe控制器初始化过程
0. 准备配置空间,做outbound配置
1. 枚举 pcie 设备
2.1. 为设备准备内存
读写BAR0,获取需求内存大小.
写 BAR0 为 PCIe地址,做outbound设置(映射物理地址到pcie地址,并多给1KB)
2.2. 为设备准备中断
从 设备配置空间 cap 0x11 中读取到他需要M(Table Size+1)个 msi-x 中断
解析 pcie 节点的 msi-map,从 LPI 中获取对应的M个硬件中断号
填充cap msi-x 的 Table offset/Table BIR ,offset 到 预留的1KB
填充cap msi-x 的 PBA offset/PBA BIR ,offset 到 预留的1KB
2. 构造 pci_dev 结构体
3.1 填充 pci_dev 结构体变量的 irq 成员
3.2 填充 pci_dev 结构体变量的 mem 相关成员
3.3 调用 pci_device_register 注册 pci_dev 结构体变量 到 pci总线 设备链表
2. PCIe设备初始化过程
1. 内存设置
获取到设备内存并映射物理内存到虚拟地址
2. 中断设置
1.地址值对设置
构造M个 <addr,val> 对
将 M个 <addr,val> 对 写入 内存.内存基址由 cap msi-x 的 Table offset/Table BIR 指定
将<addr,val>中的地址做inbound设置,做 Bus Master Enable
2. 申请软件中断号
从bitmap 中获取 软件中断号,然后alloc irq_desc , 并填充 handler 进 irq_action 链表
3.MSI-X Enable 及 开启层层开关
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)