前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >RDMA技术 - Nvidia DPU_MLX5驱动手册 - 完成队列

RDMA技术 - Nvidia DPU_MLX5驱动手册 - 完成队列

原创
作者头像
晓兵
发布2024-12-21 20:31:52
发布2024-12-21 20:31:52
25600
代码可运行
举报
文章被收录于专栏:DPUDPU
运行总次数:0
代码可运行

术语

  • CQC: CQ上下文

简介

完成队列 (第8.19章节)

HCA 实现完成队列,用于在工作请求完成后发布完成报告。本节讨论 CQ 的结构和操作。CQ 是一个包含以下实体的对象:

  1. 完成队列缓冲区 - 一个几乎连续的循环缓冲区,可由用户级软件访问,并由硬件用于发布完成 - 写入完成队列元素 (CQE)。创建 CQ 时必须分配此区域。可以通过 QUERY_HCA_CAP 命令 (log_max_cq_sz) 检索支持的最大 CQ 大小。CQE 大小为 64 或 128 字节,在创建 CQ 时配置。
  2. 完成队列上下文 (CQC) - 描述 CQ 属性的数据结构,在创建 CQ 时由 SW 传递给设备。HCA 硬件每个虚拟 HCA 最多可支持 16M 个 CQ;给定硬件配置支持的实际数量可以通过 QUERY_HCA_CAP 命令 (log_max_cqs) 检索。有关更多详细信息,请参阅第 716 页上的“完成队列上下文 (CQC)”。
  3. CQ DoorBell 记录 - 包含最近发布的 CQ 命令和消费者索引信息的结构,可供用户级软件访问。

完成队列缓冲区

CQ 是一个虚拟连续的内存缓冲区,HCA 使用它来发布完成报告,应用软件使用它来轮询完成报告。此缓冲区由主机软件在创建 CQ 时分配,其物理地址传递给 HCA。与此缓冲区关联的内存作为物理页面列表传递给 HCA。CQ 缓冲区必须在 CQE 大小边界上对齐。每个 CQ 缓冲区包含两个对象: CQ 和 CQ 门铃记录。CQ 缓冲区结构如图 29 所示。

硬件将完成(写入 CQE)发布到 CQ。在 CQE 消耗后,SW 会更新 CQ 门铃记录。除了 CQE 消耗信息外,CQ 门铃记录还包含有关 CQ 状态(准备事件、准备请求事件: Armed for Event, Armed for Solicited Event)的信息。CQ 是一个虚拟连续的循环缓冲区,其中包含 HCA 在完成与此 CQ 相关的 I/O 操作后发布的完成队列条目 (CQE)。应用程序(非特权)软件可以读取 CQ 缓冲区以轮询 HCA 发布的完成情况。缓冲区由两个计数器管理:

• 生产者计数器 – 由硬件维护的计数器,每向 CQ 写入一个 CQE 时,计数器都会递增。生产者计数器的最低有效位(由 CQ.log_cq_-size 字段指示)称为生产者索引。生产者索引指向 CQ 中硬件要写入的下一个条目。请参阅第 434 页的“CQ 计数器”。

• 消费者计数器 – 由应用程序软件维护的计数器,每从 CQ 成功轮询一个 CQE 时,计数器都会递增。消费者计数器的最低有效位(由 CQ.log_cq_size 字段指示)称为消费者索引。消费者索引指向下一个要轮询的 CQE。请参阅第 434 页的“CQ 计数器”

这两个计数器都被 SW 视为有符号整数如果生产者计数器等于消费者计数器,则 CQ 为空。如果生产者计数器减去消费者计数器等于 CQ 大小,则 CQ 已满。成功轮询 CQ(即找到新的 CQE)后,软件将更新消费者计数器,硬件将使用该计数器来监控潜在的 CQ 溢出。如果 CQ 已满,而另一个 CQE 需要发布到 CQ,则如果启用了溢出检测,则硬件将执行以下操作:

  1. 将 CQ 转移到适当的错误状态。
  2. 将 QP/RQ/SQ 转移到错误状态。
  3. 生成适当的事件。

如果 CQ 已满,而另一个 CQE 需要发布到 CQ,并且如果溢出检测被禁用,则旧的 CQE 可能会被覆盖。

CQE格式

64字节CQE和128字节CQE格式如下:

64B: 0x0~0x3C(60B)

128B: 接收完成报告的扩展 CQE 段的格式如上表 146 所示, 0x0~0x3C(用于GRH或内联64B), 0x40(64)~0x7C(124): 存放64B的CQE内容

当 GRH 位于扩展 CQE 的第一段时,它位于字节 0x0 - 0x27 中。设备中扩展了 CQE 格式,以便能够携带操作时间戳以及接收操作中收到的数据的原子响应和/或头部。设备 CQE 格式如表 145 所示。通过在创建 CQ 时设置 cqe_sz 参数,每个 CQ 都可以独立配置为报告 64 或 128 字节 CQE。SQ 将完成情况报告给扩展 CQ,可以配置为将原子或读取响应的数据放置在 CQE(而不是将其写入 WQE 指定的内存缓冲区),用于响应适合 CQE 数据部分的操作(最大 64 字节,转换为 64 字节的原子/读取)。请注意,连接到此类 CQ 的 QP 上的 WQE 必须请求生成 CQE(CE 字段应为 0x2 或 0x3)。有关详细信息,请参阅第 312 页上的表 42“常规 - Ctrl 段格式”。可以将 SQ 配置为始终将数据放置在 inline_64 段中,或者如果数据大小小于或等于 32B,则将其放置在 inline_32 段中。只有配置为 128B CQE 的 CQ 才可以将数据放置在 inline_64 段中。RQ 可以配置为将消息放置到 CQE 的数据部分,这对于节省 CPU 和芯片组上的缓存未命中非常方便。只有当整个有效载荷适合 CQE 的数据部分时,硬件才会将数据放置到 CQE。对于 UD 和 DC,如果存在 GRH,它可能会分散到 CQE 的 data_64 段中。如果 GRH 分散到 CQE,数据将不会分散到 CQE,数据到 CQE 的放置由基本 CQE 部分中的 cqe_format 和 l3_hdr 位指示。 RQ 可以配置为始终将数据放置在 inline_64 段中,或者仅对于 RC/XRC QP,如果数据大小小于或等于 32B,则将其放置在 inline_32 段中。只有配置为 128B CQE 的 CQ 才可以将数据放置在 inline_64 段中。CQ 条目 (CQE) 的基本部分包含足够的信息来将 CQE 与其 WQE 关联起来,并携带足够的信息让 SW 了解发生了什么。 64B CQE 布局如表 145“64B 完成队列条目格式布局”(第 435 页)中所示。报告错误的基本 CQE 的格式如表 159“带错误的完成 CQE 布局”(第 455 页)中所示。报告签名错误的 SIGERR_CQE 的格式如表 161“SIGERR CQE 条目格式布局”(第 458 页)中所示。CQE 字段详细描述如表 147 中所示。部分字段解析如下:

CE: 拥塞经历

拥塞经历 – 数据包被 tx 溢出机制标记为拥塞。仅当 tx_lossy_overflow_oper 设置为 mark 时才会设置此字段。请参阅 TBD

ml_path

对于 IB UD CQE 上的响应者:这些是传入 UD 数据包中 DLID 的较低 LMC 位,此字段中不属于 LMC 位的较高位由 HW 清零。如果传入消息 DLID 是允许的 LID 或传入消息是多播的,则无效。否则,此字段保留

组合字段: immediate / invalidate key / pkey/ flow_table_metadata

对于响应者 CQE,如果完成的 WQE 操作码是“立即发送”或“立即写入”,则此字段包含收到消息的立即字段。 对于响应者 CQE,如果完成的 WQE 操作码是“无效发送”,则此字段包含已无效的 R_key。 对于 GSI 数据包的响应者 CQE,此字段的位 15:0 包含数据包的 Pkey。 对于 Eth RQ,此字段保存在 metadata_reg_b 中的数据包流表处理期间收集的元数据

byte_cnt/mini_cqe_num: 数据总字节/最小CQE数量

传输的数据的字节数。适用于 RDMA 读取、Atomic 和接收完成。Byte_cnt 指定分散到缓冲区或 CQE 的总字节数(如果启用了分散到 CQE)。

对于 RoCE/IB:如果 GRH/IPv4/IPv6 未分散到 CQE,则其 40B 长度包含在字节数中(即使不存在 GRH)。

对于 Header Data Split:接收队列是 headers-separation 的主题,byte_cnt[31:24] 指定分散到第一个分散条目的字节数(headers 的长度)。byte_cnt[23:0] 指定收到的总字节数(不含 headers)。

对于 LRO 消息(lro_num_seg 字段不清除):指定消息的总长度。

对于压缩 CQE(cqe_format == 3),指定 Mini CQE 的总数(将 > 1)。

对于跨步 WQ:请参见第 304 页上的第 8.9.1.3 节“跨步接收 WQ”。byte_cnt[31:31] ==1 表示 CQE 属于 FILLER CQE 类型。byte_cnt[30:30]:指定消息结尾(仅适用于 IB)。byte_cnt[29:16]:指定已使用的跨步数。byte_cnt[15:0]:指定接收的字节数(包括填充)。对 FILLER CQE 和 ERROR CQE 无效。

对于填充消息,填充被排除在外

Signature: 数据签名校验

CQE 的逐字节异或 - 签名保护(请参阅第 879 页上的“完成和事件队列元素(CQE 和 EQE)”)。如果整个 CQE(包括签名字段)的逐字节异或和 CQE 索引为 0xff0xFF,则 CQE 有效。对于 128B CQE,如果数据/GRH 已写入其中(cqe_format == 2 或 grh == 2),则将考虑 GRH/inline_64 部分的签名校验

Opcode:操作码

0x0:Requester 0x1:Responder_RDMA_Write_with_Immediate 0x2:Responder_Send 0x3:Responder_Send_with_Immediate 0x4:Responder_Send_with_Invalidate 0x5:Resize_cq - 请参阅第 453 页上的“调整 CQ 大小” 0x6:No_packet_operation 0x12:SIGERR - 签名错误 CQE,(SIGERR_CQE 格式如第 458 页上的表 161“SIGERR CQE 条目格式布局”中所示)。 0xD:Requester_Error -(ERR_CQE 格式如表 8.19.7,“完成并出错” 在第 455 页中所示) 0xE:Responder_Error -(ERR_CQE 格式如表 8.19.7,“完成并出错” 在第 455 页中所示) 0xF:Invalid_CQE - 所有权位无效,CQE 归 HW 所有

cqe_format: CQE格式

0 - no inline data in the CQE , CQE中没有Inline数据

1 - inline data in the data_32 segment of the CQE (offsets 00h-1Ch) , 将Inline的32字节存放在00~1C中

2 - inline data in the data_64 segment of the CQE (additional 64B) : 将Inline的64字节存放在00~3C中

3 - Compressed CQE, 压缩CQE

Please note that if cqe_format == 3, mini_cqe_num > 1: 请注意,如果 cqe_format == 3,则 mini_cqe_num > 1

门铃记录

CQ 门铃记录位于 CQ 上下文指向的物理地址中。CQ 门铃记录在 8B 边界上对齐。从 CQ 中获取 CQE(轮询完成动词)后,软件更新 update_ci。当 CQ 准备好生成事件(请求完成通知动词)时,软件更新 cmd_sn、cmd 和 cq_ci, 格式如下:

update_ci: 上次轮询的 CQE 的消费者计数器

cmd_sn: 命令序列号。此字段的值在创建时应初始化为 2。对于第一个 DoorBell敲响时,此值应为 0,并且应在完成事件后的每个第一个 DoorBell 敲响后递增。也就是说,cmd_sn = num_of_completion_event_delivered % 4 , 取值为[0, 1, 2, 3]

cmd:

  • 1 - 请求下一个 Solicited 完成事件的通知。arm_ci 字段应指定 DoorBell 响铃时的 CQ 消费者计数器。
  • 0 - 请求下一个 Solicited 或 Unsolicited 完成事件的通知。计数器字段应指定 DoorBell 响铃时的 CQ 消费者计数器。

arm_ci: 如 cmd 中所述的, 用于设置 CQ 的消费者计数器

轮询完成

CQE归属者/所有权

CQE 所有权由 CQE 中的 Owner 位定义。每次 CQ 绕圈时(wraps around),表示 SW 所有权的值都会翻转(flipped)。以下伪代码解释了如何确定 CQE 属于 SW 所有权

当创建或调整 CQ 大小时,软件需要使用所有者位 = 硬件, 来初始化整个 CQE 缓冲区

MLX5参考实现:

代码语言:javascript
代码运行次数:0
复制
static inline int mlx5_get_next_cqe(struct mlx5_cq *cq,
                    struct mlx5_cqe64 **pcqe64,
                    void **pcqe)
{
    void *cqe;
    struct mlx5_cqe64 *cqe64;
​
    cqe = next_cqe_sw(cq);
    if (!cqe)
        return CQ_EMPTY;
​
    cqe64 = (cq->cqe_sz == 64) ? cqe : cqe + 64;
​
    ++cq->cons_index;
​
    VALGRIND_MAKE_MEM_DEFINED(cqe64, sizeof *cqe64);
​
    /*
     * Make sure we read CQ entry contents after we've checked the
     * ownership bit.
     */
    udma_from_device_barrier();
​
#ifdef MLX5_DEBUG
    {
        struct mlx5_context *mctx = to_mctx(cq->verbs_cq.cq_ex.context);
​
        if (mlx5_debug_mask & MLX5_DBG_CQ_CQE) {
            mlx5_dbg(mctx->dbg_fp, MLX5_DBG_CQ_CQE,
                 "dump cqe for cqn 0x%x:\n", cq->cqn);
            dump_cqe(mctx, cqe64);
        }
    }
#endif
    *pcqe64 = cqe64;
    *pcqe = cqe;
​
    return CQ_OK;
}
​
static void *get_sw_cqe(struct mlx5_cq *cq, int n)
{
    void *cqe = get_cqe(cq, n & cq->verbs_cq.cq.cqe);
    struct mlx5_cqe64 *cqe64;
​
    cqe64 = (cq->cqe_sz == 64) ? cqe : cqe + 64;
​
    if (likely(mlx5dv_get_cqe_opcode(cqe64) != MLX5_CQE_INVALID) &&
        !((cqe64->op_own & MLX5_CQE_OWNER_MASK) ^ !!(n & (cq->verbs_cq.cq.cqe + 1)))) {
        return cqe;
    } else {
        return NULL;
    }
}
​
static void *get_cqe(struct mlx5_cq *cq, int n)
{
    return cq->active_buf->buf + n * cq->cqe_sz;
}

报告完成

在执行轮询以完成时,软件会检查所有者位并检查操作码字段是否与 consumer_counter 指向的 CQE 条目的 0xf 不同。如果所有者条目值为 SW,则 CQE 有效,软件应使用该条目并增加 CQ 门铃记录中的消费者计数器。只要所检查的 CQE 的所有者位具有 SW 值,就必须重复此操作。轮询完成算法的伪代码如下所示:

注意:

  • 在看到 CQE 归 SW 所有后,SW 应该执行内存屏障并重新读取 CQE。
  • 对于多个 CQE 轮询,退出算法时只允许更新一次 DoorBell 记录

请求完成通知

通过更新 DoorBell 记录并将相应命令写入 CQ Doorbell Register 来实现此事件的订阅(第 250 页上的“UAR 页面格式”)。用户可以获取请求事件通知或非请求事件通知。在本节中:

