【C语言】InfiniBand驱动mlx4_register_interface函数

一、讲解

mlx4_register_interface函数是Mellanox InfiniBand驱动程序的一部分,这个函数的作用是注册一个新的接口(intf)到InfiniBand设备。这允许不同的子系统,如以太网或存储,能够在同一个硬件设备上注册它们各自需要的接口,在硬件资源上建立抽象层。这段代码是从网络驱动的源代码中取出来的,具体的操作流程是这样的:
1. 参数检查: 该函数首先检查传入的接口(intf)是否有`add`和`remove`方法。这两个方法是必须的,因为它们被驱动用来添加和移除设备。如果其中一个方法缺失,函数返回`-EINVAL`,表示一个无效的参数错误。
2. 互斥锁保护: 函数使用了互斥锁`intf_mutex`来确保在修改接口列表(intf_list)时不会有并发问题。
3. 更新接口列表: 函数将`intf`加入到全局的接口列表,使用`list_add_tail`函数把接口添加到列表的尾部。
4. 遍历设备列表: 接下来使用`list_for_each_entry`来遍历当前已注册的设备列表`dev_list`。
5. 多功能设备检查: 在遍历时,对于每个设备`priv`,它会检查是否是一个多功能(multifunction)设备,并且是否接口标志(intf->flags)包含了绑定(BONDING)的属性。如果是这样,它会通过日志输出调试信息,并清除接口标志中的绑定属性。
6. 添加设备: 调用`mlx4_add_device`函数来实际将接口添加到设备。这通常涉及调用接口的`add`方法。
7. 解锁: 最后,函数解锁互斥锁`intf_mutex`。
8. 返回值: 如果一切顺利,函数将返回`0`,表示成功。
这个函数没有直接使用特定的PCIe函数,它是驱动程序高级接口注册流程的一部分。但它关联的操作可能间接地与PCIe有关,因为InfiniBand驱动程序底层可能需要与PCIe硬件交互来执行任务,如访问硬件资源、配置硬件等。这通常涉及读取和写入PCIe配置空间、映射内存空间、处理中断等任务,可能使用诸如`pci_read_config_*, pci_write_config_*, pci_enable_device`, pci_set_master, pci_alloc_irq_vectors, pci_iomap, pci_set_drvdata等PCIe底层函数。
最后需要注意的是,这段代码是内核的一部分,并且使用GPL协议发布,所以任何在此代码基础上的开发或修改,都必须遵循GPL协议。

二、中文注释

这段代码是Linux内核代码的一部分,在kernel-4.9\drivers\net\ethernet\mellanox\mlx4\intf.c文件中,与Mellanox技术有关的mlx4网络驱动程序。这个特定的函数`mlx4_register_interface`的目的是注册一个网络接口到mlx4驱动。以下是对每一部分的中文注释:

// 定义 mlx4_register_interface 函数,它需要一个指向 mlx4_interface 结构体的指针作为参数
int mlx4_register_interface(struct mlx4_interface *intf)
{// 声明一个指向 mlx4_priv 结构体的指针struct mlx4_priv *priv;// 如果接口的 add 或 remove 函数指针为空,则返回 -EINVAL(无效的参数错误)if (!intf->add || !intf->remove)return -EINVAL;// 锁定 intf_mutex 保护全局变量在多线程中被安全访问mutex_lock(&intf_mutex);// 在全局接口列表 intf_list 的末尾添加新接口list_add_tail(&intf->list, &intf_list);// 遍历 dev_list 中的每个条目(即 mlx4_priv 设备列表)list_for_each_entry(priv, &dev_list, dev_list) {// 检查是否启用了多功能(multi-function)并且接口的 flags 包含 BONDING 标志if (mlx4_is_mfunc(&priv->dev) && (intf->flags & MLX4_INTFF_BONDING)) {// 打印调试信息,表明对于多功能设备,要禁用 HA(高可用)模式mlx4_dbg(&priv->dev,"SRIOV, disabling HA mode for intf proto %d\n", intf->protocol);// 清除 intf 的 BONDING 标志intf->flags &= ~MLX4_INTFF_BONDING;}// 为当前遍历到的设备 priv 添加这个接口mlx4_add_device(intf, priv);}// 解锁保护全局变量 intf_mutexmutex_unlock(&intf_mutex);// 返回 0 表示函数成功完成return 0;
}
// 向内核导出 mlx4_register_interface 符号,使其可以被模块 GPL 兼容地使用
EXPORT_SYMBOL_GPL(mlx4_register_interface);

