8139网卡驱动问题
RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));这条语句应该是更新读包地址,但为什么要把偏移量减16呢?想来想去可能是skb_buffer要16字节的IP头,但是前面已经通过skb_reserve (skb, NET_IP_ALIGN)预留了空间。
请牛人解释一手! 我感觉你没仔细看代码就来问了,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实在想不出是做什么。这些计算可能要能看到网卡的硬件说明书才能理解吧。 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字节,猜想是不是也为了对齐?只是猜想,网上找了好多帖都没人解释一手。 这个问题和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 编辑 ] 原帖由 zoorror 于 2009-7-30 15:45 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
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应该和这个对齐没什么关系。
页:
[1]