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

news2024/11/11 4:48:23

简介

整个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/1132586.html

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

相关文章

迭代器的封装与反向迭代器

一、反向迭代器 在list模拟实现的过程中&#xff0c;第一次接触了迭代器的封装&#xff0c;将list的指针封装成了一个新的类型&#xff0c;并且以迭代器的基本功能对其进行了运算符重载 反向迭代器是对正向迭代器的封装&#xff0c;并且体现了泛型编程的思想&#xff0c;任意…

PX30 android8.1添加RTL8723DU

将8723du复制到kernel/drivers/net/wireless/rockchip_wlan/rtl8723du 并修改makefile 修改平台 CONFIG_PLATFORM_I386_PC nCONFIG_PLATFORM_ARM_RK3188 y 修改 ifeq ($(CONFIG_PLATFORM_ARM_RK3188), y) EXTRA_CFLAGS -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDRO…

【C语言】指针那些事之数组传参和指针传参的区别

C语言系列 文章目录 目录 C语言系列 文章目录 前言 一&#xff0c;数组传参和指针传参 1.1一维数组传参 1.2二维数组传参 1.3一级指针传参 1.4当一个函数的参数部分为一级指针的时候&#xff0c;函数可以接收什么参数 1.5二级指针传参 1.6当函数的参数为二级指针的时…

服务器动态/静态/住宅/原生IP都是什么意思

​  在互联网的世界中&#xff0c;我们经常会听到关于IP地址的各种说法&#xff0c;比如服务器动态IP、静态IP、住宅IP和原生IP。那么这些术语究竟代表着什么意思呢?让我们一起来了解一下。 动态IP 动态IP(Dynamic IP)是指互联网服务提供商(ISP)在每次用户上网时&#xff0c…

智安网络|探索语音合成技术的未来:揭秘人工智能配音技术的背后

随着人工智能技术的迅猛发展&#xff0c;配音行业也迎来了人工智能配音技术的崭新时代。人工智能配音技术通过语音合成和自然语言处理等技术手段&#xff0c;实现了逼真的语音合成&#xff0c;为影视、广告和游戏等领域带来了新的可能性。 第一部分&#xff1a;语音合成技术的…

求臻医学:肺癌患者就诊指南及基因检测意义

2023年国家癌症中心公布的最新的数据显示&#xff0c;中国癌症新发病例数前十的癌症分别是&#xff1a;肺癌82万&#xff0c;结直肠癌56万&#xff0c;胃癌48万&#xff0c;乳腺癌42万&#xff0c;肝癌41万&#xff0c;食管癌32万&#xff0c;甲状腺癌22万&#xff0c;胰腺癌12…

塔式服务器介绍

大家都知道服务器分为机架式服务器、刀片式服务器、塔式服务器三类&#xff0c;今天小编就分别讲一讲这三种服务器&#xff0c;第三篇先来讲一讲塔式服务器的介绍。 塔式服务器定义&#xff1a;塔式服务器的外观和普通电脑差不多&#xff0c;直立放置。机箱比较大&#xff0c;服…

信息安全应急响应小组 诚招

介绍 小组接触领域:攻防领域CISP认证,CTF,工业自动化控制,工业网络,机械制图等 小组成立意义;致力于解决公司内外网安全,高校内外网安全,CTF赛题分析,工控领域内网安全等 小组

Stable Diffusion WebUI扩展canvas-zoom详细讲解

canvas-zoom这是什么? 这是一个针对画布做一些操作的工具,比如缩放等。 下面来详细说一下这些操作的热键。 重要的热键: 缩放(Alt+滚轮)、移动画布 (F)、全屏 (S) 和重置缩放 (R) (1)Shift + wheel - 缩放画布 按住Shift + 滚轮之后,一点反应都没有,之后按…

VR全景应用广泛体现在哪里?有何优势?

VR全景作为一种新型营销方式&#xff0c;正在逐渐走进人们的视线&#xff0c;它区别于以往单一角度的照片和视频&#xff0c;VR全景制作显得更加直观、更加真实、更加生动。VR全景通过VR技术将所拍摄的图片变成720度可观看的场景模式&#xff0c;把产品的特色以及魅力整体呈现展…

微电子/集成电路专业学术期刊汇总!

1. JSSC (IEEE Journal of Solid-State Circuits ) IEEE SSCS 旗下的旗舰期刊。IC领域公认的顶刊&#xff0c;难度最大&#xff0c;认可度最高。2020年刚升为一区。 虽然IF只有6.1&#xff0c;但其在IC圈影响力碾压众多一区高分期刊。 投这个期刊必须要有流片和测试结果&…

文件防泄密软件哪个好?

文件防泄密软件哪个好&#xff1f; 在互联网数据时代发展模式下&#xff0c;很多企业的数据都是公司的重要命脉&#xff0c;然后也会有很多人铤而走险&#xff0c;盗取公司机密信息&#xff0c;做违法的事情&#xff0c;然而&#xff0c;保护好公司数据不被泄密成了很多老板头…

Leetcode周赛365补题(3 / 3)

目录 1、2、有序三元组的最大值 - 预处理前后最大值 遍历 &#xff08;1&#xff09;预处理前后值遍历&#xff08;枚举j&#xff09; &#xff08;2&#xff09;枚举k 2、无限数组的最短子数组 - 前缀和 滑动窗口 1、2、有序三元组的最大值 - 预处理前后最大值 遍历 …

linux环境下进程相关概念解释

进程 进程概念PCB(Process control block)进程组织查看进程ps 命令getpid()/getppid()kill -9 pid/ppidfork(&#xff09;为什么fork会有两个返回值&#xff1f;为什么父进程返回子进程的PID&#xff0c;而子进程返回0&#xff1f; linux下的进程状态Z进程孤儿进程 进程优先级查…

新风机小助手-风压变速器

风压变速器是一种用于调节系统中风量和风压的装置&#xff0c;常用于通风系统中。它通过改变进出风口的开度来调整风流的速度和风压。 风压变速器通常由进出风口和可调节的风门组成。风门可以手动或自动调节&#xff0c;控制进出风口的开度&#xff0c;从而改变风量和风压。根据…

数据结构和算法概述

什么是数据结构&#xff1f; 官方解释&#xff1a; 数据结构是一门研究非数值计算的程序设计问题中的操作对象&#xff0c;以及他们之间的关系和操作等相关问题的学科。 大白话&#xff1a; 数据结构就是把数据元素按照一定的关系组织起来的集合&#xff0c;用来组织和存储…

CSC联合培养|公共管理博士赴世界名校瑞士苏黎世联邦理工学院

A同学拟申报CSC联合培养博士项目&#xff0c;要求到专业契合的世界知名高校。最终我们用世界大学排名第7的瑞士苏黎世联邦理工学院邀请函&#xff0c;助其顺利获批CSC&#xff0c;并如期出国。 A同学背景&#xff1a; 申请类型&#xff1a; CSC联合培养博士 工作背景&#xf…

mysql查询最近7天 每天销售额 统计销售额

sql统计每一天的支出数目&#xff0c;支出金额&#xff0c;收入数目&#xff0c;收入金额 finance_type0&#xff1a;收入 finance_type1&#xff1a;支出 部分建表语句&#xff1a; CREATE TABLE finance (finance_id int(11) NOT NULL AUTO_INCREMENT COMMENT ID,finance_u…

Unity 项目中查找仅具有单一颜色的纹理

如何使用 只需在“项目”窗口中创建一个名为“编辑器”的文件夹&#xff0c;然后在其中添加此脚本即可。然后&#xff0c;打开“窗口-单色纹理检测器”并点击“刷新”。 你可能会问&#xff0c;为什么我需要这个&#xff1f;某些纹理可以是 1024x1024 或更大&#xff0c;并且…

PHPstorm 安装汉化包失败解决方法

出错的原因是官方的包和软件的版本不对应&#xff0c;下载对应的汉化包就行了 官网汉化包下载地址https://plugins.jetbrains.com/plugin/13710-chinese-simplified-language-pack----/versions 下载对应ide版本的包&#xff0c;我下载了一个2020版的 放到安装软件的plugins文…