您的位置:首页 > 其它

device的私有memory

2017-03-16 09:39 316 查看
一般调用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: