Linux Ethernet Device driver 数据结构和软件流程

Tx/Rx Buffer Descriptor结构

1. Ethernet device是PCIe Device, 其hardware registers是在PCIe Bar_0 Space上;
2.Ethernet device的DMA收发数据模块有Tx TDBAH/TDBAL Registers和 Rx有Register RDBAH/RDBAL Registers用于存放hardware Tx/Rx Buffer Descriptor;
3.Ethernet驱动程序需要为Tx/Rx Buffer Descriptors分配phy-mem-address,并配置给DMA Tx TDBAH/TDBAL和Rx RDBAH/RDBAL Registers; 驱动程序需要将phy-mem-address映射为virt-address供软件读写数据使用;
4.Ethernet驱动程序建立了tx_ring/rx_ring来维护大量data收发的Tx/Rx Buffer_Descriptors的状态;
5.关于发送TX的Buffer Descriptor的配置, tx_ring->dma是Tx buffer descriptor在主机里的phy-mem-address;该地址处存放了数据结构tx_desc的集合;

(1)e1000_setup_tx_resources()
申请tx_ring->dma地址(phy address);
映射到virt_address, 设置给txdr->desc, 这是TX Buffer Descriptor的数据结构, 软件访问txdr->desc也就是访问DMA的Tx Buffer Descriptor;
e1000_setup_tx_resources(){
   txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, GFP_KERNEL);
(2)e1000_open()
调用的e1000_configure_tx()里, 将tx_ring.dma配置到TX DMA TDBAH/TDBAL Registers里;
(3)在Ethernet驱动发送函数e1000_xmit_frame()里, 调用e1000_tx_map()将上层skb->data的数据map到tx_ring的buffer_info[]->dma里;
buffer_info->dma = dma_map_single(&pdev->dev,  skb->data + offset, size, DMA_TO_DEVICE);
buffer_info->dma是phy address;
skb->data是上层软件下发的virt-address;
(4)e1000_xmit_frame()调用e1000_tx_queue()函数, 将tx_ring的buffer_info[]的信息设置给Tx Buffer Descriptor的结构txdr->desc:
txdr->desc->buffer_addr是skb->data的phy-mem-address;

6.关于接收Rx 的Buffer Descriptor的配置

(1)e1000_setup_rx_resources()
申请rx_ring->dma地址(phy address);
映射到virt_address, 设置给rxdr->desc, 这是RX Buffer Descriptor的数据结构, 软件访问rxdr->desc也就是访问DMA的Rx Buffer Descriptor;
e1000_setup_tx_resources(){
rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,GFP_KERNEL);}
(2)e1000_open()调用的e1000_configure_rx()里, 将tx_ring.dma配置到RX DMA RDBAH/RDBAL Registers里;
(3)在e1000_alloc_rx_buffers()里, 申请数据块内存data, 映射到phy-mem-address, 配置到buffer_info->dma(phy-mem-address), 再配置到rx_desc->buffer_addr里;

Linux Ethernet Device Driver软件流程

1. Linux Ethernet driver的init函数
module_init(e1000_init_module);
在e1000_init_module(void)函数里, 调用pci_register_driver(&e1000_driver)来注册ethernet driver;
2.在e1000_probe()函数里:
(1)找出该PCIe device(ethernet device)的PCIe Bar空间的bitmask,比如bar_0有效,那么bit_0设置为1, bar_2有效, 那么bit_2为1; 总共6个Bar Spaces;
(2)为各Bar Spaces申请PCIe IO Space资源,并标识申请到的资源为”已占用”;
申请成功后, 可用pci_iomap映射资源到内核虚拟地址空间;
(3)为ethernet device分配数据结构net_device *netdev;
(4)对PCIe device(ethernet device)的Bar Space做ioremap供软件访问Bar Space上的ethernet device的hardware registers;
(5)设置ethernet hardware的功能,比如copper/fibre接口类型, pci接口, mac类型等;
(6)调用dma_set_mask_and_coherent()设置DMA地址掩码;
(7)挂接e1000_netdev_opsh函数集到netdev->netdev_ops上;
(8)挂接e1000_ethtool_ops函数集到netdev->ethtool_ops上;
(9)调用netif_napi_add()函数挂接驱动实现的poll函数以处理数据包e1000_clean();
(10)当ethernet device收到数据packet后触发hardware中断, 中断处理会调用napi_schedule,切换到poll模式以避免频繁中断;
(11)调用e1000_sw_init()
(12)调用e1000_reset_hw()来reset Ethernet device;
(13)初始化延迟工作
INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog);INIT_DELAYED_WORK(&adapter->fifo_stall_task,                       e1000_82547_tx_fifo_stall_task);
INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task);
INIT_WORK(&adapter->reset_task, e1000_reset_task);
(14)调用e1000_reset()来reset e1000 ethernet device;
 

3.Ethernet Device Driver发送函数e1000_xmit_frame()
调用e1000_tx_map()将上层skb->data映射到phy-mem-address, 放到tx_ring的buffer_info[].dma里调用e1000_tx_queue()将buffer_info.dma放到tx_desc.buffer_addr里, tx_ring.tx_desc[0]的phy-mem-address是配置在DMA Tx TDBAH/TDBAL Registers里, 启动DMA从tx_desc[].buffer_addr里取data, 发送到HW Fifo里;

4.Ethernet Device Driver接收data
数据结构e1000_adapter->clean_rx挂接了e1000_clean_rx_irq()函数作为ISR handling函数;
Ethernet设备DMA将data送至rx_desc[].buffer_addr(phy-mem-addr)后, 发送Irq给主机;
rx_ring.buffer_info[].rxbuf.data是rx_desc[].buffer_addr的virt-address;
当DMA将data送至rx_desc[].buffer_addr这个phy-mem-addr后, 软件读rx_ring.buffer_info[].rxbuf.data这个virt-address获取data, 读取rx_desc的length field获取length;
使用data/length创建skb buffer, 发送至上层软件;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值