DRM系列四:初始化drm设备--drm_dev_init

本系列文章基于linux 5.15

一、drm_dev_alloc

用于分配并初始化一个新的 DRM 设备(即drm_device),初始化主要调用drm_dev_init函数

1.1drm_dev_init

drm_device的初始化操作,但是并不会注册,函数定义在drivers/gpu/drm/drm_drv.c
其主要的作用:

  • 对应成员变量的简单初始化
  • 检测 drm_driver 的 driver_features 标志位是否设置 DRIVER_RENDER , 有则创建对应的设备
    dev/dri/enderD(128 - 192)
  • 创建一个 DRM_MINOR_PRIMARY 子设备, 每个 drm_device 必须有一个默认的 DRM_MINOR_PRIMARY 设备dev/dri/card(0 - 64)
  • 检测drm_device的 drm_driver 的 driver_features 标志位是否设置 DRIVER_GEM ,如果设置了则会为我们分配并创建一个默认的起始偏移地址为 DRM_FILE_PAGE_OFFSET_START内存大小为 DRM_FILE_PAGE_OFFSET_SIZE的 vma_offset_manager
  • 将父设备名称用作 DRM 设备的唯一标识符 unique(drm_device的成员变量),没有父设备则使用驱动程序名称作为 unique唯一标识符.
static int drm_dev_init(struct drm_device *dev,const struct drm_driver *driver,struct device *parent)
{int ret;if (!drm_core_init_complete) {DRM_ERROR("DRM core is not initialized\n");return -ENODEV;}if (WARN_ON(!parent))return -EINVAL;kref_init(&dev->ref);dev->dev = get_device(parent);dev->driver = driver;INIT_LIST_HEAD(&dev->managed.resources);spin_lock_init(&dev->managed.lock);/* no per-device feature limits by default */dev->driver_features = ~0u;drm_legacy_init_members(dev);INIT_LIST_HEAD(&dev->filelist);INIT_LIST_HEAD(&dev->filelist_internal);INIT_LIST_HEAD(&dev->clientlist);INIT_LIST_HEAD(&dev->vblank_event_list);spin_lock_init(&dev->event_lock);mutex_init(&dev->struct_mutex);mutex_init(&dev->filelist_mutex);mutex_init(&dev->clientlist_mutex);mutex_init(&dev->master_mutex);ret = drmm_add_action(dev, drm_dev_init_release, NULL);if (ret)return ret;dev->anon_inode = drm_fs_inode_new();if (IS_ERR(dev->anon_inode)) {ret = PTR_ERR(dev->anon_inode);DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);goto err;}/*检测 drm_driver 的 driver_features 标志位是否设置 DRIVER_RENDER , 有则创建对应的设备dev/dri/enderD(128 - 192)*/if (drm_core_check_feature(dev, DRIVER_RENDER)) {ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);if (ret)goto err;}/*创建一个 DRM_MINOR_PRIMARY 子设备, 每个 drm_device 必须有一个默认的 DRM_MINOR_PRIMARY 设备dev/dri/card(0 - 64)*/ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);if (ret)goto err;ret = drm_legacy_create_map_hash(dev);if (ret)goto err;drm_legacy_ctxbitmap_init(dev);
/*检测drm_device的 drm_driver 的 driver_features 标志位是否设置 DRIVER_GEM ,
如果设置了则会为我们分配并创建一个默认的起始偏移地址为 DRM_FILE_PAGE_OFFSET_START内存大小为 DRM_FILE_PAGE_OFFSET_SIZE的 vma_offset_manager*/if (drm_core_check_feature(dev, DRIVER_GEM)) {ret = drm_gem_init(dev);if (ret) {DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");goto err;}}ret = drm_dev_set_unique(dev, dev_name(parent));if (ret)goto err;return 0;err:drm_managed_release(dev);return ret;
}

1.1.1drm_minor_alloc

根据传入的 type 在 drm_minors_idr 链表中申请一个可用的 id, 并且使用这个 id 作为次设备号, 创建对应的 minor 设备.

  • DRM_MINOR_PRIMARY id 范围 0 - 64 ==> dev/dri/card0 - dev/dri/card64
  • DRM_MINOR_RENDER id 范围 128 - 192 ==> dev/dri/enderD128 - dev/dri/enderD192
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
{struct drm_minor *minor;unsigned long flags;int r;minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL);if (!minor)return -ENOMEM;minor->type = type;minor->dev = dev;idr_preload(GFP_KERNEL);spin_lock_irqsave(&drm_minor_lock, flags);r = idr_alloc(&drm_minors_idr,NULL,64 * type,64 * (type + 1),GFP_NOWAIT);spin_unlock_irqrestore(&drm_minor_lock, flags);idr_preload_end();if (r < 0)return r;minor->index = r;r = drmm_add_action_or_reset(dev, drm_minor_alloc_release, minor);if (r)return r;minor->kdev = drm_sysfs_minor_alloc(minor);if (IS_ERR(minor->kdev))return PTR_ERR(minor->kdev);*drm_minor_get_slot(dev, type) = minor;return 0;
}
1.1.1.1drm_sysfs_minor_alloc

