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中有多少个deviceenum cam_pipeline_delay max_delay;...struct cam_req_mgr_core_workq *workq;//自定义的workqueue,处理工作队列中workint32_t pd_mask;struct cam_req_mgr_connected_device *l_dev;//存放link中devicestruct cam_req_mgr_req_data req; //req_datastruct 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 queuestruct cam_req_mgr_req_tbl *l_tbl;//保存request tableint32_t num_tbl;//保存req table的个数struct cam_req_mgr_apply apply_data[CAM_PIPELINE_DELAY_MAX];//保存apply data,就是req是settingstruct 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=48int32_t rd_idx;//读索引下标。每当收到SOF或EOF,要对req处理时,从rd_idx读取reqint32_t wr_idx;//写索引下标。每当有req从umd通过sche req下发时,就会写入到wr_idx中int32_t last_applied_idx;//最新位置的读索引下标
};
- in_q 图示
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 delayint32_t dev_count; //相同pd的设备有几个int32_t dev_mask; //int32_t skip_traverse;struct cam_req_mgr_req_tbl *next; //指向下一个pd的req tblint32_t pd_delta; //两个req tbl他们的pd差值int32_t num_slots; //当前req tbl有多少个slot//slot数组,存放当前req tbl中具体存放的slot。MAX_REQ_SLOTS=48struct 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中做不同处理... //这里流程和上面一样