免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1795 | 回复: 4
打印 上一主题 下一主题

8139网卡驱动问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-30 12:44 |只看该作者 |倒序浏览
RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));这条语句应该是更新读包地址,但为什么要把偏移量减16呢?
想来想去可能是skb_buffer要16字节的IP头,但是前面已经通过skb_reserve (skb, NET_IP_ALIGN)预留了空间。
请牛人解释一手!

论坛徽章:
0
2 [报告]
发表于 2009-07-30 14:56 |只看该作者
我感觉你没仔细看代码就来问了,IP头不是16个字节,至少要20个,而且这里处理的指向rx_ring里面的一个偏移位置,和skb_buffer没什么关系,后者的保留通常是为了把IP头对齐到4字节位置上。

从代码看8139的驱动没有直接分配一些sk_buff,并把它里面的位置设置为DMA的地址,而是在创建设备时在设备结构中固定申请了buffer(在rtl8139_open中)
    tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
                       &tp->rx_ring_dma, GFP_KERNEL);


你说的地方其实是找到rx_ring里面的位置并且拷贝到新申请的sk_buff里面。拷贝结束之后相当于这个包被“吃”掉了,所以要更新ring buffer的“读指针”。这里rx_size + 4 + 3中+4开始我开始以为和FCS有关,但就算有前面的pkt_size = rx_size - 4;感觉rx_size中应该包含了它,的+3以括号外的& 3是为了进行4字节对齐;下面的-16实在想不出是做什么。这些计算可能要能看到网卡的硬件说明书才能理解吧。

论坛徽章:
0
3 [报告]
发表于 2009-07-30 15:45 |只看该作者
pkt_size = rx_size - 4,是把接收包前面4字节去掉(低2字节状态,高2字节长度)就得到数据包长度,至于双字节对齐的方法能看懂,关键就是这个-16看不懂,因为根据后面的代码skb_reserve (skb, NET_IP_ALIGN);/* 16 byte align the IP fields. */,最有可能与这个NET_IP_ALIGN有关系了,正好是16字节,猜想是不是也为了对齐?只是猜想,网上找了好多帖都没人解释一手。

论坛徽章:
0
4 [报告]
发表于 2009-07-30 17:00 |只看该作者
这个问题和ip头没什么关系。是和8139 DMA硬件相关的,只能看硬件手册。但可恨的是,硬件手册里根本没有描述这一问题!!!
我感觉应该是这样的:
首先,cur_rx应该是网卡接收到的数据包的总长度,是一个unsigned int型变量。而RTL_W16 (RxBufPtr, (u16) (cur_rx - 16))
只是将cur_rx的低16位写入RxBufPtr寄存器。如果我手册没看错的话,这个寄存器是给网卡DMA用的,DMA写接收缓冲区时不能超过这一位置。这很像循环缓冲区的读指针。
根据8139手册对Rx Buffer的描述,接收缓冲区的长度是8K+16byte, 16K+16byte, 32K+16byte或64K+16byte,也就是说,8139在使用时预留了16字节。这16字节是为了避免DMA操作越界而保留的。 在接收frame时,cur_rx是缓冲区中下一个frame的起始地址,cur_rx到(cur_rx-16)是reserved的区域, DMA最多写到(cur_rx-16)就必须停了(缓冲区满)

[ 本帖最后由 飞羽zhang 于 2009-7-30 17:01 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2009-07-30 18:41 |只看该作者
原帖由 zoorror 于 2009-7-30 15:45 发表
pkt_size = rx_size - 4,是把接收包前面4字节去掉(低2字节状态,高2字节长度)就得到数据包长度,至于双字节对齐的方法能看懂,关键就是这个-16看不懂,因为根据后面的代码skb_reserve (skb, NET_IP_ALIGN);/* ...


我感觉这里的注释有问题吧,你看一下skbuff.h中的描述:
/*
* CPUs often take a performance hit when accessing unaligned memory
* locations. The actual performance hit varies, it can be small if the
* hardware handles it or large if we have to take an exception and fix it
* in software.
*
* Since an ethernet header is 14 bytes network drivers often end up with
* the IP header at an unaligned offset. The IP header can be aligned by
* shifting the start of the packet by 2 bytes. Drivers should do this
* with:
*
* skb_reserve(NET_IP_ALIGN);

*
* The downside to this alignment of the IP header is that the DMA is now
* unaligned. On some architectures the cost of an unaligned DMA is high
* and this cost outweighs the gains made by aligning the IP header.
*
* Since this trade off varies between architectures, we allow NET_IP_ALIGN
* to be overridden.
*/
#ifndef NET_IP_ALIGN
#define NET_IP_ALIGN        2
#endif


不知道为啥驱动代码中写了个16。这个前面保留两个字节的用法是很常见的,主要是Ethernet头一般是字节或short访问,并且使用相对少,所以主要是对齐IP及后面的TCP头。这里的16应该和这个对齐没什么关系。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP