- 论坛徽章:
- 13
|
本帖最后由 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的情形呢? |
|