Realtek 8126驱动分析第四篇——multi queue相关

Realtek 8126是 5G 网卡,因为和 8125 较为接近,第四篇从这里开始也无不可。本篇主要是讲 multi queue 相关,其他的一些内容在之前就已经提过,不加赘述。

1 初始化

1.1 rtl8126_init_one

从第一篇我们可以知道每个 PCI 驱动都注册了一个 probe() 方法,为设备寻找驱动就是调用其 probe() 方法,即 rtl8126_init_one。这里我们重点讲 multi queue 相关的内容。

1.1.1 rtl8126_init_board

/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev_mq(sizeof (*tp), R8126_MAX_QUEUES);

分配并设置以太网设备,这里的 R8126_MAX_QUEUES 指 TX 和 RX 都有这么多个 queue。

1.1.2 rtl8126_try_msi

该函数里主要是先确定了支援的 irq vector number,最关键的是 rtl8126_enable_msix 函数。这样内核就根据硬件能力分配了实际的 vector 即中断号。

static int rtl8126_enable_msix(struct rtl8126_private *tp)
{int i, nvecs = 0;struct msix_entry msix_ent[R8126_MAX_MSIX_VEC];/** 这里的entry表示设备支持的MSI-X表项索引(即设备硬件层面的中断条目编号)。* 例如,设备支持16个MSI-X中断,entry可以是0-15* 而vector表示系统范围内唯一的中断向量号(Interrupt Vector Number)。* 该向量号是CPU中断描述符表(IDT)的索引,用于在硬件触发中断时,CPU查找对应的中断处理函数*/for (i = 0; i < R8126_MAX_MSIX_VEC; i++) {msix_ent[i].entry = i;msix_ent[i].vector = 0;}/* 调用pci_enable_msix_range(),内核根据硬件能力和系统资源分配实际的vector,* 并回填到msix_entry.vector*/nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent,tp->min_irq_nvecs, tp->max_irq_nvecs);if (nvecs < 0)goto out;for (i = 0; i < nvecs; i++) {struct r8126_irq *irq = &tp->irq_tbl[i];irq->vector = msix_ent[i].vector;}out:return nvecs;
}

1.1.3 rtl8126_init_software_variable

这个函数主要是初始化一些变量,诸如 HwSuppNumTxQueues 和 HwSuppNumRxQueues。

这里要注意以下代码,这里调用内核限制设置了 rss queue 的数量上限。

/* 此例程应设置多队列设备默认使用的 RSS 队列数量的上限。*/
u8 rss_queue_num = netif_get_num_default_rss_queues();
tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)?rss_queue_num : tp->HwSuppNumRxQueues;

然后根据之前设置的变量的值,在 rtl8126_setup_mqs_reg 函数中,设置不同的 ring 对应的硬件寄存器的值,这里比较重要的就是如果支援 multi queue,那么每个 queue 对应的 descriptor start address 都要设置。另外对于 RX 还要额外设置 ISR 和 IMR。

在函数 rtl8126_set_ring_size 中,设置每个 ring 的 ring size 即 descriptor number。

最关键的就是函数rtl8126_init_rss。

void rtl8126_init_rss(struct rtl8126_private *tp)
{int i;/* 0~HwSuppIndirTblEntries对queue numbers取余,得到hash indirection table*/for (i = 0; i < rtl8126_rss_indir_tbl_entries(tp); i++)tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings);/* 该函数依赖内核的强随机数生成器,生成 RSS 哈希密钥*/netdev_rss_key_fill(tp->rss_key, RTL8126_RSS_KEY_SIZE);
}

1.1.4 rtl8126_init_napi

这个函数主要是为每一个 irq vector 注册napi的poll方法。在中断线程被触发后,内核会执行中断处理函数 ISR,进而进入软中断收包环节。而进入软中断,就会调用到这里注册的 poll 函数。

1.1.5 rtl8126_set_real_num_queue

通过合理设置实际队列数,可最大化利用多核CPU和硬件加速特性(如RSS),同时避免因配置不当导致的性能瓶颈或稳定性问题。

1.2 rtl8126_open

ndo_open 在 8126 驱动中就是 rtl8126_open,当网络设备转换为启动状态时,将调用此函数。

