searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

mlnx RDMA aeq/ceq分析

2025-03-25 05:33:33
2
0

一、概述

从下往上,依次是:

1、硬件产生中断信号

2、Eq收到中断信号,触发中断函数。

3、中断函数唤醒阻塞的线程。

4、read读取到数据。

二、驱动侧中断的初始化

流程描述:

1、驱动初始化阶段,mlx5_irq_table_init()创建irq table;

2、mlx5_irq_table_create()根据PF和SF的个数申请MSI-X中断向量个数,根据中断向量个数,初始化PF和SF的个数填充irq table,用于管理中断。

3、eq初始化阶段mlx5_eq_table_init(),创建eq table,用于管理eq;初始化用于中断处理的atomic notifier链表。

4、mlx5_eq_table_create()调用create_async_eqs初始化async eq,使用MSI-X的最后一个中断向量,注册中断,mlx5_eq_async_int()是async eqs的中断处理函数。用于处理command等一些异步事件。

5、mlx5_eq_table_create()调用create_comp_eqs初始化completion eq,批量注册MSI-X中断,完成eq队列的实例化,一个eq对应一个irq,过程中将mlx5_cq_tasklet_cb()函数注册到tasklet上,此函数是软中断的调度处理函数;mlx5_eq_comp_int()是completion eq的硬中断处理函数。

备注:

1、eq使用的通知机制是atomic notifier chains机制实现中断的上半部分,tasklet机制实现中断的下半部分。

2、eq使用的是radix tree管理cqn,即一个eq对应多个cq。

三、用户态的操作

流程描述:

1、调用ibv_create_comp_channel()函数创建completion channel,函数会创建event queue,调用rdma_alloc_begin_uobject()得到一个索引到内核的fd,event queue和此fd相关联。

2、调用ibv_create_cq()函数创建cq,

(1) 将创建的completion channel得到的fd传入内核,根据fd找到对应的event queue;

(2) 初始化completion channel的处理函数ib_uverbs_comp_handler;

(3) 初始化tasklet的处理函数mlx5_ib_cq_comp();

(4) 初始化completion eq的处理函数mlx5_add_cq_to_tasklet();

(5) 调用mlx5_eq_add_cq()函数将cqn插入到radix tree,与eq关联。

3、调用ibv_req_notify_cq()函数在cq中请求一个完成通知。

4、调用ibv_get_cq_event() 阻塞等待completion channel的通知,本质上使用read函数读取创建completion channel得到的fd。

5、等到completion channel事件通知,调用ibv_poll_cq()从cq中查询已完成的WC。

四、驱动中断的交互

1、驱动中断注册,初始化完成后,等待硬件产生中断信号。

2、硬件产生中断信号,irq_int_handler()函数响应中断进行中断处理。

3、如果是最后一个中断向量送上来的信号,获取eqe,根据注册的中断类型,调用atomic_notifier_call_chainhen处理对应类型的中断事件。

4、如果是其他中断向量送上来的信号,atomic_notifier_call_chain会通知到mlx5_eq_comp_int()函数处理中断。

5、mlx5_eq_comp_int()函数,根据入参nb可以得到eq队列指针,读取eqe,从EQE读取cqn,索引到对应的cq队列,调用cq上注册的completion函数mlx5_add_cq_to_tasklet。

6、mlx5_add_cq_to_tasklet()函数将需要进行触发的cq上链到tasklet list,只有当链表为空的时候才能上链,如果链表不为空,表示当前cq已经上链了。

7、调用tasklet_schedule,进入中断的下半部处理,调用到mlx5_cq_tasklet_cb()。

8、mlx5_cq_tasklet_cb()调用在创建cq时注册的mlx5_ib_cq_comp()函数。

9、mlx5_ib_cq_comp()函数调用ib_uverbs_comp_handler()函数。

10、ib_uverbs_comp_handler()函数调用wake_up_interruptible()唤醒对应阻塞的线程,通知用户态处理。