• “请求下一个完成的通知”将由 ARM_NEXT 表示

• “请求下一个请求完成(SE)的通知”将由 ARM_SOLICITED 表示

应用软件可以启用 CQ,以便在映射到 CQ 的 WQ 上完成工作请求后生成事件。如果新的 CQE 到达 CQ 并且满足以下条件之一,则 CQ 会生成完成事件:

  1. 在 CQ 上执行了 ARM_NEXT,并且此 CQ 上已生成完成
  2. 在 CQ 上执行了 ARM_SOLICITED,并且映射到此 CQ 的 WQ 已收到设置了 Solicited Event 位的 IB 消息,或者发送了设置了 E 位的已完成

WQE 通过写入 EQE 向 EQ 报告完成事件,并且在执行具有更高 cmd_sn 值的新通知请求之前不会生成进一步的事件。cmd_sn 的必需用法在第 449 页的“CQ DoorBell 记录”中进行了描述。每当 verbs 消费者请求完成通知时,软件都应决定是否要响门铃。如果最后一个 cmd_sn 与要响的 cmd_sn 不同,则应响门铃。否则,如果两个 cmd_sn 值相等,则使用表 156的规则

表 156 - 使用重复的 cmd_sn 敲响 ARM CQ 门铃: 本轮命令中的设置ARM_SOLICITED 且上次ARM的命令状态为ARM_NEXT则不触发门铃, 其他情况均响铃并产生事件

如果在报告完成事件后将新的 CQE 发布到 CQ,并且这些 CQE 尚未被使用,则在执行通知请求后将立即生成事件。事件生成和处理由事件状态机控制。其转换如图 31 所示

Mellanox HCA 跟踪用户收到事件的最后一个索引。使用此索引,可以保证在执行请求完成通知并且已报告 CQE 时立即生成事件。此外,HCA 还提供了机制来调节 CQ 生成的事件,如第 508 页的“完成事件调节”中所述

完成队列更新错误

软件错误可能导致CQ 更新事件。具体来说,在发布完成时会检查 CQ 溢出,如果遇到,则将 QP/RQ/SQ 转换为适当的错误状态。硬件将通过写入 EQ 的 EQE 将辅助信息传递给软件。CQ 更新(和错误发现)与 WQE 执行不同步。因此,可以向远程请求发送肯定确认,随后可能会检测到 CQ 溢出(或其他错误)。由于错误,硬件可能不会写入 CQE,并且 CQ 将转换为错误状态以及导致 CQ 错误的 QP/RQ/SQ。为了避免这些错误,软件必须确保发布到 QP/RQ/SQ 的 WQE 数量不超过与此 QP/RQ/SQ 关联的 CQ 中的条目数量。当多个 QP/RQ/SQ 将完成发布到同一个 CQ 中时,此检查必须是累积的

调整 CQ 大小

此功能允许修改 CQ 大小或 CQE 大小,执行此流程时,驱动程序不得修改 CQC 中的任何其他字段。为了调整 CQ 或 CQE 大小,SW 需要为 CQ 分配一个新缓冲区并将其固定。然后,通过提交 MODIFY_CQ 命令(op_mod =1)(调整 CQ 大小)。在此命令中,SW 需要:

  1. 传递物理页面 - 就像打开 CQ 时所做的那样。
  2. 在 CQ 上下文中填写以下字段: a. log_cq_size b. page_offset c. log_page_size

仅当 QUERY_HCA_CAP 命令中的 resize_cq_en =1 时,才启用调整 Cq 大小(请参见第 29.3.4 节“QUERY_HCA_CAP - 查询设备功能”,第 1667 页)。在处理命令时,硬件将向旧 CQ 报告一个名为 Resize_Cq(CQE.opcode = 5h)的特殊 CQE,表示调整大小操作已完成。请注意,这可以在 MODIFY_CQ 命令完成之前或之后观察到。因此,建议驱动程序在创建可调整大小的 CQ 时为一个额外的 CQE 预留空间。一旦观察到特殊 CQE,驱动程序就可以取消固定旧 CQ 缓冲区(无论这发生在 MODIFY_CQ 命令完成之前还是之后)。当 MODIFY_CQ 命令完成时,HW 将不会尝试访问旧缓冲区,请注意它仍然可以包含有效的 CQE;因此,SW 仍应轮询这个旧的缓冲区以获取 CQE,直到遇到指示移动到新缓冲区的特殊 CQE

请注意,用于调整 CQ 大小的 MODIFY_CQ 命令不能嵌套;因此,在前一个命令完成之前,无法向同一 CQ 发出带有 Resize CQ 操作码修饰符的新 MODIFY_CQ 命令。当移动到新的 CQE 缓冲区时,SW 应开始轮询的索引是根据消费者计数器和新的 CQ 大小计算的。因此,软件需要获取 consumer_counter 的 log_cq_size 最低有效位,并使用它们来引用新缓冲区中的第一个 CQE。所有权位的计算方式类似。图 32 说明了调整大小的过程

建议在 MODIFY_CQ 命令结束时,或在开始任何新的调整大小操作之前,将 CQE 从旧缓冲区复制到新缓冲区。该过程包括遍历旧缓冲区,查找特殊 CQE,然后将所有先前的 CQE 复制到新 CQ(省略特殊 CQE)。这简化了此 CQ 生成的 CQE 数量的核算问题(始终最多一个额外的 CQE,即调整大小特殊 CQE)。由于消费者/生产者计数器保持不变,因此 CQ 的准备过程不受调整大小操作的影响。特殊调整大小 CQE 的格式如表 157 所示

错误完成

错误完成向 CQ 报告的方式与常规完成类似。在错误完成的情况下,并非所有 CQE 字段都有效,并且某些字段具有不同的含义。对于每个错误完成的 WQE,都会生成一个错误完成;“错误完成的 CQE”由操作码字段中的 13 或 14 值指定。错误完成的 CQE 条目的布局如表 159 所示。

syndrome: 综合错误 IB compliant completion with error syndrome 0x1: Local_Length_Error 0x2: Local_QP_Operation_Error 0x4: Local_Protection_Error 0x5: Work_Request_Flushed_Error 0x6: Memory_Window_Bind_Error 0x10: Bad_Response_Error 0x11: Local_Access_Error 0x12: Remote_Invalid_Request_Error 0x13: Remote_Access_Error 0x14: Remote_Operation_Error 0x15: Transport_Retry_Counter_Exceeded 0x16: RNR_Retry_Counter_Exceeded 0x22: Aborted_Error other is Reserved 综合错误是根据 InfiniBand 架构规范第 1 卷定义的。有关综合错误的详细说明,请参阅 IB 规范的软件传输接口和软件传输动词章节 一旦 QP/RQ/SQ 转换为错误状态,随后发布到 QP/RQ/SQ 的 WQE 将导致向相关 CQ 报告错误完成(刷新)

SIGERR CQE - 签名错误

CQE SIGERR CQE 以与常规完成类似的方式报告给 CQ。这种类型的 CQE 是针对设备根据 Mkey 发现的第一个签名错误生成的。SIGERR CQE 由 Opcode 字段中的 12 个值指定

CQE 压缩

CQE 压缩通过将多个 CQE 合并并压缩为单个合并的 CQE 来减少 PCI 开销。成功压缩可提高消息速率,尤其是对于小数据包流量。由 RQ/Responder 或 SQ/Requester 生成的所有 64B CQE 格式(有某些限制)均支持 CQE 压缩。待办事项 - 添加指示,表明此功能支持网络卸载

不是将完整的 CQE 写入内存,而是合并和压缩多个几乎相同的 CQE。无论压缩的 CQE 数量有多少,CQE 之间共享的信息都只写入一次。此外,每个 CQE 只写入唯一信息(与完整 CQE 大小相比,字节数较少)

CQE 压缩块

此块包含多个压缩的 CQE。CQE 压缩块包含 CQE 属性的单个副本,这些属性在所有压缩的 CQE(称为标题,见下文)和多个迷你 CQE(压缩形式的 CQE)之间共享。

标题

标题包含在 CQE 压缩块中的所有压缩 CQE 之间共享的信息。在每个压缩块中,无论压缩 CQE 的数量有多少,都只有一个标题。

迷你 CQE

压缩形式的 CQE,它包含提取单个完整 CQE 所需的一些数据,例如 8 字节而不是 64 字节。属于同一 CQE 压缩块(称为标题)的所有压缩 CQE 之间的共享信息只写入一次,并且每个压缩 CQE(称为迷你 CQE)仅写入每个压缩 CQE 中的独特信息(例如 8 字节)

CQE 压缩配置

如果支持 CQE 压缩(HCA_CAP.cqe_compression == 1),则可以通过在创建 CQ 时将 CQ.cqe_compressing_en 设置为 1/0 来启用/禁用每个 CQ 的 CQE 压缩。应配置 CQ.mini_cqe_res_format 以决定响应方的迷你 CQE 格式。请注意,仅当 HCA_CAP.cqe_compression_128b==1 时才支持 128 字节 cqe 的 CQE 压缩

CQE压缩块格式

消费/生产计数器

HW 将每个压缩的 CQE 的生产者计数器增加为普通 CQE。请注意,标题写在第一个压缩 CQE 的索引处,第一个迷你 CQE 数组写在第二个压缩 CQE 的索引处。第二个迷你 CQE 数组位于第九个压缩 CQE 的索引处,依此类推。SW 必须为每个压缩的 CQE 增加消费者计数器,就像将其作为“普通”CQE 处理一样。如果 SW 决定在完成处理 CQE 压缩块的所有迷你 Cq 之前更新 DoorBell 记录,SW 负责复制标题和最后一个具有有效未处理迷你 CQE 的迷你 Cq 数组,因为 HW 可以覆盖这些 CQ 条目

CQE 所有者位

HW 仅在所有迷你 CQE 都写入后才更新标题的所有者位。SW 必须更新除标题之外的所有压缩 CQE 的 HW CQE 中的所有者位。HW CQE 位置是使用消费者指数计算的 - 与计算“普通”CQE 位置的方式完全相同。所有者位值应取自标题。注意:SW 有责任确保在更新所有者位后不访问 HW CQE 位置。另请注意,必须在更新 DoorBell 记录之前写入所有者位

CQE 压缩和中断

EQE 生成

CQE 压缩不影响 EQE 生成。也就是说,当启用 CQE 压缩时,EQE 的生成方式与禁用 CQE 压缩时相同。

带有 CQ Moderation(适度) 的 CQE 压缩

完成事件审核机制将每个迷你 CQE 视为普通 CQE。例如,如果 CQ.cq_max_count == 4,即使前 3 个 CQE 被压缩,第四个 CQE 的到来也会导致 EQE 生成。在这种情况下,如果需要,压缩会话将被强制终止,而无需等待压缩会话计时器到期或发生其他情况。请注意,第四个 CQE 不会被压缩。当完成事件审核计时器在生成 EQE 之前到期时,HW 将终止 CQE 压缩会话。因此,当 CQE 压缩与完成事件审核一起启用时,它不会“导致”CQE 压缩到期超时的延迟。

限制

• 分散到 CQE 不支持 CQE 压缩

• 仅当 HCA_CAP.cqe_compression_128b==1 时才支持 128 字节 cqe 的 CQE 压缩。

• 除了会话中的第一个压缩 CQE 之外,不支持压缩 CQE 的 CQE 签名

• 如果 CQ.mini_cqe_res_format,则除了会话中的第一个压缩 CQE 之外,不支持压缩 CQE 的校验和值报告。

• LRO CQE 不支持 CQE 压缩

• 除了会话中的第一个压缩 CQE 之外,不支持压缩 CQE 的硬件时间戳

完成队列上下文CQC

