*参照元 [#e447c409] #backlinks *説明 [#h020edbe] -パス: [[linux-4.4.1/drivers/media/v4l2-core/videobuf2-dma-sg.c]] -FIXME: これは何? --説明 **引数 [#v76e0e58] -void *alloc_ctx -- -unsigned long size -- -enum dma_data_direction dma_dir -- --[[linux-4.4.1/dma_data_direction]] -gfp_t gfp_flags -- --[[linux-4.4.1/gfp_t]] **返り値 [#g34f95a0] -int -- **参考 [#d2aa2f0f] *実装 [#te350b30] 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); - --[[linux-4.4.1/vb2_dma_sg_conf]] --[[linux-4.4.1/vb2_dma_sg_buf]] --[[linux-4.4.1/sg_table]] --[[linux-4.4.1/DEFINE_DMA_ATTRS()]] dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); - --[[linux-4.4.1/dma_set_attr()]] if (WARN_ON(alloc_ctx == NULL)) return NULL; buf = kzalloc(sizeof *buf, GFP_KERNEL); if (!buf) return NULL; - --[[linux-4.4.1/WARN_ON()]] --[[linux-4.4.1/kzalloc()]] 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; - --[[linux-4.4.1/vb2_dma_sg_alloc_compacted()]] ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages, buf->num_pages, 0, size, GFP_KERNEL); if (ret) goto fail_table_alloc; - --[[linux-4.4.1/sg_alloc_table_from_pages()]] /* Prevent the device from being released while the buffer is used */ buf->dev = get_device(conf->dev); - --[[linux-4.4.1/get_device()]] 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; - --[[linux-4.4.1/dma_map_sg_attrs()]] buf->handler.refcount = &buf->refcount; buf->handler.put = vb2_dma_sg_put; buf->handler.arg = buf; atomic_inc(&buf->refcount); - --[[linux-4.4.1/vb2_dma_sg_put()]] --[[linux-4.4.1/atomic_inc()]] dprintk(1, "%s: Allocated buffer of %d pages\n", __func__, buf->num_pages); return buf; - --[[linux-4.4.1/dprintk()]] fail_map: put_device(buf->dev); sg_free_table(buf->dma_sgt); - --[[linux-4.4.1/put_device()]] --[[linux-4.4.1/sg_free_table()]] fail_table_alloc: num_pages = buf->num_pages; while (num_pages--) __free_page(buf->pages[num_pages]); - --[[linux-4.4.1/__free_page()]] fail_pages_alloc: kfree(buf->pages); fail_pages_array_alloc: kfree(buf); return NULL; - --[[linux-4.4.1/kfree()]] } *コメント [#l3e16e0b]