免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Minit

【原】Linux-千兆网卡驱动实现机制浅析 [复制链接]

论坛徽章:
0
发表于 2009-03-26 09:29 |显示全部楼层
原帖由 Minit 于 2009-3-25 22:54 发表
嗯。这个地方也是我一直没搞明白的地方,所以在前面会提出PCI总线地址与物理地址的关系,其实就是对DMA buffer和ring这块没理解清楚,经过您的提示,我大概明白了这个意思,也会再深入的分析下这块。:wink:

关于这块我也是一直非常迷糊,期盼LZ下1个精华.

论坛徽章:
0
发表于 2009-03-26 12:41 |显示全部楼层
原帖由 Minit 于 2009-3-25 20:11 发表
尚有不能明确的问题,希望大牛们能帮我解答:
1.PCI总线地址与网卡物理地址这两个之间的关系,我一直不是很清楚,所以以上的分析都未明确说明,在画图时都忽略了这部分细节;
2.DMA buffer在接收包和发包时这其中的ring是如何详细调度的;


我不是大牛,但是以前做过无线网卡的驱动,所以可以回答你的问题

以发包为例。在e1000_setup_tx_resources时,通过pci_alloc_consistent分配了一段物理内存用于存放tx descriptors, 网卡和CPU之间的关于发包的控制就是通过tx descriptors进行的。在随后的e1000_configure_tx中,会把这个tx ring buffer的dma地址和长度写到TDLEN和TDBA两个register里,这样网卡就知道了tx ring buffer的dma地址。
发包时,它先通过DMA读入tx descriptors,再根据tx desciptor里的信息:
1.  buffer_addr这是数据包的dma地址,根据这个地址,网卡通过DMA可以把数据包从主机内存读到板卡上的memroy里
2. 控制信息:如何处理这个数据包,要不要作hw checksum等等

在e1000_xmit_frame中,主要的工作就是,找到相应的tx ring buffer,根据next_to_use找到相应空闲的tx slot,把network stack传下来的skb作相应的映射(e1000_tx_map, 通过pci_map_single得到sk_buffer->data的dma address),最后通过e1000_tx_queue,把数据包的dma地址写到tx descriptor的buffer_addr中,再把next_to_use写到相应的register中(tx_ring->tdt)。写入这个register后,网卡就会知道有新的包要发送,它就启动DMA先读入tx descriptor, 再读入数据包,最后把包发送出去。

数据包发送完成后,网卡会把发送状态更新到tx descriptor中,并中断cpu,在e1000_clean_tx_irq中,会根据tx_descriptor中的发送状态,去释放相应的skb。

关于pci_alloc_consistent, pci_map_single可以参考Documentation/DMA-mapping.txt文档。

论坛徽章:
0
发表于 2009-03-26 12:52 |显示全部楼层
>>>>网卡通过DMA可以把数据包从主机内存读到板卡上的memroy里
LZ的可不可详细点讲将DMA,网卡,总线,CPU的关系?虽然微机原理也有讲过,仍然感觉不清楚.

论坛徽章:
0
发表于 2009-03-26 13:19 |显示全部楼层
原帖由 eexplorer 于 2009-3-26 12:41 发表

1.  buffer_addr这是数据包的dma地址,根据这个地址,网卡通过DMA可以把数据包从主机内存读到板卡上的memroy里
2. 控制信息:如何处理这个数据包,要不要作hw checksum等等.



1. 对于e1000网卡rx和tx各有一个FIFO,DMA应该在host memory和FIFO之间做的。
例如,rx FIFO满了,再进来的包,只能被drop掉了。

2. e1000g的可以分data descritpor和context descriptor,context  descriptor就是所谓存控制信息的地方,hw checksum, tso都用这个东东。

[ 本帖最后由 Solaris12 于 2009-3-26 13:22 编辑 ]

论坛徽章:
0
发表于 2009-03-26 13:21 |显示全部楼层
原帖由 epegasus 于 2009-3-26 12:52 发表
>>>>网卡通过DMA可以把数据包从主机内存读到板卡上的memroy里
LZ的可不可详细点讲将DMA,网卡,总线,CPU的关系?虽然微机原理也有讲过,仍然感觉不清楚.


