请问RTL8139在接收好一个package后,会自动继续接收下一个吗?
本帖最后由 karma303 于 2016-05-14 18:49 编辑想象一个情景:
RTL8139从网线上完整的收到一个package,放在ring buffer里。这时当然会触发中断(ROK)。
但是,cpu很忙(例如处在一个critial area的cli状态),无法及时去读这个package。
那么,网卡会继续从网线上接收数据吗?
还是说,网卡在cpu响应这次中断之前,会暂停接收数据?
如果继续接收,那么新收到的package是放在RBSTART位置上,覆盖前一个package?还是接着放到第一个package后面呢?
如果接着放在第一个package后面,最后不断累积,会不会ring buffer溢出呢?或者说,硬件写入模式是回绕的话,是不是可能最终还是可能把第一个包给覆盖呢?
我产生这个疑惑,主要是因为linux内核里针对8139的这段驱动代码: while((readb(ioaddr + CR) & RxBufEmpty) == 0)
{
unsigned int rx_status;
unsigned short rx_size;
unsigned short pkt_size;
struct sk_buff *skb;
if(tp->cur_rx > RX_BUF_LEN)
tp->cur_rx = tp->cur_rx % RX_BUF_LEN;
/* TODO: need to convert rx_status from little to host endian
* XXX: My CPU is little endian only
*/
rx_status = *(unsigned int*)(tp->rx_ring + tp->cur_rx);
rx_size = rx_status >> 16;
/* first two bytes are receive status register
* and next two bytes are frame length
*/
pkt_size = rx_size - 4;
/* hand over packet to system */
skb = dev_alloc_skb (pkt_size + 2);
if (skb) {
skb->dev = dev;
skb_reserve (skb, 2); /* 16 byte align the IP fields */
eth_copy_and_sum(
skb, tp->rx_ring + tp->cur_rx + 4, pkt_size, 0);
skb_put (skb, pkt_size);
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
else {
LOG_MSG("Memory squeeze, dropping packet.\n");
tp->stats.rx_dropped++;
}
/* update tp->cur_rx to next writing location* /
tp->cur_rx = (tp->cur_rx + rx_size + 4 + 3) & ~3;
/* update CAPR */
writew(tp->cur_rx, ioaddr + CAPR);
}
}大家注意到没有,这是用一个while循环,意思是,ring buffer里可能不止一个package里。
但是!! 8139每收到一个package就会报告给cpu一个ROK中断,然后就被处理掉了。 所以,ring buffer里怎么可能出现堆积了两个以上的package的情形呢? 放在缓存队列啊, ring buffer 如果按照pkt arrive的速度去interrupt cpu,那cpu基本上就啥都做不了了。
NAPI本来就是关了中断去轮询,只有ring里有很多报文去轮询才有意义么。
页:
[1]