PCIe Linux MRRS和MPS参数设置策略

news2024/9/21 8:02:34

1.概述

MPS(Max Payload Size)和MRRS(Max Read Request Size)共同影响PCIe总线的传输效率。如果MPS和MRRS设置的过小,传输相同长度的数据,需要更多的TLP报文,导致PCIe总线传输效率降低,如果MPS和MRRS设置的过大,超出系统中某些设备的允许值,导致这些设备无法处理TLP报文,然后上报Malformed TLP错误。因此合理的设置MPS和MRRS非常重要,内核提供了5种策略,可以根据不同的场景进行选择。MPS和MRRS的意义参考PCIe总线-MPS MRRS RCB参数介绍(四)。

2.策略

2.1.策略定义

内核定义的5种配置MPS和MRRS的策略如下所示。

[include/linux/pci.h]
enum pcie_bus_config_types {
    PCIE_BUS_TUNE_OFF,        /* Don't touch MPS at all */
    PCIE_BUS_DEFAULT,         /* Ensure MPS matches upstream bridge */
    PCIE_BUS_SAFE,            /* Use largest MPS boot-time devices support */
    PCIE_BUS_PERFORMANCE,     /* Use MPS and MRRS for best performance */
    PCIE_BUS_PEER2PEER,       /* Set MPS = 128 for all devices */
};

每个策略的行为如下,具体的设置流程参考后面的代码分析小结。

  1. PCIE_BUS_TUNE_OFF
    所有的PCIe设备都使用硬件默认的MPS和MRRS,内核不会修改。
  2. PCIE_BUS_DEFAULT
    内核会修改设备的MPS,使设备和设备上游桥设置的MPS保持一致(如果上游桥为Root Port,且设置的MPS大于设备支持的最大MPS,则将设备支持的最大MPS设置到Root Port中)。MRRS使用设备硬件的默认值,内核不会修改。
  3. PCIE_BUS_SAFE
    使用总线上所有设备支持的最大MPS中最小的MPS。MRRS使用设备硬件的默认值,内核不会修改。
  4. PCIE_BUS_PERFORMANCE
    比较设备上游桥设置的MPS和设备支持的最大MPS,使用较小的MPS(如果上游桥为Root Port,则将MPS设置为桥支持的最大MPS)。MRRS和MPS设置相同。
  5. PCIE_BUS_PEER2PEER
    所有设备的MPS都设置为128。MRRS使用设备硬件的默认值,内核不会修改。

2.2.策略配置

内核中定义了pcie_bus_config变量,用于保存MPS和MRRS的设置策略。如下所示,pcie_bus_config的值由配置选项决定,配置选项有两种方式决定,一个是内核menuconfig,另一种是通过command-line参数传入。

[drivers/pci/pci.c]
/* PCIe MPS/MRRS strategy; can be overridden by kernel command-line param */
#ifdef CONFIG_PCIE_BUS_TUNE_OFF
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
#elif defined CONFIG_PCIE_BUS_SAFE
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;
#elif defined CONFIG_PCIE_BUS_PERFORMANCE
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
#elif defined CONFIG_PCIE_BUS_PEER2PEER
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PEER2PEER;
#else
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
#endif

如下图所示,MPS和MRRS的设置策略,内核menuconfig配置选项如下图所示。

MPS和MRRS配置选项
如下图所示,内核MPS和MRRS的menuconfig选项需要先使能CONFIG_EXPERT选项,否则不会出现在menuconfig选项中。

MPS和MRRS策略依赖选项
内核MPS和MRRS策略的command-line参数如下所示:

pci=pcie_bus_tune_off
pci=pcie_bus_safe
pci=pcie_bus_perf
pci=pcie_bus_peer2peer

3.设置流程

如下图所示,内核中设置MPS/MRRS分为两步,第一步是在扫描单个设备的时候,先读取设备的配置空间,获取设备支持的最大MPS,然后调用pci_configure_mps函数设置设备的MPS,第二步是在内核扫描完总线上所有PCIe设备之后,根据策略,遍历总线,调用pcie_bus_configure_settings设置设备的MPS和MRRS。

MPS和MRRS内核配置流程

3.1.第一步

设备支持的最大MPS通过配置空间的Device Capabilities Register获取,并保存到pci_devpcie_mpss成员中。pci_configure_mps函数的主要作用是实现PCIE_BUS_TUNE_OFF策略,将设备和设备上游桥的MPS设置相同,具体的流程如下:

  1. 当设备是RC下面接的内部EP(PCI_EXP_TYPE_RC_END)时。MPS/MRRS的配置策略为PCIE_BUS_PEER2PEER,则MPS固定设置为128,如果是其他策略,则MPS设置为设备支持的最大值。
  2. 获取当前设备和设备上游桥设置的MPS,当两者的MPS相等时,则直接返回,不设置。
  3. 当MPS/MRRS的配置策略为PCIE_BUS_TUNE_OFFPCIE_BUS_PEER2PEERPCIE_BUS_SAFEPCIE_BUS_PERFORMANCE时直接返回,等待整个PCIe总线枚举完成后再进行设置(PCIE_BUS_TUNE_OFF除外)。
  4. 当MPS/MRRS的配置策略为PCIE_BUS_DEFAULT,如果设备支持的最大MPS小于设备上游桥设置的MPS,且设备上游桥为Root Port(PCI_EXP_TYPE_ROOT_PORT),则将设备上游桥的MPS设置为设备支持的最大MPS。
  5. 将设备上游桥的MPS设置的设备当中。
[drivers/pci/probe.c]
static void pci_configure_mps(struct pci_dev *dev)
{
    ......
    /* 1. PCI_EXP_TYPE_RC_END类型的设备,PCIE_BUS_PEER2PEER策略固定设置为128,
     * 其他策略固定设置为支持的最大值
     */
    if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) {
        if (pcie_bus_config == PCIE_BUS_PEER2PEER)
            mps = 128;
        else
            mps = 128 << dev->pcie_mpss;
        rc = pcie_set_mps(dev, mps);
        ......
    }
    /* 2. 当设备和设备上游桥设置的MPS相等时,则直接返回 */
    mps = pcie_get_mps(dev);
    p_mps = pcie_get_mps(bridge);
    if (mps == p_mps)
        return;

    /* 3. 非PCIE_BUS_DEFAULT策略直接返回,不设置 */
    if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
        ......
        return;
    }
    if (pcie_bus_config != PCIE_BUS_DEFAULT)
        return;
    /* 4. 修正Root Port的MPS */
    mpss = 128 << dev->pcie_mpss;
    if (mpss < p_mps && pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) {
        pcie_set_mps(bridge, mpss);
        ......
        p_mps = pcie_get_mps(bridge);
    }
    /* 5. 将设备上游桥的MPS设置的设备当中 */
    rc = pcie_set_mps(dev, p_mps);
    ......
}

3.2.第二步

当整个PCIe总线枚举完成之后,内核会遍历Host bridge子总线,调用pcie_bus_configure_settings函数设置MPS和MRRS。对于PCIE_BUS_TUNE_OFFPCIE_BUS_DEFAULT策略,则直接跳过,不设置。
pcie_bus_configure_settings的执行流程如下所示:

  1. 当MPS/MRRS的配置策略为PCIE_BUS_PEER2PEER,则MPS固定设置为128。
  2. 当MPS/MRRS的配置策略为PCIE_BUS_SAFE,如果设备是支持热插拔的桥,则MPS为128,否则设置为这条子总线上设备支持的最大MPS中最小的一个(子总线从该设备上游桥开始)。
  3. 设置当前设备和其下游设备的MPS、MRRS。