用于为 DRM minor 分配并初始化一个 struct device,其作用如下:

struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
{const char *minor_str;struct device *kdev;int r;
/*根据 minor->type 的值,选择对应的设备名称格式字符串: a.如果是渲染节点(DRM_MINOR_RENDER),则使用b. "renderD%d"。 如果是普通节点(DRM_MINOR_PRIMARY),则使用 "card%d"。*/if (minor->type == DRM_MINOR_RENDER)minor_str = "renderD%d";elseminor_str = "card%d";kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);if (!kdev)return ERR_PTR(-ENOMEM);/*设置设备属性*/device_initialize(kdev);/*通过 MKDEV 宏将主设备号 DRM_MAJOR 和次设备号 minor->index 组合成设备号*/kdev->devt = MKDEV(DRM_MAJOR, minor->index);kdev->class = drm_class;kdev->type = &drm_sysfs_device_minor;kdev->parent = minor->dev->dev;kdev->release = drm_sysfs_release;dev_set_drvdata(kdev, minor);/*使用 dev_set_name 设置设备名称,格式为 "renderD%d" 或 "card%d",其中 %d 是 minor->index。*/r = dev_set_name(kdev, minor_str, minor->index);if (r < 0)goto err_free;return kdev;err_free:put_device(kdev);return ERR_PTR(r);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/69870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解析与使用 Apache HttpClient 进行网络请求和数据抓取

目录 1. 什么是 HttpClient&#xff1f; 2. 基本使用 3. 使用 HttpClient 爬取腾讯天气的数据 4. 爬取拉勾招聘网站的职位信息 5. 总结 前言 Apache HttpClient 是 Apache 提供的一个用于处理 HTTP 请求和响应的工具类库。它提供了一种便捷、功能强大的方式来发送 HTTP 请…

扣子平台音频功能:让声音也能“智能”起来。扣子免费系列教程(14)

在数字化时代&#xff0c;音频内容的重要性不言而喻。无论是在线课程、有声读物&#xff0c;还是各种多媒体应用&#xff0c;音频都是传递信息、增强体验的关键元素。扣子平台的音频功能&#xff0c;为开发者和内容创作者提供了一个强大而灵活的工具&#xff0c;让音频的使用和…

【自开发工具介绍】SQLSERVER的ImpDp和ExpDp工具01

1、开发背景 大家都很熟悉&#xff0c;Oracle提供了Impdp和ExpDp工具&#xff0c;功能很强大&#xff0c;可以进行db的导入导出的处理。但是对于Sqlserver数据库只是提供了简单的图形化的导出导入工具&#xff0c;在实际的开发和生产环境不太可能让用户在图形化的界面选择移行…

上手DeepSeek大模型:本地化安装部署,确保数据不泄露

摘要&#xff1a;过年前DeepSeek横空出世&#xff0c;在世界范围内掀起AI狂潮&#xff0c;成了大家茶余饭后的话题。对于普通人怎样使用这个大模型呢&#xff1f;这篇文章来上手实践。 使用DeepSeek最简单的办法就是使用在线版或者手机版。 - 1 - 使用在线版 在浏览器中输…

蓝桥杯刷题DAY1:前缀和

所谓刷题&#xff0c;讲究的就是细心 帕鲁服务器崩坏【算法赛】 “那个帕鲁我已经观察你很久了&#xff0c;我对你是有些失望的&#xff0c;进了这个营地&#xff0c;不是把事情做好就可以的&#xff0c;你需要有体系化思考的能力。” 《幻兽帕鲁》火遍全网&#xff0c;成为…

【React】PureComponent 和 Component 的区别

前言 在 React 中&#xff0c;PureComponent 和 Component 都是用于创建组件的基类&#xff0c;但它们有一个主要的区别&#xff1a;PureComponent 会给类组件默认加一个shouldComponentUpdate周期函数。在此周期函数中&#xff0c;它对props 和 state (新老的属性/状态)会做一…

ZZNUOJ(C/C++)基础练习1021——1030(详解版)

目录 1021 : 三数求大值 C语言版 C版 代码逻辑解释 1022 : 三整数排序 C语言版 C版 代码逻辑解释 补充 &#xff08;C语言版&#xff0c;三目运算&#xff09;C类似 代码逻辑解释 1023 : 大小写转换 C语言版 C版 1024 : 计算字母序号 C语言版 C版 代码逻辑总结…

