接下来重点看看L647对应的函数spck_pci_nvme_enumerate()就好,因为我们的目标是看明白是如何利用Class Code发现SSD设备的。
647 return spdk_pci_nvme_enumerate(pcie_nvme_enum_cb, &enum_ctx);
- /* src/spdk-17.07.1/lib/env_dpdk/pci_nvme.c */
-
- 81 int
- 82 spdk_pci_nvme_enumerate(spdk_pci_enum_cb enum_cb, void *enum_ctx)
- 83 {
- 84 return spdk_pci_enumerate(&g_nvme_pci_drv, enum_cb, enum_ctx);
- 85 }
注意: L84第一个参数为一个全局变量g_nvme_pci_drv的地址
- /* src/spdk-17.07.1/lib/env_dpdk/pci_nvme.c */
-
- 38 static struct rte_pci_id nvme_pci_driver_id[] = {
- 39 #if RTE_VERSION >= RTE_VERSION_NUM(16, 7, 0, 1)
- 40 {
- 41 .class_id = SPDK_PCI_CLASS_NVME,
- 42 .vendor_id = PCI_ANY_ID,
- 43 .device_id = PCI_ANY_ID,
- 44 .subsystem_vendor_id = PCI_ANY_ID,
- 45 .subsystem_device_id = PCI_ANY_ID,
- 46 },
- 47 #else
- 48 {RTE_PCI_DEVICE(0x8086, 0x0953)},
- 49 #endif
- 50 { .vendor_id = 0, /* sentinel */ },
- 51 };
- ..
- 53 static struct spdk_pci_enum_ctx g_nvme_pci_drv = {
- 54 .driver = {
- 55 .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
- 56 .id_table = nvme_pci_driver_id,
- ..
- 66 },
- 67
- 68 .cb_fn = NULL,
- 69 .cb_arg = NULL,
- 70 .mtx = PTHREAD_MUTEX_INITIALIZER,
- 71 .is_registered = false,
- 72 };
终于跟Class Code (SPDK_PCI_CLASS_NVME=0x010802)扯上了关系。 全局变量g_nvme_pci_drv就是在L53行定义的,而g_nvme_pci_drv.driver.id_table则是在L38行定义的。
- 38 static struct rte_pci_id nvme_pci_driver_id[] = {
- ..
- 41 .class_id = SPDK_PCI_CLASS_NVME,
- ..
- 53 static struct spdk_pci_enum_ctx g_nvme_pci_drv = {
- 54 .driver = {
- ..
- 56 .id_table = nvme_pci_driver_id,
- ..
那么,我们只需要进一步深挖spdk_pci_enumerate()就可以找到SSD设备是如何被发现的了...
- /* src/spdk-17.07.1/lib/env_dpdk/pci.c#150 */
-
- 149 int
- 150 spdk_pci_enumerate(struct spdk_pci_enum_ctx *ctx,
- 151 spdk_pci_enum_cb enum_cb,
- 152 void *enum_ctx)
- 153 {
- ...
- 168
- 169 #if RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
- 170 if (rte_pci_probe() != 0) {
- 171 #else
- 172 if (rte_eal_pci_probe() != 0) {
- 173 #endif
- ...
- 184 return 0;
- 185 }
省略了一些代码,我们接下来重点关注L170,
170 if (rte_pci_probe() != 0) {
从rte_pci_probe()函数的实现开始,我们就深入到DPDK的内部了,代码如下,
- /* src/dpdk-17.08/lib/librte_eal/common/eal_common_pci.c#413 */
-
- 407 /*
- 408 * Scan the content of the PCI bus, and call the probe() function for
- 409 * all registered drivers that have a matching entry in its id_table
- 410 * for discovered devices.
- 411 */
- 412 int
- 413 rte_pci_probe(void)
- 414 {
- 415 struct rte_pci_device *dev = NULL;
- 416 size_t probed = 0, failed = 0;
- 41