dma_alloc_coherent 申请内存用法和问题总结

  • Post author:
  • Post category:其他




1、dma_alloc_coherent用法

通过dma_alloc_coherent接口可以申请连续的大块内存。

dma_addr_t dma_handle;
cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);


入参:

dev:	``struct device *``,可设为NULL
size:  想要申请的内存长度,单位为bytes
gfp:   分配内存时的标志位,如GFP_KERNEL等,在此不多介绍


出参

cpu_addr:   内存虚拟其实地址
dma_handle: 实际物理地址



2、问题

使用这个接口最大只能申请到4M的内存,申请超过4M时,报

swiotlb buffer is full (sz: 16777216 bytes)

错误。



3、解决方法



方法一,走CMA空间配置



3.1 内核配置

CONFIG_CMA

在内核配置

CONFIG_CMA=y

,dma分配默认会走cma,空间会大点。

cat /proc/meminfo |grep Cma 可查看设备上cma空间大小。



3.2 修改cma起始地址

按照3.1设置后,有时仍然报swiotlb错误.

参考

一个大佬的回答

,总结如下:

检查内核打印,给cma分配的地址是否在4G以上,dma_allocat_coherent() 要求地址低于掩码[(0x1 << 32)-1] = 0xFFFFFFFF。如果地址大于这个,它将回退到 swiotlb 缓冲区。

因此需要指定cma空间分配的地址,方法见3.3



3.3 设置cma空间(大小和地址等)


3.3.1 内核配置

配置

CONFIG_CMA=y

后,cma空间应默认为64M.

如果需要修改,先配置

CONFIG_DMA_CMA=y

打开DMA Contiguous Memory Allocator, 再配置

CONFIG_CMA_SIZE_MBYTES

大小就行。

相关配置:

CONFIG_DMA_CMA
CONFIG_CMA_AREAS 配置 CMA 分配器区域数
CONFIG_CMA_SIZE_MBYTES 配置 CMA 的大小
CONFIG_CMA_SIZE_SEL_MBYTES 按 MB 配置 CMA 区域大小
CONFIG_CMA_SIZE_SEL_PERCENTAGE 按物理内存的百分比配置 CMA 区域大小
CONFIG_CMA_SIZE_SEL_MIN 优先选择最小的 CMA 体积
CONFIG_CMA_SIZE_SEL_MAX 优先选择最大的 CMA 体积
CONFIG_CMA_ALIGNMENT CMA 对齐大小


优点:


配置简单便捷。


缺点:


不能指定cma区域的地址。



3.3.2 cmdline配置

可通过cmdline配置cma空间属性。用法说明:

cma=nn[MG]@[start[MG][-end[MG]]]
            [ARM,X86,KNL]
            Sets the size of kernel global memory area for
            contiguous memory allocations and optionally the
            placement constraint by the physical address range of
            memory allocations. A value of 0 disables CMA
            altogether. For more information, see
            include/linux/dma-contiguous.h

例如:

cma=128M                    /* 设置一个128M的cma空间 */
cma=128M@0x8000000          /* 设置一个128M的cma空间并指定起始地址为0x8000000 */
cma=256M@0-4G               /* 在0-4G范围内设置一个256M的cma空间 */


cma=256M@0-4G

可解决上述dma_allocat_coherent要求地址在0~4G范围内的问题。


优点:


可配置大小,也可指定地址。

可通过uboot传参,也可内核指定CMDLINE。



3.3.3 dts配置

在dts中添加cma节点,可指定cma大小和空间。



方法二,修改内核代码

4M这个限制是本身应该是分的普通内存的限制, 例如把配置加一个CONFIG_FORCE_MAX_ZONEORDER=16把最大限制改成128M也能解决。

  23 /* Free memory management - zoned buddy allocator.  */
  24 #ifndef CONFIG_FORCE_MAX_ZONEORDER
  25 #define MAX_ORDER 11
  26 #else
  27 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
  28 #endif
  29 #define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))
"./include/linux/mmzone.h"    



参考


For the problem when using swiotlb



dma_alloc_coherent failed on x86_64 but works on i686



版权声明:本文为qq_28499879原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。