CRM的request管理笔记

2024-01-07 20:05:26

1 request类型

request有两种,device request和link request。

  • link request
    link req是对link进行精确控制。
    link req是对每个link的请求,比如某一帧是否需要bubble recovery、某一帧是否需要长曝光等feature。
  • device request
    对一个设备进行每帧控制。设备包括:isp、flash、sensor、actuator等。
    camx node通过packet方式传递request的配置到kmd对应的驱动模块,驱动会保存好对应request配置。
    设备驱动会通知crm哪个request从umd已经加入到kmd了。(通过cam_req_mgr_cb_add_req函数通知)

link request数据原型

struct cam_req_mgr_sched_request_v2 {
	__s32 version;
	__s32 session_hdl;
	__s32 link_hdl;
	__s32 bubble_enable;
	__s32 sync_mode;
	__s32 additional_timeout;
	__s32 num_links;
	__s32 num_valid_params;
	__s64 req_id;
	__s32 link_hdls[MAX_LINKS_PER_SESSION];
};

2 link 中in_q介绍

  • 什么是in_q,它的职责?
    在link中存放的输入请求队列。

  • in_q在link中位置:
    link持有req_data, req_data中包含了in_q和req_tbl。
    在这里插入图片描述

link的结构体定义:

struct cam_req_mgr_core_link {
	int32_t                              link_hdl;
	int32_t                              num_devs;//link中有多少个device
	enum cam_pipeline_delay              max_delay;
    ...
	struct cam_req_mgr_core_workq       *workq;//自定义的workqueue,处理工作队列中work
	int32_t                              pd_mask;
	struct cam_req_mgr_connected_device *l_dev;//存放link中device
	struct cam_req_mgr_req_data          req; //req_data
	struct cam_req_mgr_timer            *watchdog;//看门狗,监控sof是否超时,sensor是否长时间没有出帧
	...
};

其中cam_req_mgr_req_data 定义中有in_q和 req_tbl。

struct cam_req_mgr_req_data {
	struct cam_req_mgr_req_queue *in_q; //保存Input request queue
	struct cam_req_mgr_req_tbl   *l_tbl;//保存request table
	int32_t                       num_tbl;//保存req table的个数
	struct cam_req_mgr_apply      apply_data[CAM_PIPELINE_DELAY_MAX];//保存apply data,就是req是setting
	struct cam_req_mgr_apply      prev_apply_data[CAM_PIPELINE_DELAY_MAX];
	struct mutex                  lock;
};
  • in_q定义
struct cam_req_mgr_req_queue {
	int32_t                     num_slots;  //当前存放slot个数
	struct cam_req_mgr_slot     slot[MAX_REQ_SLOTS]; //slot数组,用slot来存储每帧信息。MAX_REQ_SLOTS=48
	int32_t                     rd_idx;//读索引下标。每当收到SOF或EOF,要对req处理时,从rd_idx读取req
	int32_t                     wr_idx;//写索引下标。每当有req从umd通过sche req下发时,就会写入到wr_idx中
	int32_t                     last_applied_idx;//最新位置的读索引下标
};
  • in_q 图示
    input queue图示
    umd中通过session的ProcessRequest,然后调用到pipeline的openrequest,进而一步步调用,最终调用sched_req的cmd命令,
    ioctl调用到kmd中,kmd的crm中响应SCHED_REQ命令,调用cam_req_mgr_schedule_request做进一步处理。
    cam_req_mgr_schedule_request()做了什么?
    1)根据umd传入数据,填充task_data。task_data中u此时存放的sched_req数据。
    2)在cam_req_mgr_process_sched_req()中,取出sched_req数据,设置给当前link的in_q中的slot数组中,对应索引是wd_idx

3 request table介绍

  • 什么是req table,它的职责是?
    req tbl存在于link中,它是保存不同pipeline delay的link dev的req信息。判断当前link中pd值相同的dev的apply setting是否满足了。

request table定义

struct cam_req_mgr_req_tbl {
	int32_t                     id; //req tbl的id值
	int32_t                     pd; //当前req tbl对应哪个pipeline delay
	int32_t                     dev_count; //相同pd的设备有几个
	int32_t                     dev_mask; //
	int32_t                     skip_traverse;
	struct cam_req_mgr_req_tbl *next; //指向下一个pd的req tbl
	int32_t                     pd_delta; //两个req tbl他们的pd差值
	int32_t                     num_slots; //当前req tbl有多少个slot
	 //slot数组,存放当前req tbl中具体存放的slot。MAX_REQ_SLOTS=48
	struct cam_req_mgr_tbl_slot slot[MAX_REQ_SLOTS];
};

cam_req_mgr_tbl_slot 定义如下:

struct cam_req_mgr_tbl_slot {
	int32_t                                idx; //slot的索引
	uint32_t                               req_ready_map; //跟着当前pd值的req tbl中哪些设备req ready了
	enum crm_req_state                     state; //当前slot的状态
	uint32_t                               inject_delay_at_sof;
	uint32_t                               inject_delay_at_eof;
	struct  crm_tbl_slot_special_ops       ops;
};

link持有req_data, req_data中包含了in_q和req_tbl。

  • 图解req tbl
    2个req tbl会共用一个idx。
    在这里插入图片描述

4 in_q 和request table关系

in_q和req tbl会共享idx,通过idx建立联系。
在这里插入图片描述

5 add request

link 的device在add request后,dev会回调req通知crm。通过cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)回调的。
以IFENode为例,调用流程

IFENode::ExecuteProcessRequest() @camxifenode.cpp
	->CommitAndSubmitPacket();
		-> GetHwContext()->Submit(GetCSLSession(), m_hDevice, m_pIQPacket)
			->Submit() @camxhwcontext.cpp
				->CSLSubmit()@camxcsl.cpp
					-> CSLSubmitHW() @@camxcslhw.cpp
					->CSLHwInternalDefaultSubmit()@camxcslhwinternal.cpp
						->ioctlCmd.op_code         = CAM_CONFIG_DEV;
						->pDevice->deviceOp.Ioctl(pDevice, VIDIOC_CAM_CONTROL, &ioctlCmd)

上面是umd调用流程,下面走到kmd的CONFIG_DEV ioctl中。

cam_node_handle_ioctl() @cam_node.c
	->case CAM_CONFIG_DEV:
	->__cam_node_handle_config_dev()
		->cam_context_handle_config_dev(ctx, config) @cam_context.c //ctx是cam context
			->ctx->state_machine[ctx->state].ioctl_ops.config_dev(ctx, cmd)
				-> __cam_isp_ctx_config_dev_in_top_state() @cam_isp_context.c
					->ctx->ctx_crm_intf->add_req(&add_req);					

因为之前crm中配置过

static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
	.notify_trigger = cam_req_mgr_cb_notify_trigger,
	.notify_err     = cam_req_mgr_cb_notify_err,
	.add_req        = cam_req_mgr_cb_add_req,
	.notify_timer   = cam_req_mgr_cb_notify_timer,
	.notify_stop    = cam_req_mgr_cb_notify_stop,
};

所以ctx->ctx_crm_intf->add_req()会调用到cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)。
cam_req_mgr_cb_add_req()做了什么?
当link device中收到的req,会通知crm ,crm中link的对应pipeline delay的req tbl中保存了到达req的信息,
当某一帧的req tbl中slot state为ready,同时in_q中这一帧的req的slot state也为ready,表示这一帧的req已经准备好了,
可以根据crm控制策略下发apply setting。

思考问题:
上面的cam_req_mgr_cb_add_req()是link device调用的,对于非link device,会通知crm req到达吗?
答案是会的,具体看下BPSNode的调用流程,最后也会走到camxhwcontext的Submit(),后面的调用流程和上面link device的相同。
以BPSNode为例,看下调用流程:

BPSNode::ExecuteProcessRequest() @camxbpsnode.cpp
	->CommitAllCommandBuffers(pBPSCmdBuffer);
	->pIQPacket->CommitPacket();
	->pIQPacket->AddCmdBufferReference(pBPSCmdBuffer[BPSCmdBufferFrameProcess],...);
	->GetHwContext()->Submit(GetCSLSession(), m_hDevice, pIQPacket) //不同的Node,设置的packet不同,到kmd中做不同处理
		... //这里流程和上面一样

文章来源:https://blog.csdn.net/lz_1990/article/details/135422609
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。