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 ,注冊靜態(tài)的設(shè)置rte_pci_bus,在rte_pci_bus中設(shè)置了pci bus的各個(gè)回調(diào)函數(shù)
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); \ }設(shè)置了bus name并調(diào)用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)設(shè)置了constructor屬性,這些函數(shù)會在main函數(shù)之前執(zhí)行,prio為優(yōu)先級,優(yōu)先級高的constructor函數(shù)會被先執(zhí)行,以下是dpdk優(yōu)先級的一些定義
//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的相關(guān)初始化最先被執(zhí)行
對于rte_bus_register,會檢測被注冊的總線必要的回調(diào)函數(shù)是否存在,然后將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); }驅(qū)動(dòng)注冊
RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd);
net_ixgbe 為驅(qū)動(dòng)名字,rte_ixgbe_pmd結(jié)構(gòu)體是對被注冊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; }將驅(qū)動(dòng)添加到對應(yīng)的總線的driver_list。我們在看看rte_ixgbe_pmd 結(jié)構(gòu)體
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, };結(jié)構(gòu)體中,pci_id_ixgbe_map描述了driver支持的設(shè)備,并設(shè)置了probe、remove回調(diào)函數(shù),在后續(xù)會掃描PCI總線上的device,并對調(diào)用rte_pci_match(dr, dev)檢測device、driver匹配,匹配則進(jìn)一步調(diào)用driver的probe函數(shù)。
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函數(shù)中會遍歷rte_bus_list,并調(diào)用每個(gè)bus注冊的scan回調(diào)函數(shù),對于本文例子就是rte_pci_scan()函數(shù)。rte_pci_scan 會遍歷系統(tǒng)中的device設(shè),備,并將device信息填充到rte_pci_device,最后調(diào)用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總線上的設(shè)備,會在rte_pci_probe遍歷rte_pci_bus.device_list,對每個(gè)device調(diào)用 pci_probe_all_drivers()函數(shù),并在函數(shù)中遍歷rte_pci_bus.driver_list,使用rte_pci_match(dr, dev) 判斷device和driver是否匹配,匹配則調(diào)用driver的probe。
以下是對這個(gè)過程的簡化代碼
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
總結(jié)
以上是生活随笔為你收集整理的dpdk 18 ixgbe驱动初始化分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。