[drivers/pci/probe.c]
void pcie_bus_configure_settings(struct pci_bus *bus)
{
    u8 smpss = 0;
    ......
    /* 1. MPS固定为128 */
    if (pcie_bus_config == PCIE_BUS_PEER2PEER)
        smpss = 0;
    /* 2. 如果设备是支持热插拔的桥,则MPS为128,否则设置为这条子总线上
     * 设备支持的最大MPS中最小的一个
     */
    if (pcie_bus_config == PCIE_BUS_SAFE) {
        smpss = bus->self->pcie_mpss;
        pcie_find_smpss(bus->self, &smpss);
        pci_walk_bus(bus, pcie_find_smpss, &smpss);
    }
    /* 3. 设置当前设备和其下游设备的MPS、MRRS */
    pcie_bus_configure_set(bus->self, &smpss);
    pci_walk_bus(bus, pcie_bus_configure_set, &smpss);
}

pcie_bus_configure_set函数如下所示,对于MPS/MRRS的配置策略为PCIE_BUS_TUNE_OFFPCIE_BUS_DEFAULT,直接返回,不设置MPS和MRRS,而对于其他策略,调用pcie_write_mps设置MPS,调用pcie_write_mrrs设置MRRS。

[drivers/pci/probe.c]
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
{
    ......
    if (pcie_bus_config == PCIE_BUS_TUNE_OFF ||
        pcie_bus_config == PCIE_BUS_DEFAULT)
            return 0;

    mps = 128 << *(u8 *)data;
    orig_mps = pcie_get_mps(dev);

    pcie_write_mps(dev, mps); // 设置MPS
    pcie_write_mrrs(dev);     // 设置MRRS
    ......
}

pcie_write_mps函数如下所示,对于MPS/MRRS的配置策略为PCIE_BUS_PERFORMANCE,如果设备是Root Port(PCI_EXP_TYPE_ROOT_PORT)则MPS为其支持的最大MPS,如果是其他设备,则取设备和设备上游桥支持的最大MPS中最小的一个。最后调用pcie_set_mps函数将MPS设置到配置空间的Device Control Register中。

[drivers/pci/probe.c]
static void pcie_write_mps(struct pci_dev *dev, int mps)
{
    ......
    if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
            mps = 128 << dev->pcie_mpss;
            if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self)
                mps = min(mps, pcie_get_mps(dev->bus->self));
    }

    rc = pcie_set_mps(dev, mps);
    ......
}

pcie_write_mrrs函数如下所示,只有MPS/MRRS的设置策略为PCIE_BUS_PERFORMANCE才会设置MRRS,其他策略使用设备默认的MRRS。在性能模式下,MRRS应该设置为设备支持的最大值,但不能超过设备设置的MPS,因此先读取设备的MPS,然后将读取的值作为MRRS值设置到配置空间的Device Control Register中,如果写入的MRRS值超过了设备支持的最大值,则减半继续设置。

[drivers/pci/probe.c]
static void pcie_write_mrrs(struct pci_dev *dev)
{
    // 只有PCIE_BUS_PERFORMANCE策略才会配置MRRS
    if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
        return;
    mrrs = pcie_get_mps(dev);  // 获取设备配置的MPS
    // 设置MRRS,和设备的MPS相等
    while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
        rc = pcie_set_readrq(dev, mrrs);
        if (!rc)
            break;
        mrrs /= 2;
    }
}

4.设置接口

除了内核会根据选择的策略设置MPS和MRRS之外,驱动也可以调用内核提供的接口主动设置MPS和MRRS。内核定义的接口如下所示:

[include/linux/pci.h]
int pcie_get_readrq(struct pci_dev *dev);         // 获取设置的MRRS
int pcie_set_readrq(struct pci_dev *dev, int rq); // 设置MRRS
int pcie_get_mps(struct pci_dev *dev);            // 获取设置的MPS
int pcie_set_mps(struct pci_dev *dev, int mps);   // 设置MPS

参考资料

  1. PCI Express® Base Specification Revision 5.0 Version 1.0
  2. Linux Kernel 5.10

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

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

相关文章

PHP多项目多场景排队叫号系统源码

&#x1f514;&#x1f4c8;多项目多场景排队叫号系统&#xff0c;让等待也高效有序&#xff01; 一、告别无序等待&#xff0c;智能排队新风尚 你是否曾在医院、银行或政务大厅等地方&#xff0c;面对冗长的队伍感到无奈&#xff1f;多项目多场景排队叫号系统&#xff0c;正…

Mybatis的分页,延迟加载和缓存

目录 分页&#xff1a; 方式一&#xff1a;利用 limit 实现物理分页 利用limit的关键字分页 方式二&#xff1a;RowBounds集合逻辑分页 方式三&#xff1a;插件分页 延迟加载和立即加载&#xff1a; 什么是立即加载&#xff1a; 什么是延迟加载 延迟加载的配置 缓存&a…

XSS漏洞洞讲解

目录 一、XSS漏洞的定义 1.什么是XSS漏洞&#xff1f; 二、XSS漏洞的类型 1.反射型 XSS 2.DOM型 XSS 3.存储型 XSS 三、实战案例演练 第1关 Ma Spaghet 第2关 Jefff 第3关 Ugandan Knuckles 第4关 Ricardo Milos 第5关 Ah Thats Hawt 第6关 Ligma ​第7关 Mafia …

c++ 使用Tesseract5.0 识别图片文字示例

Tesseract5.0相对于旧版本的程序&#xff0c;识别精准度会提升不少&#xff0c;如下&#xff1a; 1、示例1&#xff1a; 图片&#xff1a; 结果&#xff1a; 2、示例2&#xff1a; 图片&#xff1a; 结果&#xff1a; c代码如下&#xff1a; #include <iostream> #in…

C++ 设计模式——建造者模式

建造者模式 建造者模式组成部分建造者模式使用步骤1. 定义产品类2. 创建具体产品类3. 创建建造者接口4. 实现具体建造者5. 创建指挥者类6. 客户端代码 建造者模式 UML 图建造者模式 UML 图解析建造者模式的优缺点建造者模式的适用场景完整代码 建造者模式 建造者模式&#xff…

Hogan 阻抗控制的理解

机器人阻抗控制是一种基于力的控制方法,它通过调节机器人在受到外部力作用时所表现出的抵抗能力(即阻抗),来实现与环境的良好交互。以下是对机器人阻抗控制的详细理解: 一、阻抗控制的基本原理 阻抗控制的核心思想是通过模拟物体的力学特性(如刚度、阻尼和质量),使机…

定时器处理按键抖动

一、按键的抖动 1.按键的定义和原因 按键抖动是由于‌机械按键在闭合和断开时&#xff0c;由于触点的弹性作用&#xff0c;会产生一系列的抖动现象。这种抖动对于人类来说几乎感觉不到&#xff0c;但对‌单片机来说&#xff0c;却是一个可以感应到的过程&#xff0c;且处理时…

SQL - 设计数据库

数据建模 数据建模就是为要存储在数据库中的数据创建模型的过程 步骤 1.理解和分析业务需求 (收集信息) 收集需求&#xff0c;明确业务流程&#xff0c;定义数据需求&#xff0c;分析业务规则 2.构建业务的概念模型 (识别和表示业务中实体、事务或概念以及它们之间的关系) 识别…

APP支付宝授权获取code uniapp

1.点击使用plus.runtime跳转打开支付宝 //打开支付宝授权&#xff0c;在支付宝APP中授权后会在支付宝中跳转到你填写的h5地址//urls是授权地址可以后端拼接也可以前端写死 //以下是一个拼接示例&#xff0c;需修改app_id的值和redirect_uri的值即可 //app_id是商户的APPID&…

WorkPlus-为用户提供IM即时通讯和实时音视频通信本地化服务

WorkPlus作为一家领先的企业级通讯解决方案提供商&#xff0c;为用户提供了本地化服务&#xff0c;以满足IM即时通讯和实时音视频通信的需求。本文将深入探讨WorkPlus本地化服务的重要性以及其为用户提供的IM即时通讯和实时音视频通信的解决方案。 一、本地化服务的意义 低延迟…

【动态规划、dp】[CSP-J 2022] 上升点列 题解

