dma_alloc_coherent的第三个参数dma_handle 分析

我们在通过dma_alloc_coherent申请一致性dma内存
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
        dma_addr_t *dma_handle, gfp_t flag)
{
    return dma_alloc_attrs(dev, size, dma_handle, flag, 0);
}
又调用dma_alloc_attrs
static inline void *dma_alloc_attrs(struct device *dev, size_t size,
                       dma_addr_t *dma_handle, gfp_t flag,
                       unsigned long attrs)
{
    struct dma_map_ops *ops = get_dma_ops(dev);
    void *cpu_addr;

    BUG_ON(!ops);

    if (dma_alloc_from_coherent(dev, size, dma_handle, &cpu_addr))
        return cpu_addr;

    if (!arch_dma_alloc_attrs(&dev, &flag))
        return NULL;
    if (!ops->alloc)
        return NULL;

    cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
    debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
    return cpu_addr;
}
dma_alloc_attrs 又会调用dma_alloc_from_coherent ,这个函数会先从设备自身的一致性area里面申请memory
int dma_alloc_from_coherent(struct device *dev, ssize_t size,
                       dma_addr_t *dma_handle, void **ret)
{
    struct dma_coherent_mem *mem;
    int order = get_order(size);
    unsigned long flags;
    int pageno;
    int dma_memory_map;

    if (!dev)
        return 0;
    mem = dev->dma_mem;
    if (!mem)
        return 0;

    *ret = NULL;
    spin_lock_irqsave(&mem->spinlock, flags);

    if (unlikely(size > (mem->size << PAGE_SHIFT)))
        goto err;

    pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
    if (unlikely(pageno < 0))
        goto err;

    /*
     * Memory was found in the per-device area.
     */
    *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
    *ret = mem->virt_base + (pageno << PAGE_SHIFT);
    dma_memory_map = (mem->flags & DMA_MEMORY_MAP);
    spin_unlock_irqrestore(&mem->spinlock, flags);
    if (dma_memory_map)
        memset(*ret, 0, size);
    else
        memset_io(*ret, 0, size);

    return 1;

err:
    spin_unlock_irqrestore(&mem->spinlock, flags);
    /*
     * In the case where the allocation can not be satisfied from the
     * per-device area, try to fall back to generic memory if the
     * constraints allow it.
     */
    return mem->flags & DMA_MEMORY_EXCLUSIVE;
}
从dma_alloc_from_coherent 中可以看到mem是从dev->dma_mem 中得到,也就是从device自身的memory中的得到的.
随后通过pageno = bitmap_find_free_region(mem->bitmap, mem->size, order); 来找看是否有足够memory,如果有的话,就返回申请到memory的pageno。
然后dma_handle 就得到物理地址,而ret得到虚拟地址。
也就是说static inline void *dma_alloc_coherent(struct device *dev, size_t size,dma_addr_t *dma_handle, gfp_t flag),可以通过dma_handle 的到申请到memory的物理地址.


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值