博通BCM575系列 RDMA 网卡驱动 bnxt_re 分析(一)

news2024/11/16 8:43:49

简介

整个BCM系列驱动分成以太网部分(bnxt_en.ko)和RDMA部分(bnxt_re.ko), 两个模块之间通过内核的auxiliary_bus进行管理.我们主要分析下bnxt_re驱动.

代码结构

这个驱动的核心是 qplib_fp.c, 这个文件主要包含了驱动的数据路径, 包括Post Send, Post Recv, Poll CQ流程的实现. ib_verbs.c主要是实现了上层的Verbs接口, qplib_rcfw.c 实现了驱动和固件通信的部分, qplib_res.c 实现了核心资源的初始化和分配函数.
在这里插入图片描述
整个驱动四万多行代码, 每个小模块精密合作共同构成了这个性能利器.

Page Buffer List(PBL)

在Infiniband中QP接收用户发送的命令, 硬件处理QP中的命令. 处理完成后硬件将结果写入CQ, 用户Poll CQ去取命令执行结果. 这整个过程需要固件和驱动的协作, QP和CQ应该怎么实现, 才能保证硬件和驱动高效协作以实现RoCE的高带宽和低时延将数据包快速可靠的交付给用户呢 ?

在bnxt_re中, 实现这个目标的方法是Page Buffer List(PBL), 驱动使用PBL作为核心去实现QP, CQ等核心资源, PBL使用类似页表的结构去管理DMA Buffer. PBL用来管理多个物理Page, 类似scatter-gather列表, 通过PBL将多个物理不连续的页组织成一个虚拟连续的空间.Page Table Entry(PTE)用来描述一个物理页面, 一个一级的PBL如下图所示, 通过多个vmalloc出来的PTE结构来描述多个物理页面.

在这里插入图片描述

PTE长度为64位, 格式如下图所示, page表示页号, 共52位. next_to_last为1表示PTE指向的页是PBL的倒数第二个页, last为1表示PTE指向的页是PBL的最后一个页,

在这里插入图片描述

二级PBL使用两次遍历去找到最终的页, 第一次使用Page Directory Entry(PDE)找到存储PTE的页, 在使用PTE找到最终的数据页.

在这里插入图片描述

page字段表示PTE Page地址的高位, 如果PTE页的大小超过了4K(用来描述页的PDE会变少), page低位应该置为0.valid表示PDE是否指向了一个有效的PTE Page.
在这里插入图片描述

有效位

类似内核页表的有效位, PBL的valid的含义和内核页表类似, 表示PTE描述的页面是否有效. 避免在一开始就分配一大片的Page, 提高性能, 并且降低资源浪费.

队列PBL

有些PBL用来描述队列, 当PBL被缓存到硬件cache的时候, current和next指针可以被保存, 用来提高cache利用率(通过预取next指针到硬件cache). 但是如果是环形队列最后一个元素, 这种prefetch机制可能会遇到一些障碍, 为了顺利的进行prefetch操作, 在PTE中加入了next_to_last指向PBL表中倒数第二个Page, last表示PTE指向队列最后一个Page.

实现原理

以一级PBL为例讲解下PBL的实现原理, 从上图中我们可以看到要实现一级PBL我们需要一片内存去存储PTE, 实际驱动中会先计算出占用的内存的大小, 然后计算出需要多少个Page, 再计算需要多少个PBL去管理这些Page. 一个4K页最多存储512个指针(4K / 8). 因此使用PBL的数量, 通过下面的方式计算得出:

npbl = npages >> 9;
if (npages % BIT(9))
    npbl++;
bnxt_qplib_pbl

一个PBL结构用来描述多个Page, 其中pg_arr用来存储页面的CPU地址, pg_map_arr用来存储页面的DMA地址.

struct bnxt_qplib_pbl {
    //PBL管理的页面数量
	u32				pg_count;
    //每个页的大小
	u32				pg_size;
    //存储PBL管理的Page的首地址
	void				**pg_arr;
	//Page首地址的DMA表示
    dma_addr_t			*pg_map_arr;
};
PBL的创建和初始化

PBL结构嵌入到HWQ中使用, 根据页的数量分配DMA内存.

struct bnxt_qplib_hwq {
	struct bnxt_qplib_pbl		pbl[PBL_LVL_MAX];
};

int __alloc_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
		       struct bnxt_qplib_sg_info *sginfo)
{
	struct pci_dev *pdev;
	int i;
	
