参照元

説明

引数

返り値

参考

実装

static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
                              enum dma_data_direction dma_dir, gfp_t gfp_flags)
{
        struct vb2_dma_sg_conf *conf = alloc_ctx;
        struct vb2_dma_sg_buf *buf;
        struct sg_table *sgt;
        int ret;
        int num_pages;
        DEFINE_DMA_ATTRS(attrs);
        dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
        if (WARN_ON(alloc_ctx == NULL))
                return NULL;
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
                return NULL;
        buf->vaddr = NULL;
        buf->dma_dir = dma_dir;
        buf->offset = 0;
        buf->size = size;
        /* size is already page aligned */
        buf->num_pages = size >> PAGE_SHIFT;
        buf->dma_sgt = &buf->sg_table;

        buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
                             GFP_KERNEL);
        if (!buf->pages)
                goto fail_pages_array_alloc;

        ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags);
        if (ret)
                goto fail_pages_alloc;
        ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
                        buf->num_pages, 0, size, GFP_KERNEL);
        if (ret)
                goto fail_table_alloc;
        /* Prevent the device from being released while the buffer is used */
        buf->dev = get_device(conf->dev);
        sgt = &buf->sg_table;
        /*
         * No need to sync to the device, this will happen later when the
         * prepare() memop is called.
         */
        sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
                                      buf->dma_dir, &attrs);
        if (!sgt->nents)
                goto fail_map;
        buf->handler.refcount = &buf->refcount;
        buf->handler.put = vb2_dma_sg_put;
        buf->handler.arg = buf;

        atomic_inc(&buf->refcount);
        dprintk(1, "%s: Allocated buffer of %d pages\n",
                __func__, buf->num_pages);
        return buf;
fail_map:
        put_device(buf->dev);
        sg_free_table(buf->dma_sgt);
fail_table_alloc:
        num_pages = buf->num_pages;
        while (num_pages--)
                __free_page(buf->pages[num_pages]);
fail_pages_alloc:
        kfree(buf->pages);
fail_pages_array_alloc:
        kfree(buf);
        return NULL;
}

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-02-08 (月) 18:49:16