免费注册 查看新帖 |

Chinaunix

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

[网络子系统] e100的RFD是什么意思? [复制链接]

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-01-16 14:14 |只看该作者 |倒序浏览
本帖最后由 chishanmingshen 于 2013-01-16 14:24 编辑

e100_rx_alloc_skb()中的RFD到底是什么意思???根el有何关系?求助...
  1.         /* Link the RFD to end of RFA by linking previous RFD to
  2.          * this one.  We are safe to touch the previous RFD because
  3.          * it is protected by the before last buffer's el bit being set */
  4.         if (rx->prev->skb) {
  5.                 struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
  6.                 put_unaligned(cpu_to_le32(rx->dma_addr), &prev_rfd->link);<------为何把当前rx的dma_addr保存在上一个rx的rfd中???
  7.         }
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-01-16 23:17 |只看该作者
RFD应该是接收描述符的简称(Receive Frame Descriptor),至于为啥要把当前rx的dma_addr保存在上一个rx的rfd中,是因为网卡的接收描述符的DMA缓冲块是环形缓冲区,这样就建立了一个环形链。

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2013-01-17 09:37 |只看该作者
那这个跟el有啥关系?请指点...回复 2# frogsu


   

论坛徽章:
0
4 [报告]
发表于 2013-01-17 12:37 |只看该作者
首先你贴出来的代码里是关于建立环形缓冲区的,提到了el bit位设置问题。"We are safe to touch the previous RFD because it is protected by the before last buffer's el bit being set." 从这句话字面意思是说在el bit 被设置之前,可以安全使用其RFD。猜测el bit应该是关于e100的接收包操作相关的操作,估计表达接收中、或者接收完成之类的。我之前接触e1000e驱动,感觉比较像。呵呵,具体的你还是参考参考e100的datasheet。

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2013-01-17 12:44 |只看该作者
*
*        In order to keep updates to the RFD link field from colliding with
*        hardware writes to mark packets complete, we use the feature that
*        hardware will not write to a size 0 descriptor and mark the previous
*        packet as end-of-list (EL).   After updating the link, we remove EL
*        and only then restore the size such that hardware may use the
*        previous-to-end RFD.
*


e100.c中的注释, 我没看不明白...

论坛徽章:
0
6 [报告]
发表于 2013-01-18 00:16 |只看该作者
      查阅了网上的资料:http://blog.csdn.net/bekars/article/details/1066360
      知道了原来e100使用了共享内存方式来接收数据,定义了一个RFD。所以,在接收数据时,只需要把接收数据的skb->data(第一个RFD)的物理地址写入共享控制模块的指针里,网卡就能自动根据这个地址进行DMA,并且根据RFD中link域,找下个RFD。
     至于这句话的意思,我的理解如下:
     为了防止RFD的link域更新与硬件写包完成相冲突,可利用硬件不会写长度为0或EL置位的RFD的特征。所以,在更新RFD的link域后,需恢复RFD的长度,这样硬件就可以重新利用整块RFD空间了。(不知道是否准确?!)

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2013-01-18 16:20 |只看该作者
有道理


  1. static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
  2.         unsigned int work_to_do)
  3. {
  4.         struct rx *rx;
  5.         int restart_required = 0, err = 0;
  6.         struct rx *old_before_last_rx, *new_before_last_rx;
  7.         struct rfd *old_before_last_rfd, *new_before_last_rfd;

  8.         /* Indicate newly arrived packets */
  9.         for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
  10.                 err = e100_rx_indicate(nic, rx, work_done, work_to_do);
  11.                 /* Hit quota or no more to clean */
  12.                 if (-EAGAIN == err || -ENODATA == err)
  13.                         break;
  14.         }


  15.         /* On EAGAIN, hit quota so have more work to do, restart once
  16.          * cleanup is complete.
  17.          * Else, are we already rnr? then pay attention!!! this ensures that
  18.          * the state machine progression never allows a start with a
  19.          * partially cleaned list, avoiding a race between hardware
  20.          * and rx_to_clean when in NAPI mode */
  21.         if (-EAGAIN != err && RU_SUSPENDED == nic->ru_running)
  22.                 restart_required = 1;

  23.         old_before_last_rx = nic->rx_to_use->prev->prev;
  24.         old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;

  25.         /* Alloc new skbs to refill list */
  26.         for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
  27.                 if(unlikely(e100_rx_alloc_skb(nic, rx)))
  28.                         break; /* Better luck next time (see watchdog) */
  29.         }

  30.         new_before_last_rx = nic->rx_to_use->prev->prev;
  31.         if (new_before_last_rx != old_before_last_rx) {
  32.                 /* Set the el-bit on the buffer that is before the last buffer.
  33.                  * This lets us update the next pointer on the last buffer
  34.                  * without worrying about hardware touching it.
  35.                  * We set the size to 0 to prevent hardware from touching this
  36.                  * buffer.
  37.                  * When the hardware hits the before last buffer with el-bit
  38.                  * and size of 0, it will RNR interrupt, the RUS will go into
  39.                  * the No Resources state.  It will not complete nor write to
  40.                  * this buffer. */
  41.                 new_before_last_rfd =
  42.                         (struct rfd *)new_before_last_rx->skb->data;
  43.                 new_before_last_rfd->size = 0;
  44.                 new_before_last_rfd->command |= cpu_to_le16(cb_el);
  45.                 pci_dma_sync_single_for_device(nic->pdev,
  46.                         new_before_last_rx->dma_addr, sizeof(struct rfd),
  47.                         PCI_DMA_TODEVICE);

  48.                 /* Now that we have a new stopping point, we can clear the old
  49.                  * stopping point.  We must sync twice to get the proper
  50.                  * ordering on the hardware side of things. */
  51.                 old_before_last_rfd->command &= ~cpu_to_le16(cb_el);
  52.                 pci_dma_sync_single_for_device(nic->pdev,
  53.                         old_before_last_rx->dma_addr, sizeof(struct rfd),
  54.                         PCI_DMA_TODEVICE);
  55.                 old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
  56.                 pci_dma_sync_single_for_device(nic->pdev,
  57.                         old_before_last_rx->dma_addr, sizeof(struct rfd),
  58.                         PCI_DMA_TODEVICE);
  59.         }

  60.         if(restart_required) {
  61.                 // ack the rnr?
  62.                 iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
  63.                 e100_start_receiver(nic, nic->rx_to_clean);
  64.                 if(work_done)
  65.                         (*work_done)++;
  66.         }
  67. }

复制代码
old_before_last_rx和new_before_last_rx是什么关系?

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2013-03-08 11:49 |只看该作者
自己搞明白了,呵呵。

就是为了防止硬件读错最后一个元素,将该链表的倒数第二个元素做特殊处理:设置el标志。

结贴!

btw: 建议后来人不要看e100或8139的了,太老了,缺点多。。。


回复 7# chishanmingshen


   

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2013-03-08 11:52 |只看该作者
非常感谢!

发现这个帖子不是悬赏的,给不了你分数。。。。呵呵

回复 6# frogsu


   

论坛徽章:
0
10 [报告]
发表于 2013-03-08 15:47 |只看该作者
回复 8# chishanmingshen


不看老网卡看啥?上来就多对列等各种网络加速和负载减免的NB网卡驱动么?那一定更迷茫,呵呵。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP