5.4 TLP中与数据负载相关的参数
在PCIe总线中,有些TLP含有Data Payload,如存储器写请求、存储器读完成TLP等。在PCIe总线中,TLP含有的Data Payload大小与Max_Payload_Size、Max_Read_Request_Size和RCB参数相关。下文将分别介绍这些参数的使用。
5.4.1 Max_Payload_Size参数
PCIe总线规定在TLP报文中,数据有效负载的最大值为4KB,但是PCIe设备并不一定能够发送这么大的数据报文。PCIe设备含有“Max_Payload_Size”和“Max_Payload_Size Supported”参数,这两个参数分别在Device Capability寄存器和Device Control寄存器中定义。
“Max_Payload_Size Supported”参数存放在一个PCIe设备中,TLP有效负载的最大值,该参数由PCIe设备的硬件逻辑确定,系统软件不能改写该参数。而Max_Payload_Size参数存放PCIe设备实际使用的,TLP有效负载的最大值。该参数由PCIe链路两端的设备协商决定,是PCIe设备进行数据传送时,实际使用的参数。
PCIe设备发送数据报文时,使用Max_Payload_Size参数决定TLP的最大有效负载。当PCIe设备的所传送的数据大小超过Max_Payload_Size参数时,这段数据将被分割为多个TLP进行发送。当PCIe设备接收TLP时,该TLP的最大有效负载也不能超过Max_Payload_Size参数,如果接收的TLP,其Length字段超过Max_Payload_Size参数,该PCIe设备将认为该TLP非法。
RC或者EP在发送存储器读完成TLP时,这个存储器读完成TLP的最大Payload也不能超过Max_Payload_Size参数,如果超过该参数,PCIe设备需要发送多个读完成报文。值得注意的是,这些读完成报文需要满足RCB参数的要求,有关RCB参数的详细说明见下文。
在实际应用中,尽管有些PCIe设备的Max_Payload_Size Supported参数可以为256B、512B、1024B或者更高,但是如果PCIe链路的对端设备可以支持的Max_Payload_Size参数为128B时,系统软件将使用对端设备的Max_Payload_Size Supported参数,初始化该设备的Max_Payload_Size参数,即选用PCIe链路两端最小的Max_Payload_Size Supported参数初始化Max_Payload_Size参数。
在多数x86处理器系统的MCH或者ICH中,Max_Payload_Size Supported参数为128B。这也意味着在x86处理器中,与MCH或者ICH直接相连的PCIe设备进行DMA读写时,数据的有效负载不能超过128B。而在PowerPC处理器系统中,该参数大多为256B。
目前在大多数EP中,Max_Payload_Size Supported参数不大于512B,因为在大多数处理器系统的RC中,Max_Payload_Size Supported参数也不大于512B。因此即便EP支持较大的Max_Payload_Size Supported参数,并不会提高数据传送效率。
而Max_Payload_Size参数的大小与PCIe链路的传送效率成正比,该参数越大,PCIe链路带宽的利用率越高,该参数越小,PCIe链路带宽的利用率越低。
PCIe总线规范规定,对于实时性要求较高的PCIe设备,Max_Payload_Size参数不应设置过大,因此这个参数有时会低于PCIe链路允许使用的最大值。
5.4.2 Max_Read_Request_Size参数
Max_Read_Request_Size参数由PCIe设备决定,该参数规定了PCIe设备一次能从目标设备读取多少数据。
Max_Read_Request_Size参数在Device Control寄存器中定义。该参数与存储器读请求TLP的Length字段相关,其中Length字段不能大于Max_Read_Request_Size参数。在存储器读请求TLP中,Length字段表示需要从目标设备读取多少数据。
值得注意的是,Max_Read_Request_Size参数与Max_Payload_Size参数间没有直接联系,Max_Payload_Size参数仅与存储器写请求和存储器读完成报文相关。
PCIe总线规定存储器读请求,其读取的数据长度不能超过Max_Read_Request_Size参数,即存储器读TLP中的Length字段不能大于这个参数。如果一次存储器读操作需要读取的数据范围大于Max_Read_Request_Size参数时,该PCIe设备需要向目标设备发送多个存储器读请求TLP。
PCIe总线规定Max_Read_Request_Size参数的最大值为4KB,但是系统软件需要根据硬件特性决定该参数的值。因为PCIe总线规定EP在进行存储器读请求时,需要具有足够大的缓冲接收来自目标设备的数据。
如果一个EP的Max_Read_Request_Size参数被设置为4KB,而且这个EP每发出一个4KB大小存储器读请求时,EP都需要准备一个4KB大小的缓冲[1]。这对于绝大多数EP,这都是一个相当苛刻的条件。为此在实际设计中,一个EP会对Max_Read_Request_Size参数的大小进行限制。
5.4.3 RCB参数
RCB位在Link Control寄存器中定义。RCB位决定了RCB参数的值,在PCIe总线中,RCB参数的大小为64B或者128B,如果一个PCIe设备没有设置RCB的大小[2],则RC的RCB参数缺省值为64B,而其他PCIe设备的RCB参数的缺省值为128B。PCIe总线规定RC的RCB参数的值为64B或者128B,其他PCIe设备的RCB参数为128B。
在PCIe总线中,一个存储器读请求TLP可能收到目标设备发出的多个完成报文后,才能完成一次存储器读操作。因为在PCIe总线中,一个存储器读请求最多可以请求4KB大小的数据报文,而目标设备可能会使用多个存储器读完成TLP才能将数据传递完毕。
当一个EP向RC或者其他EP读取数据时,这个EP首先向RC或者其他EP发送存储器读请求TLP;之后由RC或者其他EP发送存储器读完成TLP,将数据传递给这个EP。
如果存储器读完成报文所传递数据的地址范围没有跨越RCB参数的边界,那么数据发送端只能使用一个存储器完成报文将数据传递给请求方,否则可以使用多个存储器读完成TLP。
假定一个EP向地址范围为0xFFFF-0000~0xFFFF-0010这段区域进行DMA读操作,RC收到这个存储器读请求TLP后,将组织存储器读完成TLP,由于这段区域并没有跨越RCB边界,因此RC只能使用一个存储器读完成TLP完成数据传递。
如果存储器读完成报文所传递数据的地址范围跨越了RCB边界,那么数据发送端(目标设备)可以使用一个或者多个完成报文进行数据传递。数据发送端使用多个存储器读完成报文完成数据传递时,需要遵循以下原则。
- 第一个完成报文所传送的数据,其起始地址与要求的起始地址相同。其结束地址或者为要求的结束地址(使用一个完成报文传递所有数据),或者为RCB参数的整数倍(使用多个完成报文传递数据)。
- 最后一个完成报文的起始地址或者为要求的起始地址(使用一个完成报文传递所有数据),或者为RCB参数的整数倍(使用多个完成报文传递数据)。其结束地址必须为要求的结束地址。
- 中间的完成报文的起始地址和结束地址必须为RCB参数的整数倍。
当RC或者EP需要使用多个存储器读完成报文将0xFFFE-FFF0~0xFFFF-00C7之间的数据发送给数据请求方时,可以将这些完成报文按照表5?9方式组织。
表5?9 存储器读完成报文的拆分方法
方式1 |
方式2 |
方式3 |
0xFFFE-FFF0~0xFFFE-FFFF |
0xFFFE-FFF0~0xFFFE-FFFF |
0xFFFE-FFF0~0xFFFE-FFFF |
0xFFFF-0000~0xFFFF-003F |
0xFFFF-0000~0xFFFF-007F |
0xFFFF-0000~0xFFFF-00C7 |
0xFFFF-0040~0xFFFF-007F |
0xFFFF-0080~0xFFFF-00C7 |
|
0xFFFF-0080~0xFFFF-00BF |
||
0xFFFF-00C0~0xFFFF-00C7 |
上表提供的方式仅供参考,目标设备还可以使用其他拆分方法发送存储器读完成TLP。PCIe总线使用多个完成报文实现一次数据读请求的主要原因是考虑Cache行长度和流量控制。在多数x86处理器系统中,存储器读完成报文的数据长度为一个Cache行,即一次传送64B。除此之外,较短的数据完成报文占用流量控制的资源较少,而且可以有效避免数据拥塞。
5.5 小结
本章重点介绍PCIe总线的事务层。在PCIe总线层次结构中,事务层最易理解,同时也与系统软件直接相关。
5.4 TLP中与数据负载相关的参数的更多相关文章
- 在MyBatis中查询数据、涉及多参数的数据访问操作、插入数据时获取数据自增长的id、关联表查询操作、动态SQL、关于配置MyBatis映射没有代码提示的解决方案
1. 单元测试 在单元测试中,每个测试方法都需要执行相同的前置代码和后置代码,则可以自定义2个方法,分别在这2个方法中执行前置代码和后置代码,并为这2个方法添加@Before和@After注解,然后, ...
- 论Scrapy中的数据持久化
引入 Scrapy的数据持久化,主要包括存储到数据库.文件以及内置数据存储. 那我们今天就来讲讲如何把Scrapy中的数据存储到数据库和文件当中. 终端指令存储 保证爬虫文件的parse方法中有可迭代 ...
- 以使用QSqlQuery向数据库中插入数据为例,做一个小结
背景: 最近在使用Qt+SQLite写一个本地数据库管理程序(使用者不懂SQL),在写向数据库中插入数据的 相关的函数时,我遇到了几个问题(暂时就这些): 1.向指定字段插入指定数据时,读取到的数据都 ...
- SQLyog中创建数据表及相关查询方法
USE du; /*1.创建账务表 id name mony*/ CREATE TABLE zhangwu(id INT PRIMARY KEY AUTO_INCREMENT, sname VARCH ...
- sqlserver中的数据导到mysql相关
一.在sqlserver中生成数据表脚本,粘贴到记事本中,如下语法要进行替换 1.int IDENTITY (1, 1) NOT NULL——>id int unsigned NOT NULL ...
- 『现学现忘』Docker基础 — 30、Docker中数据卷相关命令
目录 1.Volume命令说明 2.Volume命令的使用 (1)创建数据卷 (2)查看本地数据卷列表 (3)打印myVolume数据卷的详细信息 (4)删除数据卷 (5)删除所有未使用的数据卷 3. ...
- 查看linux中swap内存的相关参数
内容主要来源于:linux的内存回收和交换 各项命令查看的linux环境是:Linux SUSE-33 2.6.32.12-0.7-defaul zone? 内存管理的相关逻辑都是以zone为单位的, ...
- 一步一步在Windows中使用MyCat负载均衡 上篇
传统关系型数据库的分布式开发通常需要自己做,不仅耗时耗力而且效果不是很理想,当想快速搭建时,最初想到的是看有没有第三方,网上牛人还是很多的,做得比较好的其中之一Mycat,它是开源的分布式数据库系统, ...
- 一步一步在Windows中使用MyCat负载均衡 下篇
之前在 一步一步在Windows中使用MyCat负载均衡 上篇 中已经讲了如何配置出MyCat.下面讲其相关的使用. 五.配置MyCat-eye 对于MyCat监控官网还提供一个MyCat-eye w ...
随机推荐
- Git分支高级管理[四]
标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 切换分支 git checkout 撤销对文件的修改 git checkout -- ...
- 在UITableView顶部制作简单的UISegmentControl实例方法
// http://www.tuicool.com/articles/yUfURj 使用方法 如上图: 分两步: 一.创建320长度背景,高不超过40最好 //segment背景图 UIImageVi ...
- re模块与正则表达式
一.正则表达式概念 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达式.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),是计算机科 ...
- 安装redis 2.6.4
下载redis-2.6.4下载链接:http://pan.baidu.com/s/1eQ9Z8NS make MALLOC=jemalloc/server/redis2/src/redis-serve ...
- cglib应用
JDK的动态代理,经常被用来动态地创建对象的代理.JDK的动态代理用起来非常简单,但是有一个限制,就是使用动态代理的对象必须实现一个或多个接口.如果想代理没有实现接口,还可以使用cglib包来完成代理 ...
- 使用angular/react/vue实现相同的面试题组件
面试题要求如下所示 1.angular: <!DOCTYPE html><html lang="en"><head> <meta char ...
- C#开发短信发送
//需要用到的命名空间 using System.Net;using System.IO;using System.Text;//调用时只需要把拼成的URL传给该函数即可.判断返回值即可public ...
- 蛋疼的_after_insert
这两天在做一个素材类的网站,用的依旧是TP3.2,在做到发布话题这部分的时候,发现了一个问题,我在添加话题的时候在模型里写了个钩子函数_after_insert(),希望在新增话题数据之后同时将话题的 ...
- log4cpp退出时内存泄露的修复方案
1.缘由 一直对log4cpp非常有好感,就在自己的项目中集成了log4cpp1.1.1版本,并围绕着它建立了一系列的封装函数方便外部调用.写完了一个测试代码后,忽然想看看自己写的程序有没有内存泄露问 ...
- idea编译时JDK版本变化
修改参考:http://www.cnblogs.com/woshimrf/p/5863248.html 添加maven-compiler-plugin插件.