1 架构目的
基于4.1.15内核,kernel中的component框架是为了subsystem能够按照一定的顺序初始化设备而提出的架构。subsystem中由较多设备模块组成,而内核加载每个模块时间不定。因此需要component框架来保证需最后初始化的设备加载前,所需设备全部加载完毕。
2 架构简介
在component中,包含两个基本概念,master和component。master是设备树中的“超级设备(superdevice)”,负责管理该超级设备下的普通设备,用于挂在全局链表masters上。component是由master管理的普通设备,所有的component都会挂在全局链表component_list链表上。看下两个结构体的定义:
struct master {
struct list_head node; // 用于添加自身到masters链表中
bool bound; // 当所有component都执行完毕以后置true
const struct component_master_ops *ops;
struct device *dev;
struct component_match *match; // 旗下必需的component列表
struct dentry *dentry;
};
struct component {
struct list_head node;
struct master *master; // 决定挂在哪个master下
bool bound;
const struct component_ops *ops;
int subcomponent;
struct device *dev;
};
Component架构大致如下:
1.3 文件路径
/driver/base/component.c文件包含了主要逻辑。
1.4 qcom driver初始化
kmd主要由三个模块组成,分别是crm,cam sync以及子模块,umd层是控制kmd运转的大致框图如下。在provider初始化的时候会open video0,遍历所有的子设备节点,将所有子设备信息都放到CSL中,为之后的数据流转做好准备:
crm是qcom driver的核心,其注册为platform_driver后,会调用相应的probe方法:
static int cam_req_mgr_probe(struct platform_device *pdev) {
int rc = 0;
struct component_match *match_list = NULL;
struct device *dev = &pdev->dev;
rc = camera_component_match_add_drivers(dev, &match_list);
if (rc) {
CAM_ERR(CAM_CRM,
"Unable to match components, probe failed rc: %d",
rc);
goto end;
}
/* Supply match_list to master for handing over control */
rc = component_master_add_with_match(dev,
&cam_req_mgr_component_master_ops, match_list);
if (rc) {
CAM_ERR(CAM_CRM,
"Unable to add master, probe failed rc: %d",
rc);
goto end;
}
end:
return rc;
}
这里会调用camera_component_match_add_drivers方法将crm需要的子设备信息都收集到一个match_list结构体中:
int camera_component_match_add_drivers(struct device *master_dev,
struct component_match **match_list) {
int i, rc = 0;
struct platform_device *pdev = NULL;
struct device *start_dev = NULL, *match_dev = NULL;
if (!master_dev || !match_list) {
CAM_ERR(CAM_UTIL, "Invalid parameters for component match add");
rc = -EINVAL;
goto end;
}
for (i = 0; i < ARRAY_SIZE(cam_component_drivers); i++) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
struct device_driver const *drv =
&cam_component_drivers[i]->driver;
const void *drv_ptr = (const void *)drv;
#else
struct device_driver *drv = &cam_component_drivers[i]->driver;
void *drv_ptr = (void *)drv;
#endif
start_dev = NULL;
while ((match_dev = bus_find_device(&platform_bus_type,
start_dev, drv_ptr, &camera_platform_compare_dev))) {
put_device(start_dev);
// 相当于是类型转换
pdev = to_platform_device(match_dev);
CAM_DBG(CAM_UTIL, "Adding matched component:%s", pdev->name);
component_match_add(master_dev, match_list,
camera_component_compare_dev, match_dev);
start_dev = matc