Linux内核里I.MX6ULL平台的FEC(快速以太网控制器)网络驱动fec_netdev_ops操作集:
一、核心“指令集”:fec_netdev_ops操作集
它就像网络驱动的“操作手册”,把协议栈、用户指令和硬件操作绑定在一起。
在`fec_probe()`函数里完成注册后,不管是用户执行`ifconfigeth0 up`,还是内核协议栈要发数据,都靠它找到对应的驱动函数。具体涵盖:
-网卡启停:打开网卡调用`fec_enet_open`,关闭调用`fec_enet_close`;
- 数据收发:上层发数据靠`fec_enet_start_xmit`,接收数据适配NAPI机制;
- 配置管理:修改MTU、设置组播、校验MAC地址、处理超时等功能,都对应了操作集里的具体回调。
二、网卡开启:fec_enet_open()的执行流程
当你执行命令打开网卡时,这个函数会按顺序完成硬件初始化和资源准备,核心步骤有5个:
1. 给硬件通电:调用`fec_enet_clk_enable`,开启ENET模块的时钟,给硬件供电;
2. 准备数据通道:调用`fec_enet_alloc_buffers`,为发送和接收队列申请环形缓冲区,搭建数据存储的“通道”;
3. 重启硬件引擎:调用`fec_restart`,重置硬件寄存器,配置好MAC地址和缓冲区指针,让硬件进入待命状态;
4. 连接物理层芯片:调用`fec_enet_mii_probe`,通过MDIO总线扫描PHY芯片(比如常用的LAN8720A),建立物理层连接;
5. 启动收发功能:开启NAPI调度,启动PHY芯片的自动协商,同时激活发送队列,允许上层协议栈开始发数据。
要注意:要是PHY芯片探测失败,比如网线没插、地址配错,网卡就没办法正常启用,这也是常见的驱动故障点。
三、网卡关闭:fec_enet_close()的资源清理
关闭网卡时,这个函数会把开启时占用的资源彻底释放,避免内存泄漏,流程分5步:
1. 停掉PHY芯片:调用`phy_stop`,停止PHY的自动协商,让物理层停摆;
2. 关闭收发调度:禁用NAPI调度,同时关闭发送队列,停止数据收发流程;
3. 关停硬件模块:调用`fec_stop`,清空硬件寄存器,停止DMA传输,把硬件完全关闭;
4. 断开PHY连接:调用`phy_disconnect`,断开和PHY芯片的关联,避免无效访问;
5. 释放所有资源:关闭ENET时钟,清除电源管理请求,最关键的是调用
`fec_enet_free_buffers`,释放之前申请的环形缓冲区,把所有资源彻底回收。
四、数据发送:fec_enet_start_xmit()的核心逻辑
这个函数是协议栈向硬件发送数据的“中转站”,负责把上层传来的`sk_buff`数据交给硬件发送,核心流程如下:
1. 选择发送队列:根据数据的队列映射,从多个发送队列里挑出对应的队列;
2. 区分数据类型发送:判断数据是否支持GSO/TSO。如果支持,就用`fec_enet_txq_submit_tso`,靠硬件把大包拆分;不支持就调用`fec_enet_txq_submit_skb`,直接把数据交给硬件;
3. 动态流控:用`fec_enet_get_free_txdesc_num`查看剩余的发送描述符数量。要是剩余量低于设定阈值,就调用`netif_tx_stop_queue`暂停发送,通知上层暂时停发数据,等发送完成中断里再恢复发送队列,避免硬件处理不过来。
简单说,它能自动判断数据类型,还能通过流控平衡软硬件处理能力,保证发送稳定。
五、中断与NAPI:数据收发的“前后半场”
I.MX6ULL的FEC驱动用NAPI机制实现高效收发,把工作拆成“中断快处理”和“轮询慢处理”两部分,避免中断太多拖垮CPU:
1. 中断上半场:快速调度,不做重活
中断服务函数`fec_enet_interrupt`只负责3件事:
- 读ENET的中断状态寄存器,搞清楚发生了什么中断;
- 清中断标志,避免重复触发;
- 统计中断信息,要是有数据接收或发送事件,就调用`napi_schedule_prep`检查NAPI状态,符合条件就禁用相关中断,再启动NAPI调度,为后续处理铺路。
它不处理具体数据,只做调度,防止中断太多影响性能。
2. NAPI下半场:专注收发,高效处理
NAPI的轮询函数`fec_enet_rx_napi`接过接力棒,做核心的数据收发:
- 调用`fec_enet_rx`,在设定的轮询预算内,从硬件接收数据,尽可能多收包;
- 调用`fec_enet_tx`,处理发送完成后的清理工作,比如释放发完的数据缓冲区;
- 要是收包数量没到预算,说明暂时没更多数据,就调用`napi_complete`结束本轮轮询,同时重新使能硬件中断,回到中断驱动模式,等待下次触发。
六、调试避坑:关键注意点
想搞定FEC驱动,这几个关键点要特别留意:
- 设备树配置:要检查pinctrl引脚复用、时钟配置、PHY连接路径有没有写对;
- PHY匹配:PHY的地址必须和硬件实际一致,一般是0或1,错了就找不到PHY;
- MDIO时序:用RMII模式时,MDIO的时序要满足芯片要求,不然和PHY通信会出问题;
- NAPI预算:轮询预算设太小会影响收包效率,设太大会一直占用CPU,需要根据硬件性能微调。
Linux网络驱动靠操作集,统筹所有操作,开启时搭好硬件框架,关闭时收尾资源,发送靠流控保稳定,接收靠NAPI提效率,再加上设备树和PHY的正确配置,就能实现稳定的网络通信。