Linux NTB 学习笔记:ntb_pingpong 的 doorbell/message 最小闭环 ntb_pingpong 是最适合入门的 NTB client。它不使用 Memory Window 搬大数据,而是只验证最小控制面:link 是否 up、doorbell 是否能触发中断、scratchpad 或 message 是否能写到对端。
正因为它简单,所以很适合用来理解 NTB client 如何接管 ntb_dev,以及硬件事件如何回调到 client。
pp_probe() 的主线是:pp_check_ntb()、pp_create_data()、pp_init_flds()、pp_mask_events()、pp_setu p_ctx()、pp_setup_dbgfs()。
pp_check_ntb() 会检查 doorbell、scratchpad/message 是否可用。pp_create_data() 分配 pp_ctx。pp_init_flds() 计算本地 doorbell bit 和 peer 选择 mask。pp_mask_events() 先屏蔽 doorbell/message 事件,避免还没准备好就收到中断。
pp_setup_ctx() 最关键,它调用 ntb_set_ctx() 把 link_event 和 db_event 回调注册给 NTB core,然后 ntb_link_enable() 打开 link,并主动触发一次 ntb_link_event()。
pp_init_flds() 容易绕,因为它同时涉及 port number、peer index 和 doorbell bit。
in_db 是本端接收 doorbell 的 bit,通常按本地 port number 取 BIT(lport)。pmask 和 nmask 不是 doorbell mask,而是 peer index mask,用来在多 peer 场景里选择下一个 peer。
pingpong 的策略是优先选择端口号比自己大的 peer,没有就绕回选择比自己小的 peer。这样多端口时可以形成一个 ring。
pp_ping() 是发起一次 ping 的地方。它读取 count,把 count 写入 peer scratchpad[0] 和 peer message[0],然后调用 ntb_peer_db_set() 敲对端 doorbell。最后打开本端 in_db,准备接收对端回敲。
对端收到 doorbell 后,硬件驱动中断里调用 ntb_db_event(),NTB core 再回调 pp_db_event(),最终进入 pp_pong()。
pp_pong() 会读取本地 scratchpad/message,清 message 状态,count++,mask 并 clear 本地 doorbell,然后启动 timer,准备下一轮 ping。
对端 ntb_peer_db_set() -> 本端硬件收到 inbound doorbell -> 触发中断 -> 硬件驱动 ISR 调 ntb_db_event() -> NTB core 调 client 的 db_event -> pp_pong()
这里有 两 个 前提 :本端对 应 doorbell bit 没有 被 mask ; 对端敲的是本端关 心 的 bit。pingpong 里本端关 心 的是 in_db。
ntb_pingpong 能验证 link、doorbell、中断、scratchpad/message 这 些 控制面是否正常。它不能验证 Memory Window, 也 不能验证大数据 传输带宽 。
因 此 bring-up 时可以先用 pingpong 验证 基 本 链路 ,再看 ntb_perf 或 ntb_transport。对 于需要特殊 数据 路径 的 项目 , 也 可以 参考 pingpong 的事件 模型 ,写自己的 client。