这个函数的具体流程是:
1. 检查 intf 指定的接口结构是否有必要的 add 和 remove 函数。
2. 锁定 intf_mutex 以保护全局的 intf_list 在多线程环境下的修改。
3. 将 intf 接口添加到 intf_list 链表的末尾。
4. 遍历 dev_list 链表,检查每个设备是否为多功能设备并且是否有配对标志;如有,禁用高可用模式。
5. 对每个设备调用 mlx4_add_device 函数将这个接口添加到设备。
6. 解锁 intf_mutex。
7. 函数返回,表示接口注册成功。 

三、mlx4_add_device

// 定义一个名为 mlx4_add_device 的函数,它接收指向 mlx4_interface 结构和 mlx4_priv 结构的指针作为参数。
static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
{struct mlx4_device_context *dev_ctx; // 定义一个指向 mlx4_device_context 结构的指针变量。// 使用 kmalloc 函数分配内存给 dev_ctx,大小为一个 mlx4_device_context 结构的大小。// GFP_KERNEL 标志表示正常的内核内存分配方式。dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL);if (!dev_ctx)return; // 如果内存分配失败,则直接返回。// 初始化 dev_ctx 结构体的成员。dev_ctx->intf    = intf; // 赋值接口指针。dev_ctx->context = intf->add(&priv->dev); // 调用 intf 的 add 方法,并将结果存储在 context 中。// 检查是否成功获得了 context。if (dev_ctx->context) {// 使用 spin_lock_irq 来锁定 priv->ctx_lock,禁止中断,避免 race condition。spin_lock_irq(&priv->ctx_lock);// 将 dev_ctx 加入到 priv->ctx_list 链表的尾部。list_add_tail(&dev_ctx->list, &priv->ctx_list);// 解锁。spin_unlock_irq(&priv->ctx_lock);// 如果 intf 结构体中定义了 activate 回调方法,则调用它。if (intf->activate)intf->activate(&priv->dev, dev_ctx->context);} else // 如果获取 context 失败,则释放之前分配的内存。kfree(dev_ctx);
}

上述代码通常应该是 Linux 内核的一部分,具体是 Mellanox 网络设备驱动程序的代码。代码的功能是向驱动程序注册一个新的设备,并建立需要的设备上下文。如果在建立上下文(比如分配内存或者初始化结构)时失败了,它会清理所用的资源并退出。如果成功,它会将该设备上下文添加到一个全局的链表中,并且调用激活回调(如果提供了的话)。

这段代码是一个用于Linux网络驱动中,Mellanox设备的一部分。这个函数的主要作用是将一个新的设备添加到特定的接口(interface)。
函数签名解释:
static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv)
- static: 函数的作用域是该文件内部。
- void: 函数没有返回值。
- mlx4_add_device: 函数名称,意味着“添加mlx4设备”。
- struct mlx4_interface *intf: 函数的第一个参数,一个指向`mlx4_interface`结构体的指针。这表示与设备通讯的接口。
- struct mlx4_priv *priv: 函数的第二个参数,一个指向`mlx4_priv`结构体(包含私有数据)的指针。
函数的工作流程解释:
1. kmalloc用于动态分配内存。这里分配了一个`mlx4_device_context`结构体的内存。`GFP_KERNEL`参数是告诉内核这次分配是可以睡眠的,如果当前没有足够的内存,可以等待。
2. 如果`kmalloc`返回NULL,代表内存分配失败,函数直接返回。
3. 分配成功后,开始初始化`dev_ctx`结构体的成员:指向接口的指针`intf`和通过接口提供的`add`函数回调来获得的设备上下文`context`。
4. 如果`context`不是NULL,表示设备已成功添加。
5. 函数通过获得`ctx_lock`自旋锁来保护并发访问`priv`结构体的`ctx_list`列表。
6. 使用`list_add_tail`将`dev_ctx`添加到`priv`的`ctx_list`列表尾部。
7. 释放自旋锁,允许其他代码运行。
8. 如果`intf`结构体提供了一个`activate`函数指针,调用这个函数激活设备。
9. 如果设备上下文没有成功创建,释放之前分配的`dev_ctx`结构体的内存来避免内存泄漏。
总结:这个函数处理将一个新的设备添加到一个网络接口,并在添加成功时可能触发设备的激活过程。如果添加失败,则清理资源以避免内存泄漏。 

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

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

相关文章

ASP.Net实现玩具管理(三层架构,两项数据相乘)

目录 演示功能: 点击启动生成页面 步骤: 1、建文件 ​编辑 2、添加引用关系 3、根据数据库中的列写Models下的XueshengModels类 4、DAL下的DBHelper(对数据库进行操作) 5、DAL数据访问层下的service文件 6、BLL业务逻辑层…

通讯协议制定之交互方式、步骤介绍

文章目录 通讯协议制定之交互方式、步骤介绍1. 前言2. 通讯协议发送类型2.1 周期发送2.2 事件发送 3. 通讯协议数据包类型3.1 握手3.2 心跳3.1 数据包 4. 小结 通讯协议制定之交互方式、步骤介绍 1. 前言 通讯协议又称通信规程,是指通信双方对数据传送控制的一种约…

如何部署Python Flask并实现远程访问本地搭建web站点【内网穿透】

文章目录 前言1. 安装部署Flask并制作SayHello问答界面2. 安装Cpolar内网穿透3. 配置Flask的问答界面公网访问地址4. 公网远程访问Flask的问答界面 前言 Flask是一个Python编写的Web微框架,让我们可以使用Python语言快速实现一个网站或Web服务,本期教程…

导出微软浏览器收藏的网页,并查看网页保存的登录密码

导出微软Edge浏览器收藏夹(书签)的步骤如下: 打开Microsoft Edge浏览器。右键点击浏览器收藏栏上的任意位置或使用快捷键Ctrl Shift O打开收藏夹管理页面。在收藏夹管理页面中,通常你会看到右上角或菜单区域有一个“…”或者三…

Axios中每次发送post请求前都会发送options请求

今天写前端的时候,发现每次post请求都会失败, 反复调试过后发现axios在每次发送post请求前都发送了options请求, 在网络搜罗了一大圈, 发现了原因是因为web页面发送了请求给vue后, vue再请求后端过程中发生了跨域&…

【算法】一维前缀和以及二维前缀和

目录 一维前缀和适用场景示例 二维前缀和适用场景一种情况另一种情况示例 一维前缀和 适用场景 求一段区间的和。 比如有一个数列 : 如果我们要求 [l,r]即某个区间内的数组和的时候,思路就是每遍历一个元素就进行求和,记录下加到al时的和…

Skywalking

1、简介 Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的开源项目, 2017年12月SkyWalking成为Apache国内首个个人孵化项目, 2019年4月17日SkyWalking从Apache基金会的孵化器毕业成为顶级项目, 目前SkyWalking支持Java、 .Net、 …

广告主投放系统从设计到实践

在当今数字广告行业中,广告主投放系统扮演着至关重要的角色。它是连接广告主和广告媒体之间的桥梁,帮助广告主实现广告投放目标并获得可观的回报。本篇博客文章将深入探讨广告主投放系统的设计和实践过程,并分享一些关键的经验和最佳实践。 …

flink的分组聚合、over聚合、窗口聚合对比

【背景】 flink有几种聚合,使用上是有一些不同,需要加以区分: 分组聚合:group agg over聚合:over agg 窗口聚合:window agg 省流版: 触发计算时机 结果流类型 状态大小 分组聚合group ag…

使用OpenCV实现两张图像融合在一起

简单介绍 图像融合技术是一种结合多个不同来源或不同传感器捕获的同一场景的图像数据,以生成一幅更全面、更高质量的单一图像的过程。这种技术广泛应用于遥感、医学影像分析、计算机视觉等多个领域。常见的图像融合技术包括基于像素级、特征级和决策级的融合方法&a…

基与HTML5的塔防游戏设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 项目背景与相关技术 3 1.1 背景与发展简介 3 1.2 HTML5技术及其优势 4 1.3 JavaScript开发的优势与劣势 4 1.4 CSS样式表在开发中的用处 5 1.5 本章小结 6 2 系统分析 7 2.1 需求分析 7 2.2 问题分析 7 2.3 流程设计 7 2.3 功能分析 8 2.…

Linux---多线程(上)

一、线程概念 线程是比进程更加轻量化的一种执行流 / 线程是在进程内部执行的一种执行流线程是CPU调度的基本单位,进程是承担系统资源的基本实体 在说线程之前我们来回顾一下进程的创建过程,如下图 那么以进程为参考,我们该如何去设计创建一个…

paddle的版面分析的环境搭建及使用

一、什么是版面分析 版面分析技术,主要是对图片形式的文档进行版面分析,将文档划分为文字、标题、表格、图片以及列表5类区域,如下图所示: 二、应用场景 2.1 合同比对 2.2 文本类型划分 2.3 通用文档的还原 版面分析技术可将以…

论文阅读FCN-Transformer Feature Fusion for PolypSegmentation

本文提出了一种名为Fully Convolutional Branch-TransFormer (FCBFormer)的图像分割框架。该架构旨在结合Transformer和全卷积网络(FCN)的优势,以提高结肠镜图像中息肉的检测和分类准确性。 1,框架结构: 模型采用双分…

【Python】牛客网—软件开发-Python专项练习

专栏文章索引:Python 1.(单选)下面哪个是Python中不可变的数据结构? A.set B.list C.tuple D.dict 可变数据类型:列表list[ ]、字典dict{ }、集合set{ }(能查询,也可更改)数据发生改…

Golang 开发实战day03 - Arrays Slices

Golang 教程03 - Arrays,Slices Go语言中的数组和切片都是用于存储数据的类型,但它们之间存在一些重要的区别。了解这些区别对于有效地使用它们至关重要。 1. Arrays 数组 1.1 定义 数组是一种固定大小的数据结构,用于存储相同类型的值。…

广西省行政村边界shp数据/广西省乡镇边界/广西省土地利用分类数据/径流分布

广西壮族自治区,地处中国南部,北回归线横贯中部。南北以贺州——东兰一线为界,此界以北属中亚热带季风,以南属南亚热带季风。 数据范围:全国行政区划-行政村界 数据类型:面状数据,全国各省市县…

1月笔记本电脑行业分析:多品牌下滑但ThinkPad逆势增长!

2024年1月,笔记本行业市场格局出现较大的变化。长期在京东平台保持头部联想和惠普,被ThinkPad挤下(虽然是联想旗下品牌),排名掉至第二和第三。ThinkPad以超2.7亿的月销售额成绩拿下第一,市占比16%。 与去年…

java SSM农产品订购网站系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM农产品订购网站系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采…

算法-贪心-112. 雷达设备

题目 假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。 每个小岛都位于海洋一侧的某个点上。 雷达装置均位于海岸线上,且雷达的监测范围为 d,当小岛与某雷达的距离不超过 d 时,该小岛可以被雷达覆…