1.2.1 alloc desc

这两个函数初始化DMA描述符环形缓冲区,用于网卡收发包。

1.2.2 rtl8126_init_ring

int
rtl8126_init_ring(struct net_device *dev)
{struct rtl8126_private *tp = netdev_priv(dev);int i;/* 初始化ring的一些变量 */rtl8126_init_ring_indexes(tp);/* 初始化trx desc ring,并为tx ring设置 end of ring */rtl8126_tx_desc_init(tp);rtl8126_rx_desc_init(tp);for (i = 0; i < tp->num_tx_rings; i++) {struct rtl8126_tx_ring *ring = &tp->tx_ring[i];memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb));}for (i = 0; i < tp->num_rx_rings; i++) {struct rtl8126_rx_ring *ring = &tp->rx_ring[i];
#ifdef ENABLE_PAGE_REUSEring->rx_offset = R8126_RX_ALIGN;
#elsememset(ring->Rx_skbuff, 0x0, sizeof(ring->Rx_skbuff));
#endif //ENABLE_PAGE_REUSEif (rtl8126_rx_fill(tp, ring, dev, 0, ring->num_rx_desc, 0) != ring->num_rx_desc)goto err_out;rtl8126_mark_as_last_descriptor(tp, rtl8126_get_rxdesc(tp, ring->RxDescArray, ring->num_rx_desc - 1));}return 0;err_out:rtl8126_rx_clear(tp);return -ENOMEM;
}

1.2.3 rtl8126_alloc_irq

该函数主要是为每个 irq 设置 中断处理函数 iSR rtl8126_interrupt_msix,并利用 request_irq 注册中断。

1.2.4 rtl8126_hw_config

void rtl8126_config_rss(struct rtl8126_private *tp)
{if (!tp->EnableRss) {rtl8126_disable_rss(tp);return;}_rtl8126_config_rss(tp);
}

着重就是讲这个函数。

void _rtl8126_config_rss(struct rtl8126_private *tp)
{/* 设置寄存器 RSS_CTRL_8125 的值 */_rtl8126_set_rss_hash_opt(tp);/* 把之前得到的 redirection table 写进寄存器里 */rtl8126_store_reta(tp);/* 将之前内核生成的 rss key 写进寄存器里 */rtl8126_store_rss_key(tp);
}

rtl8126_set_rx_q_num 和 rtl8126_set_tx_q_num 要向寄存器里写入 TRX queue 的数目。

到此为止,关于 multi queue 的所有初始化就已经完成了。

2 收发包

2.1 收包

如果有数据包过来,并且触发了硬件中断,那么就会调用 rtl8126_interrupt_msix 函数,首先判断是否是 link change,这显然不是,然后就会 disable hw interrupt,随后要转入软中断。

进而就会调用对应的 poll 函数,这里我们不去区分 mapping 方式,最终 RX 都会调用到函数 rtl8126_rx_interrupt。这里其他的我们不用去管,只要看一个函数 rtl8126_rx_hash。

以 rtl8126_rx_hash_v3 为例,关于 hash 的信息保存在 descriptor 中,提取出 hash 值后,赋给 skb->hash,至此工作完成。

2.2 发包

发包的部分更为简单,发包函数 rtl8126_start_xmit 会通过 skb_get_queue_mapping 来选择用哪个 queue,得出 queue_mapping 用作 queue number 即可。这里的 skb->queue_mapping 是上层计算出的结果。

到此为止,主要的 multi queue 相关的就已经完成了,但是在 linux driver 中,还有通过 ethtool 来修改 rss 相关的 code 需要介绍。

3 ethtool

.get_rxnfc => rtl8126_get_rxnfc 该函数用于返回 rx ring number 以及 返回 rss hash option。

.set_rxnfc >= rtl8126_set_rxnfc 该函数用于设置 rss hash option,这里要注意,UDP RSS 是需要通过这个函数来开启的,default 不支持。

.get_rxfh_indir_size >= rtl8126_rss_indir_size 该函数用于返回 indirection table 的 size。

.get_rxfh_key_size >= rtl8126_get_rxfh_key_size 该函数返回 rss_key 的 size。

.get_rxfh >= rtl8126_get_rxfh 该函数用于获得 indirection table 和 rss_key。

.set_rxfh >= rtl8126_set_rxfh 该函数用于将 ethtool 给的 indirection table 和 rss_key 写入寄存器,采用它们。

如果觉得这篇文章有用的话,可以点赞、评论或者收藏,万分感谢,goodbye~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/82893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用PHP对接日本股票市场数据

本文将介绍如何通过StockTV提供的API接口&#xff0c;使用PHP语言来获取并处理日本股票市场的数据。我们将以查询公司信息、查看涨跌排行榜和实时接收数据为例&#xff0c;展示具体的操作流程。 准备工作 首先&#xff0c;请确保您已经从StockTV获得了API密钥&#xff0c;并且…

爬虫工具与编程语言选择指南

有人问爬虫如何选择工具和编程语言。根据我多年的经验来说&#xff0c;是我肯定得先分析不同场景下适合的工具和语言。 如果大家不知道其他语言&#xff0c;比如JavaScript&#xff08;Node.js&#xff09;或者Go&#xff0c;这些在特定情况下可能更合适。比如&#xff0c;如果…

C语言while循环的用法(非常详细,附带实例)

while 是 C 语言中的一种循环控制结构&#xff0c;用于在特定条件为真时重复执行一段代码。 while 循环的语法如下&#xff1a; while (条件表达式) { // 循环体&#xff1a;条件为真时执行的代码 } 条件表达式&#xff1a;返回真&#xff08;非 0&#xff09;或假&#x…

1.短信登录

1.0 问题记录 1.0.1 redis 重复 token 问题 每次用户登录时&#xff0c;后端会创建一个新的 token 并存入 Redis&#xff0c;但之前登录的 token 还没有过期。这可能会导致以下问题&#xff1a; 1. Redis 中存在大量未过期但实际已不使用的 token2. 同一用户可能有多个有效 …

需求与技术实现不匹配,如何协调

协调需求与技术实现不匹配问题&#xff0c;需要加强技术参与需求阶段、推动架构与需求同步设计、建立跨职能沟通机制&#xff0c;其中加强技术参与需求阶段是最关键的一步。 需求如果脱离技术实际&#xff0c;就容易导致实现困难、资源浪费甚至项目失败。根据麦肯锡的一项研究&…

java每日精进 5.11【WebSocket】

