dma_alloc_coherent的第三个参数dma_handle 分析

编程知识 行业动态 更新时间:2024-06-13 00:19:09
我们在通过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的物理地址.


更多推荐

dma_alloc_coherent的第三个参数dma_handle 分析

本文发布于:2023-03-27 22:21:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/05df7a0f23ca9733e210789dc67e1fd1.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:第三个   参数   dma_alloc_coherent   dma_handle

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!