建议你看看书,然后问出具体的问题来

论坛徽章:
0
发表于 2009-03-26 13:25 |显示全部楼层
原帖由 eexplorer 于 2009-3-26 12:41 发表


在e1000_xmit_frame中,主要的工作就是,找到相应的tx ring buffer,根据next_to_use找到相应空闲的tx slot,把network stack传下来的skb作相应的映射(e1000_tx_map,通过pci_map_single得到sk_buffer->data的dma address),最后通过e1000_tx_queue,把数据包的dma地址写到tx descriptor的buffer_addr中,再把next_to_use写到相应的register中(tx_ring->tdt)。写入这个register后,网卡就会知道有新的包要发送,它就启动DMA先读入tx descriptor, 再读入数据包,最后把包发送出去。...


所谓的 DMA address, 在这里就是DMA buffer的物理地址,DMA buffer是host memory, 所以就是一个host memory的物理地址。

论坛徽章:
0
发表于 2009-03-26 13:33 |显示全部楼层
原帖由 epegasus 于 2009-3-26 12:52 发表
>>>>网卡通过DMA可以把数据包从主机内存读到板卡上的memroy里
LZ的可不可详细点讲将DMA,网卡,总线,CPU的关系?虽然微机原理也有讲过,仍然感觉不清楚.


假设现在系统有1G 物理memroy,映射在0-1G的物理地址空间。

在intel x86 架构下,CPU要访问内存,需要将要访问的物理地址通过system front bus发给北桥中的memory controller。
要访问内存中 0x0那块memory的话,cpu会将0x0放在他的address bus,发送到memory controller.

PCI bus address的话是PCI device要访问内存所需要的地址。所以通常driver要告诉device一块memory的bus address,这样device自己内部的dma engine要作dma时,通过bus address可以访问到正确的memory。

在x86下,bus address == physical address,既device和CPU看到的physical memory mapping是一样的。所以virt_to_bus == virt_to_phy

有些架构下,bus address 和 physical address 不一样,既device要访问memory中0x0的那块地方,它需要一个不同的地址(比如有一个2G的偏移)0x80000000。这样的话,CPU如果要device去读memory 0x0那块地方的数据,就需要把0x80000000作为dma address发给device.

论坛徽章:
0
发表于 2009-03-26 13:40 |显示全部楼层
原帖由 Solaris12 于 2009-3-26 13:25 发表


所谓的 DMA address, 在这里就是DMA buffer的物理地址,DMA buffer是host memory, 所以就是一个host memory的物理地址。


在x86架构下,dma addr == physical addr。好像有别的架构两者不等。

论坛徽章:
0
发表于 2009-03-26 14:06 |显示全部楼层
原帖由 Solaris12 于 2009-3-26 13:21 发表


建议你看看书,然后问出具体的问题来

这个目前没有找到相关的书,明确的讲解DMA问题,可能讲的比较隐晦,我没反映过来,仅从微机原理的书上猜测:
DMA可以直接读取内存,并请求总线的传输,和CPU应该处于一个级别,但是CPU又可以通过IO端口控制DMA行为.

1.DMA主要是进行数据传输用的,那么将内存中的数据传到网卡上去,一个问题是如果控制总线?细节是怎么样?网卡设备又怎么通过总线提供给DMA读写的地址?

2.网卡设备接受到数据后又如何告诉DMA该传输该数据到内存?是先发中断到CPU,CPU控制DMA,还是直接就统治DMA了,等DMA传完了再由DMA发送中断到CPU.

特别是第一点十分困惑.

论坛徽章:
0
发表于 2009-03-26 14:09 |显示全部楼层
原帖由 eexplorer 于 2009-3-26 13:40 发表


在x86架构下,dma addr == physical addr。好像有别的架构两者不等。


我说的就是x86。 x86上要支持IOMMU了,DMA address就会是虚拟地址。

如果你看Solaris的DMA接口的实现,就会发现,SPARC版的是DVMA不是DMA, 因为SPARC早就是用IOMMU了。

未来IOMMU是发展方向,特别是虚拟化。

[ 本帖最后由 Solaris12 于 2009-3-26 14:16 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP