Linux kernel 如何获取V4L2 DMA虚拟地址的物理地址?

Linux kernel 如何获取V4L2 DMA虚拟地址的物理地址?,linux-kernel,linux-device-driver,v4l2,Linux Kernel,Linux Device Driver,V4l2,我有一个典型的V4L2驱动程序,用于配置内存映射IO方法。此驱动程序将虚拟地址传递给我的用户空间应用程序。所有这些都很好 我有另一个驱动程序,它期望输入一个内核物理地址。我想将V4L2驱动程序的输出连接到此驱动程序的输入,但它需要一个物理地址此驱动程序控制FPGA功能 我的理解是内核例程:virt_-to_-phys例程不能与DMA分配的内存映射地址一起工作。这是真的吗?如果是这样,如何从传递到用户空间的DMA内存映射的V4L2虚拟地址中获取物理地址 我只是在这里做一个概念验证,所以硬编码一些地

我有一个典型的V4L2驱动程序,用于配置内存映射IO方法。此驱动程序将虚拟地址传递给我的用户空间应用程序。所有这些都很好

我有另一个驱动程序,它期望输入一个内核物理地址。我想将V4L2驱动程序的输出连接到此驱动程序的输入,但它需要一个物理地址此驱动程序控制FPGA功能

我的理解是内核例程:virt_-to_-phys例程不能与DMA分配的内存映射地址一起工作。这是真的吗?如果是这样,如何从传递到用户空间的DMA内存映射的V4L2虚拟地址中获取物理地址

我只是在这里做一个概念验证,所以硬编码一些地址不是问题。这是在专用嵌入式平台上运行的唯一应用程序

谢谢,
-Andres

这可以通过三个步骤来解释:

V4L2应用程序将调用VIDIOC_REQBUF来分配缓冲区。如果内存类型为VB2_memory_MMAP。V4l2框架驱动程序将分配缓冲区并将其打包为vb2_dc_buf结构类型,并将此结构指针存储在平面[plane].mem_priv中。此结构将具有DMA物理地址

应用程序必须通过传递平面[plane].mem_priv来调用VIDIOC_EXPBUF。然后v4l2框架实现vb2_core_EXPBUF,在其中调用特定于DMA的API,如vb2_dc_get_dmabuf和DMA_buf_fd,以获取DMA缓冲区fd

应用程序可以将这个pass这个fd导出到第二个驱动程序,第二个驱动程序将导入fd并使用dmaapi转换回DMA物理地址


V4L2驱动程序正在为用户空间创建虚拟地址。这意味着该驱动程序已经有一个物理地址,您必须知道该物理地址才能设置此映射。在创建虚拟地址映射之前,查看驱动程序源并查看它是如何获取地址的。我猜它可能来自一个PCI设备的条形寄存器,lspci会显示给你。从技术上讲,您还可以追踪分配给用户进程映射的页表条目,并读回存储在那里的地址,但这将是更难获得它的方法。