此虚拟机的处理器所支持的功能不同于保存虚拟机状态的虚拟机的处理器所支持的功能

1.问题&#xff1a;今天记录下自己曾经遇到的一个问题&#xff0c;就是复制别人虚拟机时弹出来的一个报错&#xff1a; 如图&#xff0c;根本原因就在于虚拟机版本的问题&#xff0c;无法对应的上&#xff0c;所以必须升级虚拟机。 2.问题解决&#xff1a; 1.直接点击放弃,此时…

高温环境对电机性能的影响与LabVIEW应用

电机在高温环境下的性能可能受到多种因素的影响&#xff0c;尤其是对于持续工作和高负荷条件下的电机。高温会影响电机的效率、寿命以及可靠性&#xff0c;导致设备出现过热、绝缘损坏等问题。因此&#xff0c;在设计电机控制系统时&#xff0c;特别是在高温环境下&#xff0c;…

C++ Primer 处理类型

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操 Janus-Pro-7B介绍 Janus-Pro-7B 是由 DeepSeek 开发的多模态 AI 模型&#xff0c;它在理解和生成方面取得了显著的进步。这意味着它不仅可以处理文本&#xff0c;还可以处理图像等其他模态的信息。 模型主要特点:Permalink…

使用LLaMA-Factory对AI进行认知的微调

使用LLaMA-Factory对AI进行认知的微调 引言1. 安装LLaMA-Factory1.1. 克隆仓库1.2. 创建虚拟环境1.3. 安装LLaMA-Factory1.4. 验证 2. 准备数据2.1. 创建数据集2.2. 更新数据集信息 3. 启动LLaMA-Factory4. 进行微调4.1. 设置模型4.2. 预览数据集4.3. 设置学习率等参数4.4. 预览…

three.js+WebGL踩坑经验合集(6.2):负缩放,负定矩阵和行列式的关系(3D版本)

本篇将紧接上篇的2D版本对3D版的负缩放矩阵进行解读。 (6.1):负缩放&#xff0c;负定矩阵和行列式的关系&#xff08;2D版本&#xff09; 既然three.js对3D版的负缩放也使用行列式进行判断&#xff0c;那么&#xff0c;2D版的结论用到3D上其实是没毛病的&#xff0c;THREE.Li…

软件工程经济学-日常作业+大作业

目录 一、作业1 作业内容 解答 二、作业2 作业内容 解答 三、作业3 作业内容 解答 四、大作业 作业内容 解答 1.建立层次结构模型 (1)目标层 (2)准则层 (3)方案层 2.构造判断矩阵 (1)准则层判断矩阵 (2)方案层判断矩阵 3.层次单排序及其一致性检验 代码 …

小程序的协同工作与发布

1.小程序API的三大分类 2.小程序管理的概念&#xff0c;以及成员管理两个方面 3.开发者权限说明以及如何维护项目成员 4.小程序版本

架构技能(六):软件设计(下)

我们知道&#xff0c;软件设计包括软件的整体架构设计和模块的详细设计。 在上一篇文章&#xff08;见 《架构技能&#xff08;五&#xff09;&#xff1a;软件设计&#xff08;上&#xff09;》&#xff09;谈了软件的整体架构设计&#xff0c;今天聊一下模块的详细设计。 模…

基于微信小程序的实习记录系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

B-树:解锁大数据存储和与快速存储的密码

在我们学习数据结构的过程中&#xff0c;我们会学习到二叉搜索树、二叉平衡树、红黑树。 这些无一例外&#xff0c;是以一个二叉树展开的&#xff0c;那么对于我们寻找其中存在树中的数据&#xff0c;这个也是一个不错的方法。 但是&#xff0c;如若是遇到了非常大的数据容量…

【视频+图文详解】HTML基础4-html标签的基本使用

图文教程 html标签的基本使用 无序列表 作用&#xff1a;定义一个没有顺序的列表结构 由两个标签组成&#xff1a;<ul>以及<li>&#xff08;两个标签都属于容器级标签&#xff0c;其中ul只能嵌套li标签&#xff0c;但li标签能嵌套任何标签&#xff0c;甚至ul标…

网络工程师 (8)存储管理

一、页式存储基本原理 &#xff08;一&#xff09;内存划分 页式存储首先将内存物理空间划分成大小相等的存储块&#xff0c;这些块通常被称为“页帧”或“物理页”。每个页帧的大小是固定的&#xff0c;例如常见的页帧大小有4KB、8KB等&#xff0c;这个大小由操作系统决定。同…