主要想找到从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 driver->cb_fn = enum_cb;
41 driver->cb_arg = enum_ctx;
42
43 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0)
44 int i = 0;
45
46 do {
47 rc = rte_eal_hotplug_add("pci", bdf, "");
48 } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT);
49
50 if (i > 1 && rc == -EEXIST) {
51 /* Even though the previous request timed out, the device
52 * was attached successfully.
53 */
54 rc = 0;
55 }
56 #else
57 rc = rte_eal_dev_attach(bdf, "");//这个函数在旧版本的dpdk中
58 #endif
59
60 driver->cb_arg = NULL;
61 driver->cb_fn = NULL;
62
63 cleanup_pci_devices();
64 return rc == 0 ? 0 : -1;
65 }
rte_eal_hotplug_add:
--------rte_dev_probe(devargs)
1 int
2 rte_dev_probe(const char *devargs)
3 {
4 struct eal_dev_mp_req req;
5 struct rte_device *dev;
6 int ret;
7
8 memset(&req, 0, sizeof(req));
9 req.t = EAL_DEV_REQ_TYPE_ATTACH;
10 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
11
12 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {//不是primary进程
13 /**
14 * If in secondary process, just send IPC request to
15 * primary process.
16 */
17 ret = eal_dev_hotplug_request_to_primary(&req);//那么给primary进程发attch的请求
18 if (ret != 0) {
19 RTE_LOG(ERR, EAL,
20 "Failed to send hotplug request to primary
");
21 return -ENOMSG;
22 }
23 if (req.result != 0)
24 RTE_LOG(ERR, EAL,
25 "Failed to hotplug add device
");
26 return req.result;
27 }
28
29 /* attach a shared device from primary start from here: */
31 /* primary attach the new device itself. */
32 ret = local_dev_probe(devargs, &dev);//其中会执行da->bus->scan()
33
34 if (ret != 0) {
35 RTE_LOG(ERR, EAL,
36 "Failed to attach device on primary process
");
37
38 /**
39 * it is possible that secondary process failed to attached a
40 * device that primary process have during initialization,
41 * so for -EEXIST case, we still need to sync with secondary
42 * process.
43 */
44 if (ret != -EEXIST)
45 return ret;
46 }
47
48 /* primary send attach sync request to secondary. */
49 ret = eal_dev_hotplug_request_to_secondary(&req);//给secondary进程发消息同步attach情况
50
51 /* if any communication error, we need to rollback. */
52 if (ret != 0) {
53 RTE_LOG(ERR, EAL,
54 "Failed to send hotplug add request to secondary
");
55 ret = -ENOMSG;
56 goto rollback;
57 }
59 /**
60 * if any secondary failed to attach, we need to consider if rollback
61 * is necessary.
62 */
63 if (req.result != 0) {
64 RTE_LOG(ERR, EAL,
65 "Failed to attach device on secondary process
");
66 ret = req.result;
67
68 /* for -EEXIST, we don't need to rollback. */
69 if (ret == -EEXIST)
70 return ret;
71 goto rollback;
72 }
73
74 return 0;
75
76 rollback:
77 req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
78
79 /* primary send rollback request to secondary. */
80 if (eal_dev_hotplug_request_to_secondary(&req) != 0)
81 RTE_LOG(WARNING, EAL,
82 "Failed to rollback device attach on secondary."
83 "Devices in secondary may not sync with primary
");
84
85 /* primary rollback itself. */
86 if (local_dev_remove(dev) != 0)
87 RTE_LOG(WARNING, EAL,
88 "Failed to rollback device attach on primary."
89 "Devices in secondary may not sync with primary
");
90
91 return ret;
92 }
local_dev_probe:
最终也是调用rte_pci_scan和pci_probe_all_drivers
1 /* probe device at local process. */
2 int
3 local_dev_probe(const char *devargs, struct rte_device **new_dev)
4 {
5 struct rte_device *dev;
6 struct rte_devargs *da;
7 int ret;
8
9 *new_dev = NULL;
10 da = calloc(1, sizeof(*da));
11 if (da == NULL)
12 return -ENOMEM;
13
14 ret = rte_devargs_parse(da, devargs);
15 if (ret)
16 goto err_devarg;
17
18 if (da->bus->plug == NULL) {
19 RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)
",
20 da->bus->name);
21 ret = -ENOTSUP;
22 goto err_devarg;
23 }
24
25 ret = rte_devargs_insert(&da);
26 if (ret)
27 goto err_devarg;
28
29 /* the rte_devargs will be referenced in the matching rte_device */
30 ret = da->bus->scan();//pci的话执行register函数中注册的rte_pci_scan
31 if (ret)
32 goto err_devarg;
33
34 dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
35 if (dev == NULL) {
36 RTE_LOG(ERR, EAL, "Cannot find device (%s)
",
37 da->name);
38 ret = -ENODEV;
39 goto err_devarg;
40 }
41 /* Since there is a matching device, it is now its responsibility
42 * to manage the devargs we've just inserted. From this point
43 * those devargs shouldn't be removed manually anymore.
44 */
45
46 ret = dev->bus->plug(dev);//rte_pci_plug中执行的是pci_probe_all_drivers(RTE_DEV_TO_PCI(dev))
47 if (ret > 0)
48 ret = -ENOTSUP;
49
50 if (ret && !rte_dev_is_probed(dev)) { /* if hasn't ever succeeded */
51 RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)
",
52 dev->name);
53 return ret;
54 }
55
56 *new_dev = dev;
57 return ret;
58
59 err_devarg:
60 if (rte_devargs_remove(da) != 0) {
61 free(da->args);
62 free(da);
63 }
64 return ret;
65 }
所以 1 中 nvme_pcie_ctrl_scan 不管是spdk_pci_enumerate还是spdk_pci_device_attach,核心的流程都是一样的:
执行回调函数pcie_nvme_enum_cb;
rte_pci_scan
rte_pci_probe/pci_probe_all_drivers (rte_pci_probe也是调用pci_probe_all_drivers)
所以后面我们看 rte_pci_bus.scan(rte_pci_scan)和rte_pci_bus.probe(rte_pci_probe)的实现。
rte_pci_scan:
1 /*
2 * Scan the content of the PCI bus, and the devices in the devices
3 * list
4 */
5 int
6 rte_pci_scan(void)
7 {
8 struct dirent *e;
9 DIR *dir;
10 char dirname[PATH_MAX];
11 struct rte_pci_addr addr;
12
13 ........
14 dir = opendir(rte_pci_get_sysfs_path()); ///sys/bus/pci/devices
15
16 ........
17 while ((e = readdir(dir)) != NULL) {
18 if (e->d_name[0] == '.')
19 continue;
20
21 if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)
22 continue;
23
24 snprintf(dirname, sizeof(dirname), "%s/%s",
25 rte_pci_get_sysfs_path(), e->d_name);
26
27 if (pci_scan_one(dirname, &addr) < 0)//扫描/sys/bus/pci/devices下面每个目录
28 goto error;
29 }
30 closedir(dir);
31 return 0;
32 ..........
33 }
ls /sys/bus/pci/devices/ 0000:00:00.0 0000:00:04.4 0000:00:1c.6 0000:03:00.0 0000:ff:0d.1 0000:ff:12.2 0000:ff:14.5 0000:ff:17.6 0000:00:01.0 0000:00:04.5 0000:00:1c.7 0000:05:00.0 0000:ff:0f.0 0000:ff:12.4 0000:ff:14.6 0000:ff:17.7
1 /* Scan one pci sysfs entry, and fill the devices list from it. */
2 static int
3 pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
4 {
5 char filename[PATH_MAX];
6 unsigned long tmp;
7 struct rte_pci_device *dev;
8 char driver[PATH_MAX];
9 int ret;
10
11 dev = malloc(sizeof(*dev));
12 if (dev == NULL)
13 return -1;
14
15 memset(dev, 0, sizeof(*dev));
16 dev->device.bus = &rte_pci_bus.bus;
17 dev->addr = *addr;
18
19 /* get vendor id */
20 snprintf(filename, sizeof(filename), "%s/vendor", dirname);
21 if (eal_parse_sysfs_value(filename, &tmp) < 0) {
22 free(dev);
23 return -1;
24 }
25 dev->id.vendor_id = (uint16_t)tmp;
26
27 /* get device id */
28 snprintf(filename, sizeof(filename), "%s/device", dirname);
29 if (eal_parse_sysfs_value(filename, &tmp) < 0) {
30 free(dev);
31 return -1;
32 }
33 dev->id.device_id = (uint16_t)tmp;
34
35 /* get subsystem_vendor id */
36 snprintf(filename, sizeof(filename), "%s/subsystem_vendor",
37 dirname);
38 if (eal_parse_sysfs_value(filename, &tmp) < 0) {
39 free(dev);
40 return -1;
41 }
42 dev->id.subsystem_vendor_id = (uint16_t)tmp;
43
44 /* get subsystem_device id */
45 snprintf(filename, sizeof(filename), "%s/subsystem_device",
46 dirname);
47 if (eal_parse_sysfs_value(filename, &tmp) < 0) {
48 free(dev);
49 return -1;
50 }
51 dev->id.subsystem_device_id = (uint16_t)tmp;
52
53 /* get class_id */
54 snprintf(filename, sizeof(filename), "%s/class",
55 dirname);
56 if (eal_parse_sysfs_value(filename, &tmp) < 0) {
57 free(dev);
58 return -1;
59 }
60 /* the least 24 bits are valid: class, subclass, program interface */
61 dev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;
62
63 /* get max_vfs */
64 dev->max_vfs = 0;
65 snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);
66 if (!access(filename, F_OK) &&
67 eal_parse_sysfs_value(filename, &tmp) == 0)
68 dev->max_vfs = (uint16_t)tmp;
69 else {
70 /* for non igb_uio driver, need kernel version >= 3.8 */
71 snprintf(filename, sizeof(filename),
72 "%s/sriov_numvfs", dirname);
73 if (!access(filename, F_OK) &&
74 eal_parse_sysfs_value(filename, &tmp) == 0)
75 dev->max_vfs = (uint16_t)tmp;
76 }
77
78 /* get numa node, default to 0 if not present */
79 snprintf(filename, sizeof(filename), "%s/numa_node",
80 dirname);
81
82 if (access(filename, F_OK) != -1) {
83 if (eal_parse_sysfs_value(filename, &tmp) == 0)
84 dev->device.numa_node = tmp;
85 else
86 dev->device.numa_node = -1;
87 } else {
88 dev->device.numa_node = 0;
89 }
90
91 pci_name_set(dev);
92
93 /* parse resources */
94 snprintf(filename, sizeof(filename), "%s/resource", dirname);
95 if (pci_parse_sysfs_resource(filename, dev) < 0) {
96 RTE_LOG(ERR, EAL, "%s(): cannot parse resource
", __func__);
97 free(dev);
98 return -1;
99 }
100
101 /* parse driver */
102 snprintf(filename, sizeof(filename), "%s/driver", dirname);///sys/bus/pci/drivers
103 ret = pci_get_kernel_driver_by_path(filename, driver, sizeof(driver));
104 if (ret < 0) {
105 RTE_LOG(ERR, EAL, "Fail to get kernel driver
");
106 free(dev);
107 return -1;
108 }
109
110 if (!ret) {
111 if (!strcmp(driver, "vfio-pci"))
112 dev->kdrv = RTE_KDRV_VFIO;
113 else if (!strcmp(driver, "igb_uio"))
114 dev->kdrv = RTE_KDRV_IGB_UIO;
115 else if (!strcmp(driver, "uio_pci_generic"))
116 dev->kdrv = RTE_KDRV_UIO_GENERIC;
117 else
118 dev->kdrv = RTE_KDRV_UNKNOWN;
119 } else
120 dev->kdrv = RTE_KDRV_NONE;
121
122 /* device is valid, add in list (sorted) */
123 if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
124 rte_pci_add_device(dev);
125 } else {
126 struct rte_pci_device *dev2;
127 int ret;
128
129 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
130 ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
131 if (ret > 0)
132 continue;
133
134 if (ret < 0) {
135 rte_pci_insert_device(dev2, dev);
136 } else { /* already registered */
137 if (!rte_dev_is_probed(&dev2->device)) {
138 dev2->kdrv = dev->kdrv;
139 dev2->max_vfs = dev->max_vfs;
140 pci_name_set(dev2);
141 memmove(dev2->mem_resource,
142 dev->mem_resource,
143 sizeof(dev->mem_resource));
144 } else {
145 /**
146 * If device is plugged and driver is
147 * probed already, (This happens when
148 * we call rte_dev_probe which will
149 * scan all device on the bus) we don't
150 * need to do anything here unless...
151 **/
152 if (dev2->kdrv != dev->kdrv ||
153 dev2->max_vfs != dev->max_vfs)
154 /*
155 * This should not happens.
156 * But it is still possible if
157 * we unbind a device from
158 * vfio or uio before hotplug
159 * remove and rebind it with
160 * a different configure.
161 * So we just print out the
162 * error as an alarm.
163 */
164 RTE_LOG(ERR, EAL, "Unexpected device scan at %s!
",
165 filename);
166 }
167 free(dev);
168 }
169 return 0;
170 }
171
172 rte_pci_add_device(dev);
173 }
174
175 return 0;
176 }
rte_pci_probe:
------FOREACH_DEVICE_ON_PCIBUS(dev) pci_probe_all_drivers(dev)
------------FOREACH_DRIVER_ON_PCIBUS(dr) rte_pci_probe_one_driver(dr, dev)
1 /*
2 * If vendor/device ID match, call the probe() function of the
3 * driver.
4 */
5 static int
6 rte_pci_probe_one_driver(struct rte_pci_driver *dr,
7 struct rte_pci_device *dev)
8 {
9 int ret;
10 bool already_probed;
11 struct rte_pci_addr *loc;
12
13 if ((dr == NULL) || (dev == NULL))
14 return -EINVAL;
15
16 loc = &dev->addr;
17
18 /* The device is not blacklisted; Check if driver supports it */
19 if (!rte_pci_match(dr, dev))
20 /* Match of device and driver failed */
21 return 1;
22
23 RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i
",
24 loc->domain, loc->bus, loc->devid, loc->function,
25 dev->device.numa_node);
26
27 /* no initialization when blacklisted, return without error */
28 if (dev->device.devargs != NULL &&
29 dev->device.devargs->policy ==
30 RTE_DEV_BLACKLISTED) {
31 RTE_LOG(INFO, EAL, " Device is blacklisted, not"
32 " initializing
");
33 return 1;
34 }
35
36 if (dev->device.numa_node < 0) {
37 RTE_LOG(WARNING, EAL, " Invalid NUMA socket, default to 0
");
38 dev->device.numa_node = 0;
39 }
40
41 already_probed = rte_dev_is_probed(&dev->device);
42 if (already_probed && !(dr->drv_flags & RTE_PCI_DRV_PROBE_AGAIN)) {
43 RTE_LOG(DEBUG, EAL, "Device %s is already probed
",
44 dev->device.name);
45 return -EEXIST;
46 }
47
48 RTE_LOG(INFO, EAL, " probe driver: %x:%x %s
", dev->id.vendor_id,
49 dev->id.device_id, dr->driver.name);
50
51 /*
52 * reference driver structure
53 * This needs to be before rte_pci_map_device(), as it enables to use
54 * driver flags for adjusting configuration.
55 */
56 if (!already_probed) {
57 enum rte_iova_mode dev_iova_mode;
58 enum rte_iova_mode iova_mode;
59
60 dev_iova_mode = pci_device_iova_mode(dr, dev);//从设备绑定的驱动判断dev_iova_mode,例如若是UIO驱动,则这里是PA
61 iova_mode = rte_eal_iova_mode();//dpdk初始化过程判断的,首先会去判断设备的驱动,如果驱动还没注册,那么里面是根据机器上是否有iommu等判断。而spdk中nvme 驱动是在dpdk初始化之后才注册进去的,所以即使是用uio驱动,dpdk给出的iova_mode也是VA,所以这里有点小问题! 62 if (dev_iova_mode != RTE_IOVA_DC &&
63 dev_iova_mode != iova_mode) {
64 RTE_LOG(ERR, EAL, " Expecting '%s' IOVA mode but current mode is '%s', not initializing
",
65 dev_iova_mode == RTE_IOVA_PA ? "PA" : "VA",
66 iova_mode == RTE_IOVA_PA ? "PA" : "VA");
67 return -EINVAL;
68 }
69
70 dev->driver = dr;
71 }
72
73 if (!already_probed && (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)) {
74 /* map resources for devices that use igb_uio */???注释有问题??
75 ret = rte_pci_map_device(dev);
76 if (ret != 0) {
77 dev->driver = NULL;
78 return ret;
79 }
80 }
81
82 /* call the driver probe() function */
83 ret = dr->probe(dr, dev); //在哪里?????
84 if (already_probed)
85 return ret; /* no rollback if already succeeded earlier */
86 if (ret) {
87 dev->driver = NULL;
88 if ((dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) &&
89 /* Don't unmap if device is unsupported and
90 * driver needs mapped resources.
91 */
92 !(ret > 0 &&
93 (dr->drv_flags & RTE_PCI_DRV_KEEP_MAPPED_RES)))
94 rte_pci_unmap_device(dev);
95 } else {
96 dev->device.driver = &dr->driver;
97 }
98
99 return ret;
100 }
rte_pci_map_device 从这遍开始和vfio,uio等相关
1 /* Map pci device */
2 int
3 rte_pci_map_device(struct rte_pci_device *dev)
4 {
5 int ret = -1;
6
7 /* try mapping the NIC resources using VFIO if it exists */
8 switch (dev->kdrv) {
9 case RTE_KDRV_VFIO:
10 #ifdef VFIO_PRESENT
11 if (pci_vfio_is_enabled())
12 ret = pci_vfio_map_resource(dev);
13 #endif
14 break;
15 case RTE_KDRV_IGB_UIO:
16 case RTE_KDRV_UIO_GENERIC:
17 if (rte_eal_using_phys_addrs()) {
18 /* map resources for devices that use uio */
19 ret = pci_uio_map_resource(dev);
20 }
21 break;
22 default:
23 RTE_LOG(DEBUG, EAL,
24 " Not managed by a supported kernel driver, skipped
");
25 ret = 1;
26 break;
27 }
28
29 return ret;
30 }
pci_vfio_map_resource:
---1---pci_vfio_map_resource_primary 若设primary进程
------pci_vfio_map_resource_secondary
-------2---------rte_vfio_setup_device
------------3------------vfio_mem_event_callback
这三个函数要重点看。。。。
原文链接:https://www.cnblogs.com/yi-mu-xi/p/12441357.html 原文作者:yimuxi
LinuxC/C++服务器开发/架构师 面试题、学习资料、教学视频和学习路线图(资料包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis、MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等),或点击这里加qun免费领取,关注我持续更新哦! !
页面更新:2024-05-21
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号