DPDKrte_eal_init初始化分析(根据最新的更新)

更新时间:2023-05-09 21:23:48 阅读: 评论:0

DPDKrte_eal_init初始化分析(根据最新的更新)端⼝初始化流程
1. 注册设备驱动到“dev_driver_list”链表中
2.扫描系统中的pci设备,并注册到“pci_device_list”中
3、初始化注册的驱动
4、⽹卡设备初始化
端⼝初始化流程
如上所⽰给出了端⼝打开的简单流程图,下⾯以ixgbe驱动为例详细说明:
1. 注册设备驱动到“dev_driver_list”链表中
这个链表节点为:
/**
* A structure describing a device driver.
*/
struct rte_driver {
TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
enum pmd_type type;            /**< PMD Driver type */
const char *name;              /**< Driver name. */
rte_dev_init_t *init;          /**< Device init. function. */
rte_dev_uninit_t *uninit;      /**< Device uninit. function. */
};
将ixgbe的这些信息注册到该链表中:
static struct rte_driver rte_ixgbe_driver = {
.type = PMD_PDEV,
.init = rte_ixgbe_pmd_init,
};
PMD_REGISTER_DRIVER(rte_ixgbe_driver);
PMD_REGISTER_DRIVER为dpdk定义的宏,使⽤了GNU C提供的“__attribute__(constructor)”机制,使得注册设备驱动的过程在main函数执⾏之前完成。
这样就有了设备驱动类型、设备驱动的初始化函数
2.扫描系统中的pci设备,并注册到“pci_device_list”中
链表节点为:
/**
* A structure describing a PCI device.
*/
struct rte_pci_device {
TAILQ_ENTRY(rte_pci_device) next;      /**< Next probed PCI device. */
struct rte_pci_addr addr;              /**< PCI location. */
struct rte_pci_id id;                  /**< PCI ID. */
struct rte_pci_resource mem_resource[PCI_MAX_RESOURCE];  /**< PCI Memory Resource */
struct rte_intr_handle intr_handle;    /**< Interrupt handle */
struct rte_pci_driver *driver;          /**< Associated driver */
uint16_t max_vfs;                      /**< sriov enable if not zero */
int numa_node;                          /**< NUMA node connection */
struct rte_devargs *devargs;            /**< Device ur arguments */
enum rte_kernel_driver kdrv;            /**< Kernel driver passthrough */
};
从系统中获取到PCI设备的相关信息后,记录到这样的⼀个结构体中。如何获取到这些信息:
在main函数的⼀开始,调⽤rte_eal_init()获取⽤户、系统的相关配置信息以及设置基础运⾏环境,其中包括调⽤rte_eal_pci_init()来扫描、获取系统中的CPI⽹卡信息;
⾸先,初始化pci_device_list链表,后⾯扫描的到的pci⽹卡设备信息会记录到这个链表中;
然后,调⽤rte_eal_pci_scan()扫描系统中的PCI⽹卡:遍历”/sys/bus/pci/devices”⽬录下的所有pci地址,逐个获取对应的pci地址、pci id、sriov使能时的vf个数、亲和的numa、设备地址空间、驱动类型等;
* Scan the content of the PCI bus, and the devices in the devices list
*/
int rte_eal_pci_scan(void)
{
struct dirent *e;
DIR *dir;
char dirname[PATH_MAX];
uint16_t domain;
uint8_t bus, devid, function;
dir = opendir(SYSFS_PCI_DEVICES);
if (dir == NULL) {
RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
__func__, strerror(errno));
return -1;
}
while ((e = readdir(dir)) != NULL) {
if (e->d_name[0] == '.')
continue;
if (par_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
&bus, &devid, &function) != 0)
continue;
snprintf(dirname, sizeof(dirname), "%s/%s", SYSFS_PCI_DEVICES,
e->d_name);
if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
goto error;
}
clodir(dir);
return 0;
error:
clodir(dir);
return -1;
}
这样,扫描并记录了系统中所有的pci设备的相关信息,后⾯根据上⾯获取的这些设备信息以及前⾯注册的驱动信息,就可以完成具体⽹卡设备的初始化;
3、初始化注册的驱动
在rte_eal_init()函数中,后⾯会调⽤rte_eal_dev_init()来初始化前⾯注册的驱动“dev_driver_list”:分别调⽤注册的每款驱动的初始化函数,把每款驱动的⼀些信息记录到“pci_driver_list”链表中,链表节点
为:
* @internal
* The structure associated with a PMD Ethernet driver.
*
* Each Ethernet driver acts as a PCI driver and is reprented by a generic
* *eth_driver* structure that holds:
*
* - An *rte_pci_driver* structure (which must be the first field).
*
* - The *eth_dev_init* function invoked for each matching PCI device.
*
* - The *eth_dev_uninit* function invoked for each matching PCI device.
*
* - The size of the private data to allocate for each matching device.
*/
struct eth_driver {
struct rte_pci_driver pci_drv;    /**< The PMD is also a PCI driver. */
eth_dev_init_t eth_dev_init;      /**< Device init function. */
eth_dev_uninit_t eth_dev_uninit;  /**< Device uninit function. */
unsigned int dev_private_size;    /**< Size of device private data. */
};
结构中记录设备的init、uinit、私有数据⼤⼩以及pci driver信息,⽽struct rte_pci_driver中的记录了驱
动⽀持的⽹卡设备的verder id、device id信息,这个在后⾯具体的PCI⽹卡设备初始化时,会根据这些信息来匹配驱动:
/**
* A structure describing a PCI driver.
*/
struct rte_pci_driver {
TAILQ_ENTRY(rte_pci_driver) next;      /**< Next in list. */
const char *name;                      /**< Driver name. */
pci_devinit_t *devinit;                /**< Device init. function. */
pci_devuninit_t *devuninit;            /**< Device uninit function. */
const struct rte_pci_id *id_table;      /**< ID table, NULL terminated. */
uint32_t drv_flags;                    /**< Flags contolling handling of device. */
};
/**
* A structure describing an ID for a PCI driver. Each driver provides a
* table of the IDs for each device that it supports.
*/
struct rte_pci_id {
uint16_t vendor_id;          /**< Vendor ID or PCI_ANY_ID. */
uint16_t device_id;          /**< Device ID or PCI_ANY_ID. */
uint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */
uint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */
};
已ixgbe类型的⽹卡为例,注册的信息为rte_ixgbe_pmd:
static struct eth_driver rte_ixgbe_pmd = {
.pci_drv = {
.name = "rte_ixgbe_pmd",
.id_table = pci_id_ixgbe_map,
.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
RTE_PCI_DRV_DETACHABLE,
},
.eth_dev_init = eth_ixgbe_dev_init,
.eth_dev_uninit = eth_ixgbe_dev_uninit,
.dev_private_size = sizeof(struct ixgbe_adapter),
};
⾄此,注册的每款驱动的设备初始化,⽀持的设备等信息以及系统中所有的pci设备信息就已经都有了,分别记录
在”pci_driver_list”和”pci_device_list”这两个全局的链表中,接下来就可以完成设备匹配驱动,别初始化设备了。
4、⽹卡设备初始化
rte_eal_init()函数接下来调⽤rte_eal_pci_probe()函数完成具体的设备的初始化
/*
* Scan the content of the PCI bus, and call the devinit() function for
* all registered drivers that have a matching entry in its id_table
* for discovered devices.
*/
int rte_eal_pci_probe(void)
{
struct rte_pci_device *dev = NULL;
struct rte_devargs *devargs;
int probe_all = 0;
int ret = 0;
/* 如果配置了⽩名单,只初始化⽩名单中的设备,否则所有⽀持的设备都初始化 */
if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
probe_all = 1;
TAILQ_FOREACH(dev, &pci_device_list, next) {
/* t devargs in PCI structure */
devargs = pci_devargs_lookup(dev);
if (devargs != NULL)
dev->devargs = devargs;
/* probe all or only whitelisted devices */
if (probe_all)
ret = pci_probe_all_drivers(dev);
el if (devargs != NULL &&
devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
ret = pci_probe_all_drivers(dev);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
" cannot be ud\n", dev->addr.domain, dev->addr.bus,
dev->addr.devid, dev->addr.function);
}
return 0;
}
rte_eal_pci_probe_one_driver()函数中,在probe⼀个具体的设备时,⽐较vendor id、device id,然后映射设备资源、调⽤驱动的设备初始化函数:

本文发布于:2023-05-09 21:23:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/102452.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:设备   驱动   信息
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图