【问题标题】:Linux: how to determine the DMA address corresponding to what's returned from ioremapLinux:如何确定与 ioremap 返回的内容对应的 DMA 地址
【发布时间】:2015-04-20 06:27:15
【问题描述】:

假设我有一些物理地址(这是我的 DMA 源外设的总线位置):

phys_addr = 0xffff0000;

我愿意:

virt_addr = ioremap(phys_addr, PAGE_SIZE);

在这样做之后,我不再可以直接访问phys_addr(在我的情况下,我没有访问权限,因为我正在编写的驱动程序只通过了virt_addr)。

我的第一次失败尝试:

wrong_phys_addr = virt_to_dma(dev,virt_addr);

顺便说一句,我不知道为什么设备 dev 在此查找中是相关的...

这当然不起作用,因为virt_addr 不是直接映射的内核内存。 DMA-API 似乎暗示所有类似virt_to_bus 的翻译都已弃用,每个人都应该使用dma_map_single 等来获取DMA 总线地址。所以我接下来尝试了这个:

wrong_phys_addr = dma_map_single(dev, virt_addr, size, DMA_FROM_DEVICE);

这仍然不起作用。当然,如果我直接使用0xffff0000 作为device_prep_dma_memcpy 的源DMA 地址,一切都会很好——但我不能这样做,因为我没有直接访问它的权限。我能想到的唯一可能的方法是遍历内核的页表......我真的不想手动执行此操作。有没有更好的办法?

更新

struct page *kmap_to_page(void * vaddr)

看起来很有希望。我不确定从 ioremap 返回的虚拟地址是否适用于此。另一种可能是

struct page* vmalloc_to_page(void* vmalloc_addr)

我需要进一步调查。

【问题讨论】:

  • 物理地址不一定与 DMA 地址相同。无论如何,dma_map_single() 应该可以工作。为什么驱动程序无法访问其设备的资源?

标签: c linux memory-management linux-kernel dma


【解决方案1】:

看起来vmalloc_to_page 就是我要找的东西。如果我这样做:

phys_addr = page_to_phys(vmalloc_to_page(virt_addr)))

这会产生phys_addr == 0xffff0000

按照 CL. 的建议,我还尝试了以下所有操作:

wrong_phy_addr1 = dma_map_single(dev, 0xffff0000, size, DMA_FROM_DEVICE);
wrong_phy_addr2 = dma_map_single(dev, virt_addr, size, DMA_FROM_DEVICE);
correct_phy_addr = phys_to_dma(dev, 0xffff0000);

运行后我得到:

wrong_phy_addr1 == 7fff0000
wrong_phy_addr2 == 4091e000
correct_phy_addr == ffff0000

因此,看起来phys_to_dma() 在这里胜出。使用这种方法比使用原始物理地址更可取,因为(正如 CL. 建议的那样),物理地址不一定是 DMA 地址——在我的板上它们恰好是相同的。

总之,这是我最初问题的答案:

dma_addr = phys_to_dma(dev, page_to_phys(vmalloc_to_page(virt_addr));

话虽如此,这种额外的查找成本很高,如果我的驱动程序可以使用 phys_addr (0xffff0000),则可以避免这种额外的查找——我会考虑更改接口。

在接受我自己的答案之前,我会给其他人一些时间来提供他们自己的(更好的?)答案。

【讨论】:

  • 我想知道为什么 dma_map_single(dev, virt_addr, size, DMA_FROM_DEVICE) 不起作用。 ,也许应该是 DMA_TO_DEVICE ?
猜你喜欢
  • 1970-01-01
  • 2021-07-17
  • 2015-04-09
  • 1970-01-01
  • 2010-12-14
  • 2015-04-03
  • 2013-06-23
  • 1970-01-01
  • 2020-11-18
相关资源
最近更新 更多