dpdk源码---vfio(zym)

本文主要探讨了SPDK中从NVMe设备到VFIO驱动的代码路径。通过`spdk_pci_enumerate`和`spdk_pci_device_attach`,核心流程包括`rte_pci_scan`和`rte_pci_probe`,最终涉及`pci_vfio_map_resource`及vfio相关设置。文章详细介绍了相关函数及其调用过程,适合对DPDK和网络设备驱动感兴趣的读者深入学习。
摘要由CSDN通过智能技术生成

主要想找到从nvme设备 到 vfio驱动的代码路径

[spdk/lib/nvme/nvme_pcie.c]

nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,bool direct_connect) (nvme_tcp,nvme_rdma等都有自己的scan,probe等函数,统一被封装起来,如下)

1 int nvme_transport_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
2      bool direct_connect)
3 {
4  NVME_TRANSPORT_CALL(probe_ctx->trid.trtype, ctrlr_scan, (probe_ctx, direct_connect));
5 }

1.nvme_pcie_ctrl_scan:

 1 int
 2 nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
 3              bool direct_connect)
 4 {
 5     .......//若probe_ctx中有指定nvme pci id,has_pci_addr=true
 6     if (enum_ctx.has_pci_addr == false) {
 7         return spdk_pci_enumerate(spdk_pci_nvme_get_driver(),//若没有指定
 8                       pcie_nvme_enum_cb, &enum_ctx);
 9     } else {
10         return spdk_pci_device_attach(spdk_pci_nvme_get_driver(),//指定了话直接attach
11                           pcie_nvme_enum_cb, &enum_ctx, &enum_ctx.pci_addr);
12     }
13 

spdk_pci_enumerate:

 1 int
 2 spdk_pci_enumerate(struct spdk_pci_driver *driver,
 3            spdk_pci_enum_cb enum_cb,
 4            void *enum_ctx)
 5 {
 6     struct spdk_pci_device *dev;
 7     int rc;
 8 
 9     cleanup_pci_devices();
10 
11     pthread_mutex_lock(&g_pci_mutex);
12     TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { //遍历g_pci_devices
13         if (dev->internal.attached ||
14             dev->internal.driver != driver ||
15             dev->internal.pending_removal) {
16             continue;
17         }
18 
19         rc = enum_cb(enum_ctx, dev);// 从g_pci_devices找到我们要的driver,那么调用回调函数进行后续的ctrl_construct工作
20         if (rc == 0) {
21             dev->internal.attached = true;//构建成功,attach设置为true
22         } else if (rc < 0) {
23             pthread_mutex_unlock(&g_pci_mutex);
24             return -1;
25         }
26     }
27     pthread_mutex_unlock(&g_pci_mutex);
28 
29     if (!driver->is_registered) {//若改driver还没注册,那么register到rte_pci_bus.driver_list
30         driver->is_registered = true;
31         rte_pci_register(&driver->driver);
32     }
33 //上面不是找到了吗,下面这些是干啥?为啥要scan和probe??上面只是放到rte_pci_bus.driver_list了,后面还需做什么?
34     driver->cb_fn = enum_cb;
35     driver->cb_arg = enum_ctx;
36 
37     if (rte_bus_scan() != 0 || rte_bus_probe() != 0) {//若bus scan和probe都不成功
38         driver->cb_arg = NULL;
39         driver->cb_fn = NULL;
40         return -1;
41     }
42 
43     driver->cb_arg = NULL;
44     driver->cb_fn = NULL;
45 
46     cleanup_pci_devices();
47     return 0;
48 }

回调函数pcie_nvme_enum_cb:

主要是执行nvme_ctrlr_probe(&trid, enum_ctx->probe_ctx, pci_dev) 从而构建相应type的ctrl:nvme_transport_ctrlr_construct(trid, &opts, devhandle),这些不放在这里介绍,会在spdk的源码解读里面分析。

rte_pci_register:

1 /* register a driver */
2 void
3 rte_pci_register(struct rte_pci_driver *driver)
4 {
5     TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
6     driver->bus = &rte_pci_bus;
7 }//注意这个struct rte_pci_bus rte_pci_bus = { .bus = {  .scan = rte_pci_scan,  .probe = rte_pci_probe,  .find_device = pci_find_device,  .plug = pci_plug,  .unplug = pci_unplug,  .parse = pci_parse,  .dma_map = pci_dma_map,  .dma_unmap = pci_dma_unmap,  .get_iommu_class = rte_pci_get_iommu_class,  .dev_iterate = rte_pci_dev_iterate,  .hot_unplug_handler = pci_hot_unplug_handler,  .sigbus_handler = pci_sigbus_handler, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),};

rte_bus_scan()和rte_bus_probe() 对所有bus进行scan和probe,若是pci_bus,执行的是上面注册的

.scan = rte_pci_scan, .probe = rte_pci_probe,

回到 1 中的attach函数:

spdk_pci_device_attach:跟原来看的有些不一样,之前看的版本直接调用的是rte_pci_scan

 1 int
 2 spdk_pci_device_attach(struct spdk_pci_driver *driver,
 3                spdk_pci_enum_cb enum_cb,
 4                void *enum_ctx, struct spdk_pci_addr *pci_address)
 5 {
 6     struct spdk_pci_device *dev;
 7     int rc;
 8     char bdf[32];
 9 
10     spdk_pci_addr_fmt(bdf, sizeof(bdf), pci_address);
11 
12     cleanup_pci_devices();
13 
14     TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
15         if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) {
16             break;
17         }
18     }
19 
20     if (dev != NULL && dev->internal.driver == driver) {
21         pthread_mutex_lock(&g_pci_mutex);
22         if (dev->internal.attached || dev->internal.pending_removal) {
23             pthread_mutex_unlock(&g_pci_mutex);
24             return -1;
25         }
26 
27         rc = enum_cb(enum_ctx, dev);//执行construct ctrl等
28         if (rc == 0) {
29             dev->internal.attached = true;
30         }
31         pthread_mutex_unlock(&g_pci_mutex);
32         return rc;
33     }
34 
35     if (!driver->is_registered) {
36         driver->is_registered = true;
37         rte_pci_register(&driver->driver);//register到rte_pci_bus.driver_list
38     }
39 
40     drive
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值