打开新的 CQ 时,软件应创建 CQ 上下文对象并使用 CREATE_CQ 命令将其传递给硬件

CQC 结构的格式如表 171 所示

status: 状态

代码语言:javascript
代码运行次数:0
复制
CQ status
0x0: OK
0x9: CQ_OVERFLOW
0xA: CQ_WRITE_FAIL
0xF: CQ_INVALID
Valid for the QUERY_CQ. only when HCA_CAP.cq_invalidate==1,
SW can set status to CQ_INVALID using MODIFY_CQ command

cqe_sz: CQE大小 0x0:BYTES_64 0x1:BYTES_128_IF_NEEDED - 对于 Cqe 的 128 字节内容,将生成 128 字节。对于 Cqe 的 64 字节内容,仅生成 64B 的 CQE 内容。 0x2:BYTES_128_ALWAYS - 对于 Cqe 的 128 字节内容,将生成大小 128 字节,与模式 0x1 相同。对于 Cqe 的 64 字节内容,将始终在 64B 的 CQE 内容之前添加 64 字节的零填充。仅当 HCA_CAP.cqe_128_always==1 时才支持

st: 状态

代码语言:javascript
代码运行次数:0
复制
Event delivery state machine
0x6: SOLICITED_NOTIFICATION_REQUEST_ARMED
0x9: NOTIFICATION_REQUEST_ARMED
0xA: FIRED
other: reserved
Valid for the QUERY_CQ command only.
Reserved for CREATE_CQ.

log_cq_size: CQ中的CQE个数(以2为底的幂次方作为该值)

Log (base 2) of the CQ size (in entries). Maximum CQ size is 2^22 CQEs (max log_cq_size is 22)

CQ 到 EQ 重映射

设备支持动态更改 CQ 向其报告完成事件的 EQ。这可以通过 MODIFY_CQ 命令完成(请参见第 29.9.4 节“MODIFY_CQ - 修改 CQ 参数”,第 1894 页)。成功完成重映射 EQ 的命令后,SW 必须调用或安排一个轮询修改后的 CQ 的过程。

CQE 时间戳

每个生成的 CQE 都包含一个 64 位时间戳。此字段保存生成 CQE 时采集的设备内部计时器的样本。应用程序可以使用时间戳来监视 I/O 操作的执行时间。使用时间戳选项合并 TCP 数据包的 LRO 操作的 CQE 不携带内部计时器时间戳。这由 Cqe 格式中的 lro_timestamp_is_valid 字段指示。请参阅表 145,“64B 完成队列条目格式布局”,第 435 页。

转换为实时 CQE

时间戳表示使用设备特定频率的内部计时器。要将时间戳转换为实时,比率在 HCA_CAP.device_frequency_khz 字段中给出(请参阅表 1571,“HCA 功能布局”,第 1671 页)。时间戳应除以频率以得出微秒级的值。

参考

Nvidia_Mellanox_Adapters_PRM

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 术语
  • 简介
    • 完成队列 (第8.19章节)
    • 完成队列缓冲区
    • CQE格式
      • CE: 拥塞经历
      • ml_path
      • 组合字段: immediate / invalidate key / pkey/ flow_table_metadata
      • byte_cnt/mini_cqe_num: 数据总字节/最小CQE数量
      • Signature: 数据签名校验
      • Opcode:操作码
      • cqe_format: CQE格式
    • 门铃记录
    • 轮询完成
      • CQE归属者/所有权
      • 报告完成
    • 请求完成通知
    • 完成队列更新错误
    • 调整 CQ 大小
    • SIGERR CQE - 签名错误
    • CQE 压缩
    • CQE 压缩块
    • 标题
    • 迷你 CQE
    • CQE 压缩配置
    • CQE压缩块格式
      • CQE 所有者位
    • CQE 压缩和中断
      • EQE 生成
      • 带有 CQ Moderation(适度) 的 CQE 压缩
      • 限制
    • 完成队列上下文CQC
    • CQ 到 EQ 重映射
    • CQE 时间戳
    • 转换为实时 CQE
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档