• 大小: 24KB
    文件类型: .c
    金币: 2
    下载: 1 次
    发布日期: 2022-10-06
  • 语言: 其他
  • 标签: pci  napi  ixgevf  

资源简介

这是一份关于 ixgbevf 的10G高性能网卡的驱动分析, 里面都是本人对centos内核 ixgbevf驱动源码的跟踪,里面涵盖了关于pci, napi的知识。 这一类形的高性能解决方案非常通用,而且也是行业的标准。 一个驱动从上电启动,到初始化,到挂载带pci总线, 到注册到napi模型,到poll接收数据包。 都用分析。

资源截图

代码片段和文件信息

一, PCI nic驱动
1 初始化
在pci_driver中包含一个名为*id_table的pci_device_id结构,
用于标识该驱动所能支持的网卡类型,这里IGB所能支持的相应结构为:   
static struct pci_device_id ixgbevf_pci_tbl[] = {
{pci_vdevice(intel ixgbe_dev_id_82599_vf) board_82599_vf} 
{pci_vdevice(intel ixgbe_dev_id_x540_vf) board_x540_vf}
{0 }
};

ixgbe驱动定义了pci_driver类型的结构——ixgbevf_driver,
并通过对其修改设置了该驱动的名称、其支持的网卡型号、
以及对该网卡进行各种操作时候应该调用的相应函数句柄,代码如下:   
static struct pci_driver ixgbevf_driver = {
.name     = ixgbevf_driver_name
.id_table = ixgbevf_pci_tbl
.probe    = ixgbevf_probe //当PCI层检测到一个PCI设备能够被某PCI驱动所支持 就调调用此函数
.remove   = __devexit_p(ixgbevf_remove)
.shutdown = ixgbevf_shutdown
};

当PCI层检测到一个PCI设备能够被某PCI驱动所支持时(这是通过函数pci_match_one_device来进行检测的),
就会调用这个PCI驱动上的probe函数,在该函数中会对该特定的PCI设备进行一些具体的初始化等操作。
其probe函数为ixgbevf_probe,其主要作用是网卡设备net_device的初始化。
而在网卡设备的初始化之前,首先需要完成的是将网卡设备注册到PCI层。

2. 驱动的初始化
Linux-2.6下的驱动有统一的入口和出口,即:module_init()和module_exit()。
module_init(ixgbevf_init_module);
module_exit(ixgbevf_exit_module);

其中的ixgbevf_init_module()和ixgbevf_exit_module()分别为用于加载和注销ixgbe驱动的真正起作用的代码,
其中引起网卡在PCI层注册的函数为ixgbevf_init_module(),如下: 
该函数中调用了pci_register_driver()来注册PCI驱动。 
/**
 * ixgbe_init_module - Driver Registration Routine
 *
 * ixgbe_init_module is the first routine called when the driver is
 * loaded. All it does is register with the PCI subsystem.
 **/
static int __init ixgbevf_init_module(void)
{
int ret;
printk(KERN_INFO “ixgbevf: %s - version %s\n“ ixgbevf_driver_string
       ixgbevf_driver_version);

printk(KERN_INFO “%s\n“ ixgbevf_copyright);

ret = pci_register_driver(&ixgbevf_driver); 
return ret;
}

module_init(ixgbevf_init_module);


3. 网卡驱动在PCI层的注册过程 
PCI的注册就是将PCI驱动程序挂载到其所在的总线的drivers链,
同时扫描PCI设备,将它能够进行驱动的设备挂载到driver上的devices链表上来,

3.1 pci_register_driver() 
从前面已经得知,ixgbevf_init_module()通过调用pci_register_driver()来对网卡驱动进行注册。
而通过阅读内核代码可知,pci_register_driver并非一个函数,而是一个宏,
它通过 __pci_register_driver()来完成驱动的注册。
__pci_register_driver()首先通过传入的参数struct pci_driver *ixgbevf_driver进行一些初始化工作,
具体如下:


/**
 * __pci_register_driver - register a new pci driver
 * @drv: the driver structure to register
 * @owner: owner module of drv
 * @mod_name: module name string
 * 
 * Adds the driver structure to the list of registered drivers.
 * Returns a negative value on error otherwise 0. 
 * If no error occurred the driver remains registered even if 
 * no device was claimed during registration.
 */
int __pci_register_driver(struct pci_driver *drv struct module *owner
const char *mod_name)
{
int error;

/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
drv->driver.owner = owner;
drv->driver.mod_name = mod_name;

spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);

/* register with core */
error = driver_register(&drv->driver);
if (error)
goto out;

error = pci_create_newid_file(drv);
if (error)
goto out_newid;

error = pci_create_removeid_file(drv);
if (error)
goto out_removeid;
out:
return error;

out_re

评论

共有 条评论