dpdk源碼---vfio(zym)


主要想找到從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\n");
21             return -ENOMSG;
22         }
23         if (req.result != 0)
24             RTE_LOG(ERR, EAL,
25                 "Failed to hotplug add device\n");
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\n");
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\n");
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\n");
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\n");
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\n");
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)\n",
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)\n",
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)\n",
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\n", __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\n");
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!\n",
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\n",
 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\n");
 33         return 1;
 34     }
 35 
 36     if (dev->device.numa_node < 0) {
 37         RTE_LOG(WARNING, EAL, "  Invalid NUMA socket, default to 0\n");
 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\n",
 44                 dev->device.name);
 45         return -EEXIST;
 46     }
 47 
 48     RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", 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\n", 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\n");
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

這三個函數要重點看。。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM