Bootstrap

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

/**
 * A structure describing an ID for a PCI driver. Each driver provides a
 * table of these 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) {

/* set 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);
        else 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 used\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,然后映射设备资源、调用驱动的设备初始化函数:



/*
 * If vendor/device ID match, call the devinit() function of the
 * driver.
 */
static int
rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
{
    int ret;
    const struct rte_pci_id *id_table;

for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {

/* check if device’s identifiers match the driver’s ones */
        … …

if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
            /* map resources for devices that use igb_uio /
            ret = rte_eal_pci_map_device(dev);
            if (ret != 0)
                return ret;
        } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
                rte_eal_process_type() == RTE_PROC_PRIMARY) {
            /
unbind current driver /
            if (pci_unbind_kernel_driver(dev) < 0)
                return -1;
        }
        /
call the driver devinit() function /
        return dr->devinit(dr, dev);
    }
    /
return positive value if driver doesn’t support this device

;