dpdk 18 ixgbe驱动初始化分析
rte_log_set_global_level
rte_log_set_global_level(uint32_t level)
pci bus注冊
TE_REGISTER_BUS(pci, rte_pci_bus.bus); drivers/bus/pci/pci_common.c ,注冊靜態的設置rte_pci_bus,在rte_pci_bus中設置了pci bus的各個回調函數
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,.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_REGISTER_BUS(pci, rte_pci_bus.bus);TE_REGISTER_BUS的定義如下:
// /*** Helper for Bus registration.* The constructor has higher priority than PMD constructors.*/ #define RTE_REGISTER_BUS(nm, bus) \ RTE_INIT_PRIO(businitfn_ ##nm, BUS) \ {\(bus).name = RTE_STR(nm);\rte_bus_register(&bus); \ }設置了bus name并調用rte_bus_register注冊總線
RTE_INIT_PRIO、TE_INIT的定義為:
//rte_common.h::: /*** Run function before main() with high priority.** @param func* Constructor function.* @param prio* Priority number must be above 100.* Lowest number is the first to run.*/ #define RTE_INIT_PRIO(func, prio) \ static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)/*** Run function before main() with low priority.** The constructor will be run after prioritized constructors.** @param func* Constructor function.*/ #define RTE_INIT(func) \RTE_INIT_PRIO(func, LAST)設置了constructor屬性,這些函數會在main函數之前執行,prio為優先級,優先級高的constructor函數會被先執行,以下是dpdk優先級的一些定義
//dpdk-stable/lib/librte_eal/common/include/rte_common.h #define RTE_PRIORITY_LOG 101 #define RTE_PRIORITY_BUS 110 #define RTE_PRIORITY_CLASS 120 #define RTE_PRIORITY_LAST 65535可以看出dpdk log的相關初始化最先被執行
對于rte_bus_register,會檢測被注冊的總線必要的回調函數是否存在,然后將buf添加到rte_bus_list
void rte_bus_register(struct rte_bus *bus) {RTE_VERIFY(bus);RTE_VERIFY(bus->name && strlen(bus->name));/* A bus should mandatorily have the scan implemented */RTE_VERIFY(bus->scan);RTE_VERIFY(bus->probe);RTE_VERIFY(bus->find_device);/* Buses supporting driver plug also require unplug. */RTE_VERIFY(!bus->plug || bus->unplug);TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name); }驅動注冊
RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd);
net_ixgbe 為驅動名字,rte_ixgbe_pmd結構體是對被注冊driver的描述
/** Helper for PCI device registration from driver (eth, crypto) instance */#define RTE_PMD_REGISTER_PCI(nm, pci_drv) \RTE_INIT(pciinitfn_ ##nm) \ {\(pci_drv).driver.name = RTE_STR(nm);\rte_pci_register(&pci_drv); \ } \對于rte_pci_register,
void rte_pci_register(struct rte_pci_driver *driver) {//添加driver到listTAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);//rte_pci_bus為全局變量driver->bus = &rte_pci_bus; }將驅動添加到對應的總線的driver_list。我們在看看rte_ixgbe_pmd 結構體
static struct rte_pci_driver rte_ixgbe_pmd = {.id_table = pci_id_ixgbe_map,.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,.probe = eth_ixgbe_pci_probe,.remove = eth_ixgbe_pci_remove, };結構體中,pci_id_ixgbe_map描述了driver支持的設備,并設置了probe、remove回調函數,在后續會掃描PCI總線上的device,并對調用rte_pci_match(dr, dev)檢測device、driver匹配,匹配則進一步調用driver的probe函數。
device掃描
#0 rte_pci_scan () at dpdk-stable/drivers/bus/pci/linux/pci.c:464 #1 rte_bus_scan () at dpdk-stable/lib/librte_eal/common/eal_common_bus.c:78 #2 rte_eal_init (argc=argc@entry=10, argv=argv@entry=0xffffff31a8) at dpdk-stable/lib/librte_eal/linuxapp/eal/eal.c:1028 #3 main (argc=<optimized out>, argv=0xffffff31a8) at dpdk-stable/app/test-pmd/testpmd.c:3124在rte_bus_scan函數中會遍歷rte_bus_list,并調用每個bus注冊的scan回調函數,對于本文例子就是rte_pci_scan()函數。rte_pci_scan 會遍歷系統中的device設,備,并將device信息填充到rte_pci_device,最后調用pci_scan_one–>rte_pci_add_device 將device添加到rte_pci_bus.device_list
driver初始化
#0 eth_ixgbe_pci_probe () at dpdk-stable/drivers/net/ixgbe/ixgbe_ethdev.c:1799 #1 rte_pci_probe_one_driver () at dpdk-stable/drivers/bus/pci/pci_common.c:199 #2 pci_probe_all_drivers () at dpdk-stable/drivers/bus/pci/pci_common.c:273 #3 rte_pci_probe () at dpdk-stable/drivers/bus/pci/pci_common.c:308 #4 rte_bus_probe () at dpdk-stable/lib/librte_eal/common/eal_common_bus.c:100 #5 rte_eal_init () at dpdk-stable/lib/librte_eal/linuxapp/eal/eal.c:1213在device和driver都安放好后就要開始初始化,對于PCI總線上的設備,會在rte_pci_probe遍歷rte_pci_bus.device_list,對每個device調用 pci_probe_all_drivers()函數,并在函數中遍歷rte_pci_bus.driver_list,使用rte_pci_match(dr, dev) 判斷device和driver是否匹配,匹配則調用driver的probe。
以下是對這個過程的簡化代碼
FOREACH_DEVICE_ON_PCIBUS(dev){FOREACH_DRIVER_ON_PCIBUS(dr)if (!rte_pci_match(dr, dev))return 1;probe_driver(); }by:junchao_zhao@yeah.net
總結
以上是生活随笔為你收集整理的dpdk 18 ixgbe驱动初始化分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kaggle入门篇
- 下一篇: centos上使用高版本gcc、g++