我有一个linux内核驱动程序(2.6.18),其中我使用了kmalloc(sizeof(my_struct_t),GFP_ATOMIC)来分配内存,后来用于使用某些设备的DMA控制器进行数据传输。后来我不得不增加my_struct的大小。它变得太大,以至于kmalloc()代码使用静态断言并编译__you_cannot_kmalloc_that_much符号来通知内存块太大而无法分配。所以我想我会将my_struct_t声明为静态变量,而不必分配它。
我定义了 static my_struct_t my_struct;
但DMA事务不能正常工作,我将无效数据DMA加到缓冲区。
我的问题是:禁止为dma使用静态(全局)缓冲区?如果是,那么内核存储器映射中的那些缓冲区就在哪里。
由于
答案 0 :(得分:2)
问题在于,如果要在堆栈上分配内存,则无法保证内存位于连续的物理内存块中。如果不是那么你不能DMA它。
将DMA传输分解为多个可以kmalloc的块不是更容易吗?然后,您可以发送n个DMA传输,而不仅仅是1.它会对您的总线利用率产生重大影响,并且与您当前的问题不同。
答案 1 :(得分:2)
您通常不能使用任何旧内存并将其用于DMA。问题是您的内存区域可能跨越页面边界并在物理内存的不同区域分开。此外,它可能会被换出,然后再换回到之前的不同物理位置。在某些体系结构中,存在从设备总线看不到的存储区域。你有时可能很幸运,你的不正确获取的DMA缓冲区有效,但不能保证。
查看dma分配函数,例如dma_alloc_coherent()
。另外LDD3第15章。
如果在分配DMA缓冲区时遇到问题,因为它们太大,那么您还有另一个问题,需要手动拆分DMA传输,或者使用分散 - 聚集DMA。