0条评论
0 / 1000
z****n
9文章数
1粉丝数
z****n
9 文章 | 1 粉丝
原创

mlnx RDMA aeq/ceq分析

2025-03-25 05:33:33
2
0

一、概述

从下往上,依次是:

1、硬件产生中断信号

2、Eq收到中断信号,触发中断函数。

3、中断函数唤醒阻塞的线程。

4、read读取到数据。

二、驱动侧中断的初始化

流程描述:

1、驱动初始化阶段,mlx5_irq_table_init()创建irq table;

2、mlx5_irq_table_create()根据PF和SF的个数申请MSI-X中断向量个数,根据中断向量个数,初始化PF和SF的个数填充irq table,用于管理中断。

3、eq初始化阶段mlx5_eq_table_init(),创建eq table,用于管理eq;初始化用于中断处理的atomic notifier链表。

4、mlx5_eq_table_create()调用create_async_eqs初始化async eq,使用MSI-X的最后一个中断向量,注册中断,mlx5_eq_async_int()是async eqs的中断处理函数。用于处理command等一些异步事件。

5、mlx5_eq_table_create()调用create_comp_eqs初始化completion eq,批量注册MSI-X中断,完成eq队列的实例化,一个eq对应一个irq,过程中将mlx5_cq_tasklet_cb()函数注册到tasklet上,此函数是软中断的调度处理函数;mlx5_eq_comp_int()是completion eq的硬中断处理函数。

备注:

1、eq使用的通知机制是atomic notifier chains机制实现中断的上半部分,tasklet机制实现中断的下半部分。

2、eq使用的是radix tree管理cqn,即一个eq对应多个cq。

三、用户态的操作

流程描述:

1、调用ibv_create_comp_channel()函数创建completion channel,函数会创建event queue,调用rdma_alloc_begin_uobject()得到一个索引到内核的fd,event queue和此fd相关联。

2、调用ibv_create_cq()函数创建cq,

(1) 将创建的completion channel得到的fd传入内核,根据fd找到对应的event queue;

(2) 初始化completion channel的处理函数ib_uverbs_comp_handler;

(3) 初始化tasklet的处理函数mlx5_ib_cq_comp();

(4) 初始化completion eq的处理函数mlx5_add_cq_to_tasklet();

(5) 调用mlx5_eq_add_cq()函数将cqn插入到radix tree,与eq关联。

3、调用ibv_req_notify_cq()函数在cq中请求一个完成通知。

4、调用ibv_get_cq_event() 阻塞等待completion channel的通知,本质上使用read函数读取创建completion channel得到的fd。

5、等到completion channel事件通知,调用ibv_poll_cq()从cq中查询已完成的WC。

四、驱动中断的交互

1、驱动中断注册,初始化完成后,等待硬件产生中断信号。

2、硬件产生中断信号,irq_int_handler()函数响应中断进行中断处理。

3、如果是最后一个中断向量送上来的信号,获取eqe,根据注册的中断类型,调用atomic_notifier_call_chainhen处理对应类型的中断事件。

4、如果是其他中断向量送上来的信号,atomic_notifier_call_chain会通知到mlx5_eq_comp_int()函数处理中断。

5、mlx5_eq_comp_int()函数,根据入参nb可以得到eq队列指针,读取eqe,从EQE读取cqn,索引到对应的cq队列,调用cq上注册的completion函数mlx5_add_cq_to_tasklet。

6、mlx5_add_cq_to_tasklet()函数将需要进行触发的cq上链到tasklet list,只有当链表为空的时候才能上链,如果链表不为空,表示当前cq已经上链了。

7、调用tasklet_schedule,进入中断的下半部处理,调用到mlx5_cq_tasklet_cb()。

8、mlx5_cq_tasklet_cb()调用在创建cq时注册的mlx5_ib_cq_comp()函数。

9、mlx5_ib_cq_comp()函数调用ib_uverbs_comp_handler()函数。

10、ib_uverbs_comp_handler()函数调用wake_up_interruptible()唤醒对应阻塞的线程,通知用户态处理。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0