1.纯Websocket实现消息发送 1.1一对一发送 前端 用户在输入框输入消息内容(sendText) 选择特定接收用户(sendUserId) 点击发送按钮触发handlerSend方法 构造消息内容JSON: {text: "Hello", // 消息内容toUserId: 123 // 目标用户ID } 包装为WebSocket标准格式…

【NextPilot日志移植】params.c解析

params.c 参数说明 params.c 文件的主要作用是定义与 SD卡日志记录 相关的参数。这些参数用于配置日志记录的行为&#xff0c;包括日志记录的时间、内容、存储管理以及加密设置等。 1. UTC 偏移量 (SDLOG_UTC_OFFSET) PARAM_DEFINE_INT32(SDLOG_UTC_OFFSET, 0);用途&#xf…

jFinal 使用 SolonMCP 开发 MCP(拥抱新潮流)

MCP 官方的 java-sdk 目前只支持 java17。直接基于 mcp-java-sdk 也比较复杂。使用 SolonMCP&#xff0c;可以基于 java8 开发&#xff08;像 MVC 的开发风格&#xff09;&#xff0c;且比较简单。 1、SolonMCP 简介 SolonMCP&#xff08;全称&#xff1a;solon-ai-mcp&#…

“端 - 边 - 云”三级智能协同平台的理论建构与技术实现

摘要 随着低空经济与智能制造的深度融合&#xff0c;传统集中式云计算架构在实时性、隐私保护和资源效率上的瓶颈日益凸显。本文提出“端 - 边 - 云”三级智能协同平台架构&#xff0c;以“时空 - 资源 - 服务”三维协同理论为核心&#xff0c;构建覆盖终端感知、边缘计算、云端…

【如何搭建开发环境】

了解java程序 JAVA体系结构 跨平台原理与编译和反编译 如何学习java语言&#xff0c;如何搭建环境 设置JAVA_HOME&#xff0c;指向jdk的安装目录这一级即可。比如我的JDK安装在C:\java\jdk1.8.0_25&#xff0c;那JAVA_HOME的值就是C:\java\jdk1.8.0_25设置Path变量 在Path值后…

LegoGPT,卡内基梅隆大学推出的乐高积木设计模型

LegoGPT 是由卡内基梅隆大学开发的一款创新性乐高积木设计模型&#xff0c;能够根据用户的文本提示生成结构稳固、可组装的乐高模型。该模型基于自回归语言模型和大规模乐高设计数据集进行训练&#xff0c;用户只需输入简单的文字描述&#xff0c;LegoGPT 就能逐步构建出物理稳…

深入理解 NumPy:Python 科学计算的基石

在数据科学、人工智能和科学计算的世界里&#xff0c;NumPy 是一块绕不过去的基石。它是 Python 语言中用于高性能科学计算的基础包&#xff0c;几乎所有的数据分析与机器学习框架&#xff08;如 Pandas、TensorFlow、Scikit-learn&#xff09;都离不开它的支持。 一、什么是 …

Java基础(IO)

所有操作都在内存&#xff0c;不能长时间保存&#xff0c;IO主要在硬盘&#xff0c;可以长时间保存。 一、File类 File类被定义为文件和目录路径名的抽象表示形式&#xff0c;这是因为 File 类既可以表示文件也可以表示目录&#xff0c;他们都通过对应的路径来描述。 提供构…

仿正点原子驱动BMP280气压传感器实例

文章目录 前言 一、寄存器头文件定义 二、设备树文件中添加节点 三、驱动文件编写 四、编写驱动测试文件并编译测试 总结 前言 本文驱动开发仿照正点原子的iic驱动实现&#xff0c;同时附上bmp280的数据手册&#xff0c;可访问下面的链接&#xff1a; BMP280_Bosch(博世…

论坛系统(中-1)

软件开发 编写公共代码 定义状态码 对执⾏业务处理逻辑过程中可能出现的成功与失败状态做针对性描述(根据需求分析阶段可以遇见的问题提前做出定义)&#xff0c;⽤枚举定义状态码&#xff0c;先定义⼀部分&#xff0c;业务中遇到新的问题再添加 定义状态码如下 状态码类型描…

E+H流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯

EH流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯 在现代工业自动化的广阔舞台上&#xff0c;Profibus DP与Modbus TCP这两种通信协议各领风骚&#xff0c;它们在不同的应用场景中发挥着举足轻重的作用。但工业生产的复杂性往往要求不同设备、系统之间能够顺畅沟…

服务器中存储空间不足该怎么办?

服务器作为存储数据信息的重要网络设备&#xff0c;随着企业业务的不断拓展&#xff0c;所需要存储的数据信息也在不断增加&#xff0c;最终会导致服务器中存储空间不足&#xff0c;这不仅会影响到服务器系统性能&#xff0c;还会造成业务无法正常执行&#xff0c;那么&#xf…

C++23 views::chunk_by (P2443R1) 详解

文章目录 引言C23 范围库概述范围视图&#xff08;Range Views&#xff09;范围算法&#xff08;Range Algorithms&#xff09;范围适配器&#xff08;Range Adapters&#xff09; std::views::chunk_by 介绍基本概念特性使用场景 示例代码简单示例自定义谓词示例 总结 引言 在…

零碳园区能源系统-多能互补体系

构建以可再生能源为核心的零碳园区能源系统&#xff0c;需整合光储直柔、光伏发电、微电网、氢能与储能技术&#xff0c;通过多能协同与智能调控实现能源生产、存储、消费全链条优化。以下是系统性实施方案&#xff1a; 一、系统架构设计 1. 多能互补体系 &#xff08;图示&a…

elastic search学习

首先在自己电脑上安装elastic search。安装成功后&#xff0c;查看ES是否启动成功。 安装过程参考&#xff1a;ElasticSearch入门1: mac 安装 - 霜井 - 博客园 安装完成后&#xff0c;直接执行bin目录中的elastic search命令后&#xff0c;就可以启动成功&#xff01; 在网页…