2014-02-24 211 views
4

我正在为SPI连接的LCD写帧缓冲驱动程序。我使用kmalloc分配缓冲区,这是相当大的 - 150KB。考虑到kmalloc分配缓冲区的方式,ksize报告说,更多的内存正在被使用 - 大约256KB左右。kmalloc中的缓冲区是否也是DMA安全缓冲区?

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标题也不清楚(实际上明确不清楚)。由于rx缓冲区永远不会超过几个字节,因此试图找出问题将会很麻烦!

+0

也许尝试构建你的代码直接写入到内存DMA'ble,而不是一个kmalloc的缓冲? – tangrs

+0

你为什么使用'kmalloc'作为视频缓冲区? –

+0

与__get_free_pages相反?应该没有什么区别......他们都是DMA安全的。我可以半回答我自己的问题 - 如果我对齐一个页面,我相信会排除任何缓存一致性问题的可能性,即使它是过度杀毒,也不会查看TLB的东西。 – carveone

回答

2

答案似乎是与provisos是。 (具体而言,“它比这更复杂”)

如果通过__get_free_page *()或通用内存分配器(kmalloc)获取内存,则可以使用从这些例程返回的地址来DMA /从该内存DMA。其基本含义是,kmalloc中的页面对齐缓冲区,甚至跨越多个页面,将是DMA安全的,因为底层物理内存保证是连续的,并且页面对齐缓冲区保证位于缓存线边界。

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

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

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

在我的情况下,将tx和rx缓冲区传递给没有dma_map_single的spi_sync很好 - spi例程会为我做到这一点。我可以将dma_map_single与unmap或dma_sync_single_for_cpu()一起使所有内容保持同步。我现在不打扰 - 性能调整司机的作品是一个更好的策略。

参见: