网卡驱动:stmmac DMA接收流程
1. dma buffer及zero-copy
在打开网卡时,stmmac_init_rx_buffers()函数负责分配dma buffer。
static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,int i, gfp_t flags, u32 queue)
{struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];struct sk_buff *skb;skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);if (!skb) {netdev_err(priv->dev,"%s: Rx init fails; skb is NULL\n", __func__);return -ENOMEM;}rx_q->rx_skbuff[i] = skb;rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,priv->dma_buf_sz,DMA_FROM_DEVICE);if (dma_mapping_error(priv->device, rx_q->rx_skbuff_dma[i])) {netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);dev_kfree_skb_any(skb);return -EINVAL;}if (priv->synopsys_id >= DWMAC_CORE_4_00)p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[i]);elsep->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[i]);if ((priv->hw->mode->init_desc3) &&(priv->dma_buf_sz == BUF_SIZE_16KiB))priv->hw->mode->init_desc3(p);return 0;
}
1)skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); 分配skb
2)rx_q->rx_skbuff[i] = skb; 用于zero-copy,以后再接收软中断中直接使用rx_q->rx_skbuff[i],并交给上层协议处理
3)rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, priv->dma_buf_sz, DMA_FROM_DEVICE); 进行dma映射,得到rx_q->rx_skbuff_dma[i] 源地址(即物理地址)
4)p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[i]); 在des0设置源地址(即填充buffer地址)
2. 接收数据流程:
2.1. DMA产生中断,调用 stmmac_interrupt服务程序
2.2. stmmac_interrupt 通过调用 stmmac_dma_interrupt 处理DMA相关中断(包括发送和接收)。在stmmac_dma_interrupt中,通过NAPI机制触发软中断,调用stmmac_poll接收数据包。
2.3. 在stmmac_poll中调用如下代码收数据包
work_done = stmmac_rx(priv, budget, rx_q->queue_index);if (work_done < budget) {napi_complete_done(napi, work_done);stmmac_enable_dma_irq(priv, chan);}return work_done;
1)调用stmmac_rx接收,budget为循环读取dma descriptor(通过处理descriptor来获取数据包,每个descriptor对应一个数据包)的最大次数,work_done为实际循环的次数。
2)if (work_done < budget) 代表实际循环读取dma descriptor的次数小于最大次数budget,代表已经处理完所有需要被处理的descriptor,取完所有的数据包。这时,调用stmmac_enable_dma_irq()开启中断,再次接收数据。如果work_done = budget,代表可能还有数据包需要处理,那么这些数据包留到net_rx_action再次调用stmmac_poll时处理。
3)return work_done; 该返回值会被net_rx_action使用。
2.4. 在stmmac_rx中,循环收包,循环次数while (count < limit)。每次循环以DMA descriptor为处理单位,即每次循环时从一个descriptor指定的buffer读取一个数据包,再通过 napi_gro_receive 送给协议层,处理完后count++。这里limit = budget。
2.5. 调用 stmmac_rx_refill重新填充descriptor。
在触发DMA中断前,DMA已经将网卡收到的数据包搬到descriptor指定的buffer,而这个buffer又采用了zero-copy机制,所以直接将该buffer的地址copy给一个skb,再将此skb送到协议层处理,最后再调用 stmmac_rx_refill重新填充descriptor并设置buffer。之前descriptor指定的buffer地址已经被赋值给skb,由协议层负责该skb(buffer)的管理(释放内存等)。
2.6. 总结:
这里有三种“一次获取多个数据包”的情况
1)一次软中断可能会多次调用net_rx_action
2)net_rx_action可能会多次调用stmmac_poll
3)stmmac_poll处理多个descriptor
网卡驱动:stmmac DMA接收流程相关推荐
- udp数据报从网卡驱动到用户空间流程总结
附有相关介绍资料 NAPI驱动流程: 中断发生 -->确定中断原因是数据接收完毕(中断原因也可能是发送完毕,DMA完毕,甚至是中断通道上的其他设备中断) -->通过 ...
- 网卡驱动:stmmac DMA发送流程
1. 设置DAM buffer&descriptor,并启动DMA发送 在stmmac_xmit设置buffe r& descriptor,如下片段: if (likely(!is_j ...
- linux接收网络数据并存存储,Linux网络设备驱动之数据接收流程(六)
网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判断中断类型,如果为接收中断,则读取接收到的数据,分配 sk_buffer 数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区, ...
- linux 串口 dma,STM32 USART串口DMA 接收和发送流程详解
1.dma发送流程 1.配置DMA发送中断 - NVIC_Init 2.配置串口中断 - NVIC_Init 3.GPIO配置 - GPIO_Init 4.DMA发送配置 -DMA_Init DMA ...
- Linux 网卡驱动相关——03
紧接上一篇,这里简要介绍net_device 结构和网卡驱动框架. struct net_device 是一个比sk_buff 更复杂的结构,里面包含了与TCP/IP协议栈通信的接口函数,但是自从2 ...
- 【Linux高级驱动】如何分析并移植网卡驱动
dm9000的驱动分析 m9000_init platform_driver_register(&dm9000_driver); dm9000_probe /*获取平台数据*/ stru ...
- linux内核网络协议栈--数据包的接收流程(二十三)
网卡在接受数据包时会产生中断,即当 有一个以太网帧到来时,网卡向内核产生一次中断: CPU收到中断信号后,执行中断处理程序,中断处理程序会设置 缓冲区地址.DMA 地址等信息: 网卡通过DMA 方式将 ...
- arm平台linux的ethtool配置,ARM-Linux驱动--DM9000网卡驱动分析(四)
原标题:ARM-Linux驱动--DM9000网卡驱动分析(四) 硬件平台:FL2440 (S3C2440) 内核版本:2.6.35 主机平台:Ubuntu 11.04 内核版本:2.6.39 交叉编 ...
- 网卡驱动(hisi3536网卡驱动,以及stmmac层)
一:基本概念 应用程序最终以套接字的形式完成网络设备的接口.,对网络设备定义四个层次:网络协议接口层(数据包的发送接收,向网络层协议提供统一的数据包收发接口,舍得上层协议独立于具体的设备,(ip,ar ...
最新文章
- docker 启动sqlserver_在Docker上安装MSSQL(SQL Server)
- Windows Live Writer连接sharePoint博客时,有一个权限相关的BUG
- 如何订阅Form的自定义事件
- golang mysql proxy_mixer: 一个用go实现的mysql proxy
- 如何用Linux写c程序并编译运行
- 浅析人工智能的数学基础(文末送书!)
- flask使用tablib导出excel数据表
- 最长回文Manacher
- python pandas教程百家号_Pandas 常见的基本方法
- 【250期门诊集锦】痛并快乐着的正则表达式
- PBRT 学习:安装编译
- 经典机器学习系列(十三)【结构化学习】
- 使用JS完成一个简单的计算器功能
- windows mac谷歌浏览器跨域
- php过滤只匹配中英文字符串
- vue 管理系统顶部tags浏览历史实现
- 进入中国内地第31年的麦当劳 ,为什么还能不断吸引新消费人群?
- 官网下载QT不成功解决方案
- C++课程实训——银行系统
- 使用标准的接口和API导入料号
热门文章
- 是否应该立即将网站升级到Drupal 8?
- maven远程发布jar
- 【独家:震惊!——西城区所有学区优质度透解与大排名,泄密了!】
- Exchange 2013学习(六),脱机通讯簿
- puppet系列之nginx+php日志切割与salt结合使用
- 基于ASP.NET 3.5 Web Service 的JSON扩展应用
- 分享我做的博客园Skin(目前12个,最后更新时间2006-5-10 PM)
- 数据库中主键和外键的设计原则
- ajax headers 参数有什么用_动态爬虫(ajax)-爬取bilibili热门视频信息
- 成绩查询系统c语言,学生成绩查询系统C语言代码(分服务器端和客户端).doc