kernel源代码版本:git-v3.16.39

1.初始化

e1000_init_module下pci_register_driver注册驱动,

在e1000_probe下,e1000_is_need_ioport为真时,执行

这两个ops如下:

二,网络设备打开

e1000_open是属于e1000_netdev_ops,

在e1000_setup_all_tx_resources下,

e1000_tx_ring和e1000_rx_ring注释如上,写满了。

那么在e1000_setup_tx_resources下,

从dma_alloc_coherent到dma_alloc_attrs,先通过dma_alloc_from_coherent进行内存申请

而在dma_declare_coherent_memory中,

调用dma_declare_coherent_memory只有ohci_hcd_sm501_drv_probe等,所以对于E1000,会执行if (!mem) return 0,dma_alloc_from_coherent申请失败

在intel_alloc_coherent下,

退回到e1000_setup_rx_resources,看接受缓存的处理如上。

e1000_configure配置网卡数据,其中 e1000_configure_tx,e1000_setup_rctl,e1000_configure_rx初始化了很多寄存器。对于看虚拟化下的实现很重要。

看e1000中断的申请和使能

e1000_request_irq申请中断

e1000_irq_enable使能中断,本质就是写e1000的IMS寄存器

三,e1000_xmit_frame发包接口

e1000_xmit_frame是e1000_netdev_ops下的调用函数,struct net_device_ops上的注释已经说明了

网络设备的发包是由dev_queue_xmit开始的,由__dev_queue_xmit调用dev_hard_start_xmit,执行ops->ndo_start_xmit(skb, dev)完成e1000下的发包动作。e1000_xmit_frame下关注的点是e1000_tx_map,其他的忽略,在e1000_tx_map下,填充tx_ring->buffer_info。

然后就是让网卡直接从该地址读取memory内容,即为网卡的DMA读取

另外一个函数是e1000_tx_queue,

e1000_tx_map之后将获取的dma地址存放到net ring下的发送包描述符中tx_desc->buffer_addr,剩下的工作就是硬件取包并发送了。

四,e1000_intr中断函数

屏蔽中断,然后刷新,E1000_WRITE_FLUSH本质是读取status状态,也就是PCI规范中的dalay传送方式。如果是Posted则无需刷新。

将e1000包的计数清空

调用网卡中断是e1000_netpoll,e1000_intr是在e1000_request_irq下进行初始化注册中断,e1000_netpoll归netpoll_poll_dev调用。e1000_intr在收到网卡中断后调用__napi_schedule(&adapter->napi),调用napi 轮询进行收包,__napi_schedule调用____napi_schedule,然后执行__raise_softirq_irqoff(NET_RX_SOFTIRQ),

在net_dev_init下

那么调用的函数是net_rx_action,下面执行work = n->poll(n, weight),在e1000_probe下时

netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);

那么最终执行的是e1000_clean。

五,e1000_clean收包接口

e1000_clean_tx_irq负责清理发送队列,将之前发送队列的map数据unmap,为下一次发送准备。

后面是adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget)

在e1000_configure_rx下,

同时在e1000_configure下,

接收队列被初始化

继续看e1000_clean_rx_irq,这个时候DMA已经完成了,data已经写入到指定地址了,


Linux E1000网络驱动源代码分析来自于OenHan

链接为:http://oenhan.com/linux-e1000-networking-driver

发表评论