	if (sginfo->nopte)
		return 0;

	pdev = res->pdev;
	//分配PBL表
	pbl->pg_arr = vmalloc(sginfo->npages * sizeof(void *));
	if (!pbl->pg_arr)
		return -ENOMEM;
	//存储dma地址
	pbl->pg_map_arr = vmalloc(sginfo->npages * sizeof(dma_addr_t));
	if (!pbl->pg_map_arr) {
		vfree(pbl->pg_arr);
		return -ENOMEM;
	}
    
    //初始化页面数为0, pg_size等于要管理的sg的页面大小
	pbl->pg_count = 0;
	pbl->pg_size = sginfo->pgsize;

	if (!sginfo->sghead) {
        //从DMA_ZONE分配空间给Page
		for (i = 0; i < sginfo->npages; i++) {
			pbl->pg_arr[i] = msdrv_dma_alloc_coherent(&pdev->dev,
							    pbl->pg_size,
							    &pbl->pg_map_arr[i],
							    GFP_KERNEL);
			if (!pbl->pg_arr[i])
				goto fail;
			memset(pbl->pg_arr[i], 0, pbl->pg_size);
			pbl->pg_count++;
		}
	}
    
	return 0;
fail:
	__free_pbl(res, pbl, is_umem);
	return -ENOMEM;
}

PBL_LVL_0表示描述PTE Page的PBL, PBL_LVL_1表示描述数据Page的PBL, 整个过程就是把数据Page的DMA地址 | flag, 然后写入到PTE中的过程. 对于队列类型的HWQ, 还需要将PTE Page的最后两项写入魔数PTU_PTE_NEXT_TO_LAST和PTU_PTE_LAST.

/* Fill PBL with PTE pointers */
dst_virt_ptr =
    (dma_addr_t **)hwq->pbl[PBL_LVL_0].pg_arr;
src_phys_ptr = hwq->pbl[PBL_LVL_1].pg_map_arr;
for (i = 0; i < hwq->pbl[PBL_LVL_1].pg_count; i++)
    //只有将地址写入到DMA内存中, PTE才算生效
    dst_virt_ptr[PTR_PG(i)][PTR_IDX(i)] =
        src_phys_ptr[i] | flag;
if (hwq_attr->type == HWQ_TYPE_QUEUE) {
    /* Find the last pg of the size */
    i = hwq->pbl[PBL_LVL_1].pg_count;
    dst_virt_ptr[PTR_PG(i - 1)][PTR_IDX(i - 1)] |=
                      PTU_PTE_LAST;
    if (i > 1)
        dst_virt_ptr[PTR_PG(i - 2)]
                [PTR_IDX(i - 2)] |=
                PTU_PTE_NEXT_TO_LAST;
}

PBL实现了结合了scatter-gather list和页表的优点, 实现了一个拓展性好, 且虚拟连续的内存空间.

Hardware Queue(HWQ)

HWQ是驱动中抽象出来的生产者-消费者队列, 实体是由PBL. 队列中每个元素的大小是16字节(stride=(sizeof sq_sge)), 在代码中一个元素被称为一个slot. 一个Page最多能容纳, 4K/16=256个slot. 下图是HWQ被封装后的示意图, 通过指针cons和prod的挪动实现了一个生产者-消费者队列.

在这里插入图片描述

原理

HWQ的底层是通过PBL实现, 在访问时需要将slot id翻译成对应的PBL的页号和页内偏移, 如下所示, pg_num就是页号, pg_idx就是在页面内的slot偏移.

void *bnxt_qplib_get_qe(struct bnxt_qplib_hwq *hwq,
				      u32 indx, u64 *pg)
{
	u32 pg_num, pg_idx;

	pg_num = (indx / hwq->qe_ppg);
	pg_idx = (indx % hwq->qe_ppg);
	if (pg)
		*pg = (u64)&hwq->pbl_ptr[pg_num];
	return (void *)(hwq->pbl_ptr[pg_num] + hwq->element_size * pg_idx);
}

通过这样的读写方式, 我们可以将PBL抽象成下面的形式, 我们可以看到多个物理不连续的页面, 被划分成了连续的slot. 这些slot的数量就是HWQ的深度.

在这里插入图片描述

以下就是HWQ的实现, 其中pbl_ptr和pbl_dma_ptr存储了物理页面的首地址, depth是队列深度, element_size是每个slot的大小, qe_ppg表示每个页面能容纳多少个slot.

struct bnxt_qplib_hwq {
	struct pci_dev			*pdev;
	spinlock_t			lock;
	struct bnxt_qplib_pbl		pbl[PBL_LVL_MAX];
	enum bnxt_qplib_pbl_lvl		level;		/* 0, 1, or 2 */
	void				**pbl_ptr;	/* ptr for easy access
							   to the PBL entries */
	dma_addr_t			*pbl_dma_ptr;	/* ptr for easy access
							   to the dma_addr */
	u32				max_elements;
	u32				depth;	/* original requested depth */
	u16				element_size;	/* Size of each entry */
	u16				qe_ppg;		/* queue entry per page */

	u32				prod;		/* raw */
	u32				cons;		/* raw */
};

参考

https://lore.kernel.org/all/1581786665-23705-4-git-send-email-devesh.sharma@broadcom.com/

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

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

相关文章

读C++ Primer有感

文章目录 类型转换&#xff1a;强制类型转换 标准库类型vector迭代器&#xff1a;数组数组形参可变形参的函数迭代器失效问题IO泛型算法 类型转换&#xff1a; ​ 无符号(0-255) ​ 当赋给一个超出表示范围之后&#xff0c;初始值对无符号类型表示数值总数取模后的余数 ​ un…

[精选好文] ElasticSearch入门到实战教程

给大家分享一个比较好的ElasticSearch教程&#xff0c;ES常用的语法&#xff0c;API都有总结&#xff0c;大家工作时候可以直接翻开用。 地址&#xff1a;点击查看

学习笔记:并查集

并查集 并查集被很多 OIer \texttt{OIer} OIer 认为是最简洁而优雅的数据结构之一&#xff0c;主要用于解决一些 元素分组 的问题。它管理一系列 不相交的集合&#xff0c;并支持两种操作&#xff1a; 合并&#xff1a;把两个不相交的集合合并为一个集合。查询&#xff1a;查…

Windows VS C++工程:包含目录、库目录、附加依赖项、附加包含目录、附加库目录配置与静态库、动态库的调用

文章目录 1 包含目录/附加包含目录1.1 区别和作用1.2 设置路径 2 库目录/ 附加库目录2.1 用途2.2 设置路径 3 附加依赖项3.1 用途3.2 设置路径 4 注意运行库的设置4 静态链接库调用方法5 动态链接库的调用方法 利用Visual Studio编写C工程文件时&#xff0c;时常需要自行配置自…

SQL中:语法总结(group by,having ,distinct,top,order by,like等等)

语法总结&#xff1a;group by&#xff0c;distinct ...... 1.group by2.聚集函数count 3.order by4.增insert、删&#xff08;drop、delete&#xff09;、改&#xff08;update、alter&#xff09;5.查select嵌套查询不相关子查询相关子查询使用的谓词使用的谓词子查询的相关谓…

大厂面试题-JVM中的三色标记法是什么?

目录 问题分析 问题答案 问题分析 三色标记法是Java虚拟机(JVM)中垃圾回收算法的一种&#xff0c;主要用来标记内存中存活和需要回收的对象。 它的好处是&#xff0c;可以让JVM不发生或仅短时间发生STW(Stop The World)&#xff0c;从而达到清除JVM内存垃圾的目的&#xff…

蓝桥杯每日一题2023.10.27

题目描述 快速排序 - 蓝桥云课 (lanqiao.cn) #include <stdio.h>int quick_select(int a[], int l, int r, int k) {int p rand() % (r - l 1) l;int x a[p];{int t a[p]; a[p] a[r]; a[r] t;}int i l, j r;while(i < j) {while(i < j && a[i] &…

centos 8 yum源不能使用问题

问题&#xff1a;新安装的centos 8 不能使用wget就不能下载和安装其他的软件 错误&#xff1a;为仓库 appstream 下载元数据失败 : Cannot prepare internal mirrorlist: No URLs in mirrorlist 解决&#xff1a; [rootlocalhost ~]# cd /etc/yum.repos.d [rootlocalhost yu…

栈、队列、矩阵的总结

栈的应用 括号匹配 表达式求值&#xff08;中缀&#xff0c;后缀&#xff09; 中缀转后缀&#xff08;机算&#xff09; 中缀机算 后缀机算 总结 特殊矩阵 对称矩阵的压缩存储 三角矩阵 三对角矩阵 稀疏矩阵的压缩存储

windows服务器环境下使用php调用com组件

Office设置 安装 office2013 且通过正版激活码激活 在组件服务 计算机 我的电脑 DOM 中找到 Microsoft Word 97 - 2003 文档 服务&#xff0c;右键属性 身份验证调整为 无 在 标识中 调整为 交互式用户 php环境设置 开启com组件扩展 在php.ini中设置 extensionphp_com_dotn…

关于亚马逊 CodeWhisperer 的测试反馈

CodeWhisperer 是亚马逊推出的实时 AI 编程助手&#xff0c;是一项基于机器学习的服务&#xff0c;它可以分析开发者在集成开发环境&#xff08;IDE&#xff09;中的注释和代码&#xff0c;并根据其内容生成多种代码建议。 亚马逊云科技开发者社区为开发者们提供全球的开发技术…

python---continue关键字对for...else结构的影响

代码&#xff1a; str1 laowang for i in str1:if i w:print(遇w不打印)continueprint(i) else:print(循环正常结束之后执行的代码) 图示&#xff1a;

速卖通商品详情API接口(标题|主图|SKU|价格|商品描述)

速卖通商品详情接口的用途是获取商品信息。 速卖通商品详情接口可以获取到商品的完整详细信息&#xff0c;包括商品名称、价格、图片、描述、规格、库存等&#xff0c;这些信息能够帮助用户了解商品特点、性能和市场定位&#xff0c;并做出购买决策。同时&#xff0c;通过使用…

0基础学习VR全景平台篇第114篇:全景图优化和输出 - PTGui Pro教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 前情回顾&#xff1a;之前&#xff0c;我们详细介绍了如何用编辑器、控制点、垂直线等功能优化错位和矫正水平&#xff0c;然而这些调整不会马上生效。 我们需要在【优化】选项卡…

react-native调试

一、调试页面js代码 我用的真机调试&#xff0c;手机摇晃会出现出现的页面&#xff0c;点击debug 点击debug后&#xff0c;页面会出现&#xff0c;点按提示操作快捷键会出现开发者工具 注意&#xff1a;Chrome 中并不能直接看到 App 的用户界面&#xff0c;而只能提供 consol…

百度超级链XuperChain使用JavaSDK接入

环境 &#xff1a; ubuntu20 xuperchain 5.3 go 1.17 springboot : 2.5.14 前言 请提前启动好xchain的节点&#xff0c;我选择简单启一个xchain节点作为测试&#xff0c;并且使用默认端口37101 SpringBoot项目初始化 我们先进行SpringBoot项目的配置进行讲解&#xff0c;这里…

安卓逆向之雷电模拟器中控

一, 雷电模拟器 安装使用 官方地址: https://www.ldmnq.com ,官方论坛 https://www.ldmnq.com/forum/ . 有一个多开管理器,还有就是设置手机的参数比较关键。 二,雷电模拟器开启面具,安装LSP。 设置root 权限。

搜索引擎搜索技巧总结

晚上在B站上刷到一个关于搜索技巧的干货视频&#xff0c;这个视频真的不错&#xff0c;结尾还提到了AI时代的搜索思路之前自己也零碎的探索出了一些搜索技巧&#xff0c;但是没有总结&#xff0c;就没法稳定的加入自己的工作流&#xff0c;持续提高效率受到这个视频的启发&…

线扫相机DALSA--分频倍频计算公式及原理

分频倍频计算公式及原理 推导原理&#xff1a; 假设编码器脉冲精度为P&#xff1b;同步轮/辊周长为C&#xff0c;Fov为视野&#xff0c;Res为线扫相机分辨率&#xff0c;N代表N倍频编码器&#xff0c;分频为D&#xff0c;倍频为M 线扫项目常规采用N&#xff08;N 4&#xff0…

化身全能战士:ChatGPT助我横扫办公室【文末送书两本】

化身全能战士&#xff1a;ChatGPT助我横扫办公室 半年签约 16 本书有 ChatGPT 不会的吗&#xff1f;解锁 ChatGPT 秘技&#xff0c;化身全能战士ChatGPT 基本知识办公自动化职场学习与变现 作者简介结语购买链接参与方式往期赠书回顾 &#x1f3d8;️&#x1f3d8;️个人简介&a…