题目描述 在一个二维平面内&#xff0c;给定 n n n 个整数点 ( x i , y i ) (x_i, y_i) (xi​,yi​)&#xff0c;此外你还可以自由添加 k k k 个整数点。 你在自由添加 k k k 个点后&#xff0c;还需要从 n k n k nk 个点中选出若干个整数点并组成一个序列&#xff0c…

从0开始搭建vue + flask 旅游景点数据分析系统(十三)vue + flask 图片上传、用户头像更改

项目是基于我的博文&#xff1a;vue flask 旅游景点数据分析系统 基础上做的&#xff0c;可以参考之前的博客文章。 1 前端修改 主要是修改Profile.vue <!-- 头像上传 --><el-form-item label"头像"><el-uploadclass""action"/api/…

使用 Fyne 构建 GUI 应用:设置标签文本和自增计数器

引言 Fyne 是一个用 Go 语言编写的跨平台 GUI 框架&#xff0c;它提供了一套丰富的组件来帮助开发者快速构建出漂亮的用户界面。在本文中&#xff0c;我们将通过一个简单的案例来演示如何使用 Fyne 创建 GUI 应用程序&#xff0c;该程序包含设置标签文本和自增计数器的功能。 …

按钮(Buttons)-Qt-思维导图-学习笔记

按钮(Buttons) 按钮在 Qt 中的重要性 按钮是 Qt 中最常用的控件之一 通过点击按钮&#xff0c;可以响应事件&#xff0c;实现人机交互效果 按钮在嵌入式系统和 PC 端的界面交互中都是不可或缺的 Qt 内置的六种按钮部件 QPushButton&#xff1a;下压按钮 用法示例 项目创建与…

指针详解(三)

目录 1. 数组名 2. 使用指针访问数组 3. 一维数组传参的本质 4. 冒泡排序 5. 二级指针 6. 指针数组 7. 指针数组模拟二维数组 1. 数组名 在使用指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0];/…

CV党福音:YOLOv8实现实例分割(二)之训练过程

在上一篇博客中&#xff0c;我们已经了解了YOLOv8实例分割的基本流程&#xff0c;本章则是对数据集、以及训练过程等进行进一步的学习。 文章目录 训练整体流程语义分割与实例分割数据集开启训练训练Debug数据封装损失函数初始化前向传播 总结 训练整体流程 训练模型的整体流…

洗衣机洗衣服一些知识

01智能:按衣物多少自动调节合适水位的标准洗涤程序 (需要30分钟时间) 02:大物:较大,较厚的衣服洗涤 03:轻柔:毛织品或内衣洗涤 04:快速:少量清污衣服洗涤 (13分钟) 05:浸泡:先浸泡一段时间再洗涤 06:单洗:只洗衣不脱水 07:单脱:只脱水不洗衣 08:洁桶:清洁洗衣桶 准备工作: (1)…

XSS反射型和DOM型+DOM破坏

目录 第一关 源码分析 payload 第二关 源码分析 payload 第三关 源码分析 payload 第四关 源码分析 payload 第五关 源码分析 payload 第六关 源码分析 第七关 源码分析 方法一&#xff1a;构造函数 方法二&#xff1a;parseInt 方法三&#xff1a;locat…

龙门吊(天车)防撞方案

防撞雷达设备&#xff0c;是一款基于无线微波技术自主研发的应答式高精度无线防撞产品&#xff0c;该产品具有测距精度高&#xff08;最高可到10厘米&#xff09;&#xff0c;测距稳定&#xff0c;无累计误差&#xff0c;粉尘、水汽不影响测距精度&#xff0c;抗电磁干扰等特点…

oracle数据库目录及文件

oracle数据库目录及文件 oracle安装后所有根目录 1、admin 目录 里边有不同文件夹&#xff0c;代表一个实例&#xff0c;记录 Oracle 实例的配置&#xff0c;运行日志等文件。每个实例一个目录。 SID&#xff1a;System IDentifier 的缩写&#xff0c;是 Oracle 实例的唯一标记…