一个DMA 分配失败问题研究

 

一个DMA 分配失败问题研究

作者: 宋立新

Email[email protected]

现象:最近好几个模块的同事都反应驱动中调用:dma_alloc_writecombine 会失败!

研究:首先重现该问题, nand 驱动的 probe 函数:  pxa3xx_nand_probe 中调用 dma_alloc_writecombine:

 

测试代码:

    #if 1

    {

        int i;

        for (i=0; i < 1000; i++) {

            buf_len = 0x100000;

            info->data_desc = (struct pxa_dma_desc*)dma_alloc_writecombine(&pdev->dev,

                    buf_len, &info->data_desc_addr, GFP_KERNEL);

            printk("i:%d, phy:0x%lx, virt:0x%lx/n", i, info->data_desc_addr, info->data_desc);

 

            if (!info->data_desc)

                while(1) {}

        }

    }

    #endif

 

得到串口打印:

 

i:0, phy:0xa7300000, virt:0xff600000

i:1, phy:0xa7400000, virt:0xff700000

i:2, phy:0xa7500000, virt:0xff800000

i:3, phy:0xa7600000, virt:0xff900000

i:4, phy:0xa7700000, virt:0xffa00000

i:5, phy:0xa7800000, virt:0xffb00000

i:6, phy:0xa7900000, virt:0xffc00000

i:7, phy:0xa7a00000, virt:0xffd00000

i:8, phy:0xffffffff, virt:0x0

 

从输出看来,应该是虚拟地址不够用了, 导致出错。

 

仔细分析一下目前系统的虚存占用情况:

 

目前虚拟地址空间的占用:

 

物理内存: 0xc0000000-0xcfffffff (256M)

 

IO:

       0xf2000000 32M

       0xf4000000 1M

       0xf6000000 2M

       0xf8000000 1M

       0xfa000000 1M

       0xfa500000 1M

       0xfe000000 1M

       0xff000000 1M

 

向量表及保留:0xfffe0000-0xffffffff (这个是内核使用的)

 

虚拟内存应该还有很大的空间可用。

再去分析 dma_alloc_writecombine 的代码

dma_alloc_writecombine ->__dma_alloc 中用如下代码分配虚拟地址:

c = vm_region_alloc(&consistent_head, size,gfp & ~(__GFP_DMA | __GFP_HIGHMEM));

 

原来 DMA consistent_head 分配虚拟地址空间. 再去看看consistent_head的定义

 

static struct vm_region consistent_head = {

         .vm_list        = LIST_HEAD_INIT(consistent_head.vm_list),

         .vm_start       = CONSISTENT_BASE,

         .vm_end         = CONSISTENT_END,

};

 

#define CONSISTENT_END  (0xffe00000)

#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)

#define CONSISTENT_DMA_SIZE     8 * 1024 * 1024

 

真相大白! consistent_head 一共只有 8M 空间!

 

根据目前的虚拟地址空间分布,可以简单修改CONSISTENT_DMA_SIZE 为: 8M->12M  可将虚拟地址空间增大一些

如果需要更大,则需要修改CONSISTENT_END, 目前可以修改到 0xf2000000, 然后将

CONSISTENT_DMA_SIZE 改到 32M.

 

你可能感兴趣的:(c,struct,list,IO,测试,email)