virtio_gpu_get_caps_ioctl 这个函数是 virtio GPU 驱动中的一个 ioctl 处理函数,用于获取 GPU 设备的能力集(capabilities)信息。下面是详细的功能分析。
1. 主要功能
该函数允许用户空间程序查询和获取 virtio GPU 设备支持的特定能力集数据,这些能力集描述了 GPU 的功能特性和支持的操作。
2. 输入参数
通过 struct drm_virtgpu_get_caps *args 接收用户空间的请求:
3. 执行流程
3.1 基础验证
if (vgdev->num_capsets == 0)
return -ENOSYS; // 设备不支持任何能力集
if (args->size == 0)
return -EINVAL; // 缓冲区大小不能为0
3.2 查找匹配的能力集
for (i = 0; i < vgdev->num_capsets; i++) {
if (vgdev->capsets[i].id == args->cap_set_id) {
if (vgdev->capsets[i].max_version >= args->cap_set_ver) {
found_valid = i;
break;
}
}
}
- 遍历设备支持的所有能力集
- 查找 ID 匹配且版本兼容的能力集
3.3 检查缓存:
list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
if (cache_ent->id == args->cap_set_id &&
cache_ent->version == args->cap_set_ver) {
// 在缓存中找到,直接跳转到复制阶段
goto copy_exit;
}
}
- 首先检查驱动的能力集缓存
- 如果已缓存则直接使用,避免重复查询硬件
3.4 硬件查询(如果缓存未命中):
ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,
&cache_ent);
if (ret)
return ret;
virtio_gpu_notify(vgdev);
- 向 virtio GPU 设备发送命令获取能力集
- 通知设备处理命令
3.5 等待响应
ret = wait_event_timeout(vgdev->resp_wq,
atomic_read(&cache_ent->is_valid), 5 * HZ);
if (!ret)
return -EBUSY; // 超时
- 等待设备响应(最多5秒)
- 使用原子操作确保数据有效性
3.6 数据复制
size = min(args->size, host_caps_size);
ptr = cache_ent->caps_cache;
if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size))
return -EFAULT;
- 计算实际复制大小(用户缓冲区和实际数据的最小值)
- 将能力集数据复制到用户空间
4. 关键数据结构
-
virtio_gpu_drv_capset:描述设备支持的能力集
-
id:能力集唯一标识
-
max_version:支持的最大版本 -
max_size:能力集数据最大大小
-
-
virtio_gpu_drv_cap_cache:能力集缓存项
-
caps_cache:缓存的能力集数据 -
is_valid:数据有效性标志 -
head:链表节点
-
5. 错误处理
-
-ENOSYS:设备不支持能力集功能 -
-EINVAL:无效参数或找不到匹配的能力集 -
-EBUSY:硬件查询超时 -
-EFAULT:数据复制到用户空间失败
6. 使用场景
这个函数通常被 OpenGL、Vulkan 或其他图形 API 的用户空间驱动使用,用于:
-
查询 GPU 支持的 OpenGL/Vulkan 扩展
-
获取渲染器特定的能力信息
-
确定可用的 3D 图形功能集
通过这种机制,用户空间程序可以动态发现和适配不同的 virtio GPU 实现的能力。
2251

被折叠的 条评论
为什么被折叠?



