一般调用of_reserved_mem_device_init来将reserved memory分配给特定的device.
例如drivers/gpu/drm/arm/malidp_drv.c, line 313
static inline int of_reserved_mem_device_init(struct device *dev)
{
    return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0);
}
这个函数直接转掉of_reserved_mem_device_init_by_idx
int of_reserved_mem_device_init_by_idx(struct device *dev,
                       struct device_node *np, int idx)
{
    struct rmem_assigned_device *rd;
    struct device_node *target;
    struct reserved_mem *rmem;
    int ret;

    if (!np || !dev)
        return -EINVAL;

    target = of_parse_phandle(np, "memory-region", idx);
    if (!target)
        return -ENODEV;

    rmem = __find_rmem(target);
    of_node_put(target);

    if (!rmem || !rmem->ops || !rmem->ops->device_init)
        return -EINVAL;

    rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL);
    if (!rd)
        return -ENOMEM;

    ret = rmem->ops->device_init(rmem, dev);
    if (ret == 0) {
        rd->dev = dev;
        rd->rmem = rmem;

        mutex_lock(&of_rmem_assigned_device_mutex);
        list_add(&rd->list, &of_rmem_assigned_device_list);
        mutex_unlock(&of_rmem_assigned_device_mutex);

        dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
    } else {
        kfree(rd);
    }

    return ret;
}
在of_reserved_mem_device_init_by_idx 中主要通过在dts中parse memory-region来决定给device哪个reserved memory
首先通过__find_rmem 找到这个reserved memory,然后申请一个rmem_assigned_device *rd 结构
通过调用rmem->ops->device_init(rmem, dev)来将reserved memory 分配给device
而这里的ops其实是下面这个
static const struct reserved_mem_ops rmem_dma_ops = {
    .device_init    = rmem_dma_device_init,
    .device_release    = rmem_dma_device_release,
};

因此调用rmem_dma_device_init->dma_assign_coherent_memory
static int dma_assign_coherent_memory(struct device *dev,
                      struct dma_coherent_mem *mem)
{
    if (dev->dma_mem)
        return -EBUSY;

    dev->dma_mem = mem;
    /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */

    return 0;
}
来将memory 赋值dev->dma_mem
那这种私有的memory 要具体怎么使用呢?
因此我们前面讲dma_alloc_coherent->dma_alloc_attrs->dma_alloc_from_coherent
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;
}
这个函数就会使用这个device 私有的memory

更多推荐

device的私有memory