private object dma fence

1 min

Aggregate Driver 实现结构体: struct component_master_ops { int (*bind)(struct device *master); void (*unbind)(struct device *master); }; 在 probe 函数中调用 component_match_add()来填充 component match list, 最后调用 component_master_add_with_match() register aggregate driver, remove 函数中调用 component_master_del() 来 unregister。 void component_match_add(struct device *parent, struct component_match **matchptr, int (*compare)(struct device*, void*), void *compare_data) int component_master_add_with_match(struct device *parent, const struct component_master_ops *ops, struct component_match *match) Components Driver 实现结构体: struct component_ops { int (*bind)(struct device *comp, struct device *master, void *master_data); void (*unbind)(struct device *comp, struct device *master, void *master_data); }; 在 probe 函数中调用 component_add() register component driver, remove 函数中调用 component_del() 来 ungister。...

1 min

概述 bus 模块的功能包括: bus 的注册和注销 本 bus 下有 device 或者 device_driver 注册到内核时的处理 本 bus 下有 device 或者 device_driver 从内核注销时的处理 device_drivers 的 probe 处理 管理 bus 下的所有 device 和 device_driver 数据结构 struct bus_type { const char *name; const char *dev_name; const struct attribute_group **bus_groups; const struct attribute_group **dev_groups; const struct attribute_group **drv_groups; int (*match)(struct device *dev, struct device_driver *drv); int (*uevent)(const struct device *dev, struct kobj_uevent_env *env); int (*probe)(struct device *dev); void (*sync_state)(struct device *dev); void (*remove)(struct device *dev); void (*shutdown)(struct device *dev); int (*online)(struct device *dev); int (*offline)(struct device *dev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); int (*num_vf)(struct device *dev); int (*dma_configure)(struct device *dev); void (*dma_cleanup)(struct device *dev); const struct dev_pm_ops *pm; bool need_parent_lock; }; name : bus 的名称....

2 min

struct device { struct kobject kobj; struct device *parent; struct device_private *p; const char *init_name; /* initial name of the device */ const struct device_type *type; const struct bus_type *bus; /* type of bus device is on */ struct device_driver *driver; /* which driver has allocated this device */ void *platform_data; /* Platform specific data, device core doesn't touch it */ void *driver_data; /* Driver data, set and get with dev_set_drvdata/dev_get_drvdata */ struct mutex mutex; /* mutex to synchronize calls to * its driver....

2 min

数据结构 Platform 设备是可以通过 CPU bus 直接寻址的设备, 内核在设备模型 bus, device 和 driver 的基础上, 进行了进一步封装, 抽象了 platform_bus, platform_device, platform_driver. platform 相关的实现在 include/linux/platform_device.h, drivers/base/platform.c中. struct platform_device { const char *name; int id; bool id_auto; struct device dev; u64 platform_dma_mask; struct device_dma_parameters dma_parms; u32 num_resources; struct resource *resource; const struct platform_device_id *id_entry; }; name: platform device 的名称. dev: 指向底层的 device. id: 可以手动设置, 也可设置为宏 PLATFORM_DEVID_NONE 表示没有 id, pdev->dev->name 直接设置为 pdev->name. 设置为宏 PLATFORM_DEVID_AUTO 表示自动生成 id. id_auto: 当 id 设置为 PLATFORM_DEVID_AUTO, id_auto 被置为 true, 在注册 platform_device 时可以自动生成 id....

2 min

概述 include/linux/kobject.h lib/kobject.c Kobject 是基本数据类型,每个 Kobject 都会在"/sys/“文件系统中以目录的形式出现。 Ktype 代表 Kobject 的属性操作集合 (由于通用性,多个 Kobject 可能共用同一个属性操作集,因此把 Ktype 独立出来了). Kset 是一个特殊的 Kobject(因此它也会在"/sys/“文件系统中以目录的形式出现),它用来集合相似的 Kobject(这些 Kobject 可以是相同属性的,也可以不同属性的)。 数据结构 kobject: struct kobject { const char *name; struct list_head entry; struct kobject *parent; struct kset *kset; const struct kobj_type *ktype; struct kernfs_node *sd; /* sysfs directory entry */ struct kref kref; unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; unsigned int state_remove_uevent_sent:1; unsigned int uevent_suppress:1; }; name: kobject 的名称, 也是在 sysfs 中的目录名....

2 min

双向循环链表 list.h, 列出了一些 driver 常用的 list operations: #define LIST_HEAD_INIT(name) #define LIST_HEAD(name) void INIT_LIST_HEAD(struct list_head *list) void list_add(struct list_head *new, struct list_head *head) // 在 head 之后插入 list node void list_add_tail(struct list_head *new, struct list_head *head) // 在 head 之前插入 list node void list_del(struct list_head *entry) // 删除当前 list node void list_del_init(struct list_head *entry); void list_move(struct list_head *list, struct list_head *head); void list_move_tail(struct list_head *list, struct list_head *head); int list_is_first(const struct list_head *list, const struct list_head *head) int list_is_last(const struct list_head *list, const struct list_head *head) int list_empty(const struct list_head *head) int list_is_singular(const struct list_head *head) void list_splice(const struct list_head *list, struct list_head *head) void list_splice_tail(struct list_head *list, struct list_head *head) void list_splice_init(struct list_head *list, struct list_head *head) void list_splice_tail_init(struct list_head *list, struct list_head *head) #define list_entry(ptr, type, member) #define list_first_entry(ptr, type, member) #define list_last_entry(ptr, type, member) #define list_first_entry_or_null(ptr, type, member) #define list_next_entry(pos, member) #define list_prev_entry(pos, member) #define list_for_each(pos, head) #define list_for_each_safe(pos, n, head) // 如果在遍历的时候会删除当前节点,那么需要使用 xxx_safe, 如果只是读 list 可以使用 list_for_each #define list_for_each_entry(pos, head, member) #define list_for_each_entry_reverse(pos, head, member) #define list_for_each_entry_continue(pos, head, member) #define list_for_each_entry_continue_reverse(pos, head, member) #define list_for_each_entry_from(pos, head, member) #define list_for_each_entry_safe(pos, n, head, member) #define list_for_each_entry_safe_reverse(pos, n, head, member)

1 min

kernel boot 过程,设备树初始化 reserved-memory 节点: early_init_fdt_scan_reserved_mem() fdt_scan_reserved_mem(); fdt_init_reserved_mem(); static int __init fdt_scan_reserved_mem(void) { int node, child; const void *fdt = initial_boot_params; node = fdt_path_offset(fdt, "/reserved-memory"); fdt_for_each_subnode(child, fdt, node) { const char *uname; int err; if (!of_fdt_device_is_available(fdt, child)) continue; uname = fdt_get_name(fdt, child, NULL); /// 存在 reg 属性的情况 err = __reserved_mem_reserve_reg(child, uname); /// 不存在 reg 属性的情况,存在 size 属性 if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) fdt_reserved_mem_save_node(child, uname, 0, 0); } return 0; } /// 先预留 rmem 的 base 和 size 都为 0 void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size) { struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; rmem->fdt_node = node; rmem->name = uname; rmem->base = base; rmem->size = size; reserved_mem_count++; return; } void __init fdt_init_reserved_mem(void) { int i; for (i = 0; i < reserved_mem_count; i++) { struct reserved_mem *rmem = &reserved_mem[i]; unsigned long node = rmem->fdt_node; int len; const __be32 *prop; int err = 0; bool nomap; nomap = of_get_flat_dt_prop(node, "no-map", NULL) !...

3 min

Data Structure struct software_node { const char *name; const struct software_node *parent; const struct property_entry *properties; }; struct swnode { struct kobject kobj; struct fwnode_handle fwnode; const struct software_node *node; int id; /* hierarchy */ struct ida child_ids; struct list_head entry; struct list_head children; struct swnode *parent; unsigned int allocated:1; unsigned int managed:1; }; Provider software_node_register()注册单个 software node, software_node_register_node_group()注册一组 software nodes. 都是将 software nodes 挂入一个全局链表. // 定义属性 static const struct property_entry my_device_properties[] = { PROPERTY_ENTRY_U32("reg", 0), PROPERTY_ENTRY_U32("my_property", 1234), { } }; // 定义 software node static const struct software_node my_device_node = { ....

2 min

Note > vendor driver 常用 api * v4l2, media controller framework 内部使用api ~ vendor driver 不常用 api Media Controller API media-device.h struct media_device_ops { int (*link_notify)(struct media_link*link, u32 flags, unsigned int notification); struct media_request *(*req_alloc)(struct media_device *mdev); void (*req_free)(struct media_request *req); int (*req_validate)(struct media_request *req); void (*req_queue)(struct media_request *req); }; > media_device_init(); > media_device_cleanup(); > media_device_register(); > media_device_unregister(); * media_device_register_entity(); * media_device_unregister_entity(); ~ media_device_register_entity_notify(); ~ media_device_unregister_entity_notify(); * media_device_for_each_entity() * media_device_for_each_intf() * media_device_for_each_pad() * media_device_for_each_link() link_notify: 在 userspace 调用 ioctl media_device_setup_link() 后会触发 link_notify 回调。...

5 min