gpt4 book ai didi

linux-kernel - kmalloc 中的缓冲区也是 DMA 安全缓冲区吗?

转载 作者:行者123 更新时间:2023-12-04 05:24:58 40 4
gpt4 key购买 nike

我正在为 SPI 连接的 LCD 编写帧缓冲驱动程序。我使用 kmalloc 来分配缓冲区,它非常大 - 150KB。鉴于 kmalloc 分配缓冲区的方式,ksize 报告正在使用更多内存 - 256KB 左右。

SPI spi_transfer 结构采用指向 tx 和 rx 缓冲区的指针,这两个缓冲区都必须是 DMA 安全的。因为我希望 tx 缓冲区大约为 16KB,所以我可以在 kmalloced 视频缓冲区内分配该缓冲区并且仍然是 DMA 安全的吗?

这可能被认为是过早的优化,但是视频缓冲区中有太多的空闲空间,不使用它感觉很糟糕!本质上,分配的内存在以下方面没有区别:

kmalloc(videosize)


kmalloc(PAGE_ALIGN(videosize) + txbufsize)

因此可以将返回的 kptr 带回并执行以下操作:
txbuf = (u8 *)kptr + PAGE_ALIGN(videosize);

我知道“DMA 安全”的部分要求是适当的对齐 - 我相信与 CPU 缓存行大小的对齐... - 但是页面对齐不应该是这样吗?

顺便说一句,我不确定 tx 和 rx 是否可以指向同一个地方。 spi.h header 也不清楚(实际上明确不清楚)。鉴于 rx 缓冲区永远不会超过几个字节,试图找出来制造麻烦是愚蠢的!

最佳答案

答案似乎是肯定的,但附带条件。 (特别是“它比那更复杂”)

如果您通过 __get_free_page*() 或通用内存分配器 (kmalloc) 获取内存,那么您可以使用从这些例程返回的地址向/从该内存进行 DMA。潜在的含义是,kmalloc 中的页面对齐缓冲区,即使跨越多个页面,也将是 DMA 安全的,因为底层物理内存保证是连续的,并且页面对齐缓冲区保证在缓存线边界上。

一个附带条件是设备是否能够驱动整个总线宽度(例如:ISA)。因此,内存的物理地址必须在设备的 dma_mask 内。

另一个是缓存一致性要求。这些以缓存线宽度的粒度运行。为了防止两个单独的内存区域共享一个缓存线,dma 的内存必须恰好在缓存线边界上开始,并恰好在一个边界上结束。鉴于这可能未知,建议(DMA API 文档)仅映射在页面边界开始和结束的虚拟区域(因为这些也保证是如上所述的缓存线边界)。

在这种情况下,DMA 驱动程序可以使用 dma_alloc_coherent() 来分配可 DMA 的空间,以保证 DMA 区域不可缓存。由于这可能很昂贵,因此还存在一种流方法 - 对于单向通信 - 其中一致性仅限于写入时的缓存刷新。在先前分配的缓冲区上使用 dma_map_single()。

就我而言,在没有 dma_map_single 的情况下将 tx 和 rx 缓冲区传递给 spi_sync 很好 - spi 例程将为我完成。我可以自己使用 dma_map_single 以及 unmap 或 dma_sync_single_for_cpu() 来保持所有内容同步。不过我现在不会打扰 - 在驱动程序工作后调整性能是一个更好的策略。

也可以看看:

  • Does every dma_map_single call require a corresponding dma_unmap_single?
  • Linux kernel device driver to DMA into kernel space
  • 关于linux-kernel - kmalloc 中的缓冲区也是 DMA 安全缓冲区吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22001074/

    40 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com