* [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf
@ 2012-03-06 11:38 Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support Tomasz Stanislawski
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
Hello everyone,
This patchset is an incremental patch to patchset created by Sumit Semwal [1].
The patches are dedicated to help find a better solution for support of buffer
sharing by V4L2 API. It is expected to start discussion on the final
installment for dma-buf in vb2-dma-contig allocator. Current version of the
patches contain little documentation. It is going to be fixed after achieving
consensus about design for buffer exporting. Moreover the API between vb2-core
and the allocator should be revised.
The patches were successfully tested to cooperate with EXYNOS DRM driver using
DMABUF mechanism.
Please note, that the amount of changes to vb2-dma-contig.c was significant
making the difference patch very difficult to read.
The patchset makes use of dma_get_pages extension for DMA API, which is posted
on a top of dma-mapping patches by Marek Szyprowski [4] [5].
The tree, that contains all needed patches, can be found here [6].
v2:
- extended VIDIOC_EXPBUF argument from integer memoffset to struct
v4l2_exportbuffer
- added patch that breaks DMABUF spec on (un)map_atachment callcacks but allows
to work with existing implementation of DMABUF prime in DRM
- all dma-contig code refactoring patches were squashed
- bugfixes
v1: List of changes since [1].
- support for DMA api extension dma_get_pages, the function is used to retrieve
pages used to create DMA mapping.
- small fixes/code cleanup to videobuf2
- added prepare and finish callbacks to vb2 allocators, it is used keep
consistency between dma-cpu acess to the memory (by Marek Szyprowski)
- support for exporting of DMABUF buffer in V4L2 and Videobuf2, originated from
[3].
- support for dma-buf exporting in vb2-dma-contig allocator
- support for DMABUF for s5p-tv and s5p-fimc (capture interface) drivers,
originated from [3]
- changed handling for userptr buffers (by Marek Szyprowski, Andrzej
Pietrasiewicz)
- let mmap method to use dma_mmap_writecombine call (by Marek Szyprowski)
[1] http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/42966/focus=42968
[2] https://lkml.org/lkml/2011/12/26/29
[3] http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/36354/focus=36355
[4] http://thread.gmane.org/gmane.linux.kernel.cross-arch/12819
[5] http://git.infradead.org/users/kmpark/linux-2.6-samsung/shortlog/refs/heads/3.3-rc5-dma-v7
[6] http://git.infradead.org/users/kmpark/linux-2.6-samsung/shortlog/refs/heads/3.3-rc5-vb2-dma-contig-dmabuf-drm
Sumit Semwal (1):
v4l: vb2: Add dma-contig allocator as dma_buf user
Tomasz Stanislawski (8):
v4l: vb2: fixes for DMABUF support
v4l: vb2-dma-contig: update and code refactoring
v4l: add buffer exporting via dmabuf
v4l: vb2: add buffer exporting via dmabuf
v4l: vb2-dma-contig: add support for DMABUF exporting
v4l: vb2-dma-contig: change map/unmap behaviour
v4l: fimc: integrate capture i-face with dmabuf
v4l: s5p-tv: mixer: integrate with dmabuf
drivers/media/video/Kconfig | 1 +
drivers/media/video/s5p-fimc/fimc-capture.c | 11 +-
drivers/media/video/s5p-tv/Kconfig | 1 +
drivers/media/video/s5p-tv/mixer_video.c | 12 +-
drivers/media/video/v4l2-compat-ioctl32.c | 1 +
drivers/media/video/v4l2-ioctl.c | 11 +
drivers/media/video/videobuf2-core.c | 88 +++-
drivers/media/video/videobuf2-dma-contig.c | 717 ++++++++++++++++++++++++---
include/linux/videodev2.h | 20 +
include/media/v4l2-ioctl.h | 2 +
include/media/videobuf2-core.h | 8 +-
11 files changed, 779 insertions(+), 93 deletions(-)
--
1.7.5.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-20 15:04 ` Semwal, Sumit
2012-03-06 11:38 ` [RFCv2 PATCH 2/9] v4l: vb2-dma-contig: update and code refactoring Tomasz Stanislawski
` (8 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
This patch contains fixes to DMABUF support in vb2-core.
- fixes number of arguments of call_memop macro
- fixes setup of plane length
- fixes handling of error pointers
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/videobuf2-core.c | 24 +++++++++++-------------
include/media/videobuf2-core.h | 6 +++---
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 951cb56..e7df560 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -118,7 +118,7 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
void *mem_priv = vb->planes[plane].mem_priv;
if (mem_priv) {
- call_memop(q, plane, detach_dmabuf, mem_priv);
+ call_memop(q, detach_dmabuf, mem_priv);
dma_buf_put(vb->planes[plane].dbuf);
vb->planes[plane].dbuf = NULL;
vb->planes[plane].mem_priv = NULL;
@@ -905,6 +905,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
}
if (b->memory == V4L2_MEMORY_DMABUF) {
for (plane = 0; plane < vb->num_planes; ++plane) {
+ v4l2_planes[plane].bytesused =
+ b->m.planes[plane].bytesused;
v4l2_planes[plane].m.fd = b->m.planes[plane].m.fd;
}
}
@@ -1052,17 +1054,13 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
if (IS_ERR_OR_NULL(dbuf)) {
dprintk(1, "qbuf: invalid dmabuf fd for "
"plane %d\n", plane);
- ret = PTR_ERR(dbuf);
+ ret = -EINVAL;
goto err;
}
- /* this doesn't get filled in until __fill_vb2_buffer(),
- * since it isn't known until after dma_buf_get()..
- */
- planes[plane].length = dbuf->size;
-
/* Skip the plane if already verified */
if (dbuf == vb->planes[plane].dbuf) {
+ planes[plane].length = dbuf->size;
dma_buf_put(dbuf);
continue;
}
@@ -1072,7 +1070,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
/* Release previously acquired memory if present */
if (vb->planes[plane].mem_priv) {
- call_memop(q, plane, detach_dmabuf,
+ call_memop(q, detach_dmabuf,
vb->planes[plane].mem_priv);
dma_buf_put(vb->planes[plane].dbuf);
}
@@ -1080,8 +1078,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
vb->planes[plane].mem_priv = NULL;
/* Acquire each plane's memory */
- mem_priv = q->mem_ops->attach_dmabuf(
- q->alloc_ctx[plane], dbuf);
+ mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane],
+ dbuf, q->plane_sizes[plane], write);
if (IS_ERR(mem_priv)) {
dprintk(1, "qbuf: failed acquiring dmabuf "
"memory for plane %d\n", plane);
@@ -1089,6 +1087,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
goto err;
}
+ planes[plane].length = dbuf->size;
vb->planes[plane].dbuf = dbuf;
vb->planes[plane].mem_priv = mem_priv;
}
@@ -1098,8 +1097,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
* the buffer(s)..
*/
for (plane = 0; plane < vb->num_planes; ++plane) {
- ret = q->mem_ops->map_dmabuf(
- vb->planes[plane].mem_priv, write);
+ ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv);
if (ret) {
dprintk(1, "qbuf: failed mapping dmabuf "
"memory for plane %d\n", plane);
@@ -1527,7 +1525,7 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
*/
if (q->memory == V4L2_MEMORY_DMABUF)
for (plane = 0; plane < vb->num_planes; ++plane)
- call_memop(q, plane, unmap_dmabuf,
+ call_memop(q, unmap_dmabuf,
vb->planes[plane].mem_priv);
switch (vb->state) {
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index d8b8171..412c6a4 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -88,10 +88,10 @@ struct vb2_mem_ops {
* in the vb2 core, and vb2_mem_ops really just need to get/put the
* sglist (and make sure that the sglist fits it's needs..)
*/
- void *(*attach_dmabuf)(void *alloc_ctx,
- struct dma_buf *dbuf);
+ void *(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
+ unsigned long size, int write);
void (*detach_dmabuf)(void *buf_priv);
- int (*map_dmabuf)(void *buf_priv, int write);
+ int (*map_dmabuf)(void *buf_priv);
void (*unmap_dmabuf)(void *buf_priv);
void *(*vaddr)(void *buf_priv);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 2/9] v4l: vb2-dma-contig: update and code refactoring
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 3/9] v4l: vb2: Add dma-contig allocator as dma_buf user Tomasz Stanislawski
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki, Andrzej Pietrasiewicz,
Kamil Debski
This patch combines updates and fixes to dma-contig allocator.
Moreover the allocator code was refactored.
The most important changes are:
- functions were reordered
- move compression of scatterlist to separete function
- add support for multichunk but contiguous scatterlists
- simplified implementation of vb2-dma-contig context structure
- let mmap method to use dma_mmap_writecombine
- add support for scatterlist in userptr mode
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
[mmap method]
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
[scatterlist in userptr mode]
Signed-off-by: Kamil Debski <k.debski@samsung.com>
[bugfixing]
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
[core refactoring, helper functions]
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/videobuf2-dma-contig.c | 495 +++++++++++++++++++++++-----
1 files changed, 414 insertions(+), 81 deletions(-)
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index f17ad98..c1dc043 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -10,173 +10,506 @@
* the Free Software Foundation.
*/
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/dma-mapping.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-memops.h>
-struct vb2_dc_conf {
- struct device *dev;
-};
-
struct vb2_dc_buf {
- struct vb2_dc_conf *conf;
+ struct device *dev;
void *vaddr;
- dma_addr_t dma_addr;
unsigned long size;
- struct vm_area_struct *vma;
- atomic_t refcount;
+ dma_addr_t dma_addr;
+ struct sg_table *dma_sgt;
+ enum dma_data_direction dma_dir;
+
+ /* MMAP related */
struct vb2_vmarea_handler handler;
+ atomic_t refcount;
+ struct sg_table *sgt_base;
+
+ /* USERPTR related */
+ struct vm_area_struct *vma;
};
-static void vb2_dma_contig_put(void *buf_priv);
+/*********************************************/
+/* scatterlist table functions */
+/*********************************************/
-static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
+static struct sg_table *vb2_dc_pages_to_sgt(struct page **pages,
+ unsigned long n_pages, size_t offset, size_t offset2)
{
- struct vb2_dc_conf *conf = alloc_ctx;
- struct vb2_dc_buf *buf;
+ struct sg_table *sgt;
+ int i, j; /* loop counters */
+ int cur_page, chunks;
+ int ret;
+ struct scatterlist *s;
- buf = kzalloc(sizeof *buf, GFP_KERNEL);
- if (!buf)
+ sgt = kzalloc(sizeof *sgt, GFP_KERNEL);
+ if (!sgt)
return ERR_PTR(-ENOMEM);
- buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
- GFP_KERNEL);
- if (!buf->vaddr) {
- dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
- size);
- kfree(buf);
+ /* compute number of chunks */
+ chunks = 1;
+ for (i = 1; i < n_pages; ++i)
+ if (pages[i] != pages[i - 1] + 1)
+ ++chunks;
+
+ ret = sg_alloc_table(sgt, chunks, GFP_KERNEL);
+ if (ret) {
+ kfree(sgt);
return ERR_PTR(-ENOMEM);
}
- buf->conf = conf;
- buf->size = size;
-
- buf->handler.refcount = &buf->refcount;
- buf->handler.put = vb2_dma_contig_put;
- buf->handler.arg = buf;
+ /* merging chunks and putting them into the scatterlist */
+ cur_page = 0;
+ for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
+ size_t size = PAGE_SIZE;
+
+ for (j = cur_page + 1; j < n_pages; ++j) {
+ if (pages[j] != pages[j - 1] + 1)
+ break;
+ size += PAGE_SIZE;
+ }
+
+ /* cut offset if chunk starts at the first page */
+ if (cur_page == 0)
+ size -= offset;
+ /* cut offset2 if chunk ends at the last page */
+ if (j == n_pages)
+ size -= offset2;
+
+ sg_set_page(s, pages[cur_page], size, offset);
+ offset = 0;
+ cur_page = j;
+ }
- atomic_inc(&buf->refcount);
+ return sgt;
+}
- return buf;
+static void vb2_dc_release_sgtable(struct sg_table *sgt)
+{
+ sg_free_table(sgt);
+ kfree(sgt);
}
-static void vb2_dma_contig_put(void *buf_priv)
+static void vb2_dc_put_sgtable(struct sg_table *sgt, int dirty)
{
- struct vb2_dc_buf *buf = buf_priv;
+ struct scatterlist *s;
+ int i, j;
+
+ for_each_sg(sgt->sgl, s, sgt->nents, i) {
+ struct page *page = sg_page(s);
+ int n_pages = PAGE_ALIGN(s->offset + s->length) >> PAGE_SHIFT;
+
+ for (j = 0; j < n_pages; ++j, ++page) {
+ if (dirty)
+ set_page_dirty_lock(page);
+ put_page(page);
+ }
+ }
+
+ vb2_dc_release_sgtable(sgt);
+}
- if (atomic_dec_and_test(&buf->refcount)) {
- dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
- buf->dma_addr);
- kfree(buf);
+static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
+{
+ struct scatterlist *s;
+ dma_addr_t expected = sg_dma_address(sgt->sgl);
+ int i;
+ unsigned long size = 0;
+
+ for_each_sg(sgt->sgl, s, sgt->nents, i) {
+ if (sg_dma_address(s) != expected)
+ break;
+ expected = sg_dma_address(s) + sg_dma_len(s);
+ size += sg_dma_len(s);
}
+ return size;
}
-static void *vb2_dma_contig_cookie(void *buf_priv)
+/*********************************************/
+/* callbacks for all buffers */
+/*********************************************/
+
+static void *vb2_dc_cookie(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
return &buf->dma_addr;
}
-static void *vb2_dma_contig_vaddr(void *buf_priv)
+static void *vb2_dc_vaddr(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
- if (!buf)
- return 0;
return buf->vaddr;
}
-static unsigned int vb2_dma_contig_num_users(void *buf_priv)
+static unsigned int vb2_dc_num_users(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
return atomic_read(&buf->refcount);
}
-static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
+static void vb2_dc_prepare(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
+ struct sg_table *sgt = buf->dma_sgt;
- if (!buf) {
- printk(KERN_ERR "No buffer to map\n");
- return -EINVAL;
- }
+ if (!sgt)
+ return;
+
+ dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dc_finish(void *buf_priv)
+{
+ struct vb2_dc_buf *buf = buf_priv;
+ struct sg_table *sgt = buf->dma_sgt;
+
+ if (!sgt)
+ return;
+
+ dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+/*********************************************/
+/* callbacks for MMAP buffers */
+/*********************************************/
+
+static void vb2_dc_put(void *buf_priv)
+{
+ struct vb2_dc_buf *buf = buf_priv;
- return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
- &vb2_common_vm_ops, &buf->handler);
+ if (!atomic_dec_and_test(&buf->refcount))
+ return;
+
+ vb2_dc_release_sgtable(buf->sgt_base);
+ dma_free_coherent(buf->dev, buf->size, buf->vaddr,
+ buf->dma_addr);
+ kfree(buf);
}
-static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
- unsigned long size, int write)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
{
+ struct device *dev = alloc_ctx;
struct vb2_dc_buf *buf;
- struct vm_area_struct *vma;
- dma_addr_t dma_addr = 0;
int ret;
+ int n_pages;
+ struct page **pages = NULL;
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
- ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
- if (ret) {
- printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
- vaddr);
- kfree(buf);
- return ERR_PTR(ret);
+ buf->dev = dev;
+ buf->size = size;
+ buf->vaddr = dma_alloc_coherent(buf->dev, buf->size, &buf->dma_addr,
+ GFP_KERNEL);
+
+ ret = -ENOMEM;
+ if (!buf->vaddr) {
+ dev_err(dev, "dma_alloc_coherent of size %ld failed\n",
+ size);
+ goto fail_buf;
}
- buf->size = size;
- buf->dma_addr = dma_addr;
- buf->vma = vma;
+ WARN_ON((unsigned long)buf->vaddr & ~PAGE_MASK);
+ WARN_ON(buf->dma_addr & ~PAGE_MASK);
+
+ n_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+ pages = kmalloc(n_pages * sizeof pages[0], GFP_KERNEL);
+ if (!pages) {
+ printk(KERN_ERR "failed to alloc page table\n");
+ goto fail_dma;
+ }
+
+ ret = dma_get_pages(dev, buf->vaddr, buf->dma_addr, pages, n_pages);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to get buffer pages from DMA API\n");
+ goto fail_pages;
+ }
+ if (ret != n_pages) {
+ ret = -EFAULT;
+ printk(KERN_ERR "failed to get all pages from DMA API\n");
+ goto fail_pages;
+ }
+
+ buf->sgt_base = vb2_dc_pages_to_sgt(pages, n_pages, 0, 0);
+ if (IS_ERR(buf->sgt_base)) {
+ ret = PTR_ERR(buf->sgt_base);
+ printk(KERN_ERR "failed to prepare sg table\n");
+ goto fail_pages;
+ }
+
+ /* pages are no longer needed */
+ kfree(pages);
+
+ buf->handler.refcount = &buf->refcount;
+ buf->handler.put = vb2_dc_put;
+ buf->handler.arg = buf;
+
+ atomic_inc(&buf->refcount);
return buf;
+
+fail_pages:
+ kfree(pages);
+
+fail_dma:
+ dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+
+fail_buf:
+ kfree(buf);
+
+ return ERR_PTR(ret);
+}
+
+static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+ struct vb2_dc_buf *buf = buf_priv;
+ int ret;
+
+ /*
+ * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
+ * map whole buffer
+ */
+ vma->vm_pgoff = 0;
+
+ ret = dma_mmap_writecombine(buf->dev, vma, buf->vaddr,
+ buf->dma_addr, buf->size);
+
+ if (ret) {
+ printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
+ return ret;
+ }
+
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+ vma->vm_private_data = &buf->handler;
+ vma->vm_ops = &vb2_common_vm_ops;
+
+ vma->vm_ops->open(vma);
+
+ printk(KERN_DEBUG "%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
+ __func__, (unsigned long)buf->dma_addr, vma->vm_start,
+ buf->size);
+
+ return 0;
}
-static void vb2_dma_contig_put_userptr(void *mem_priv)
+/*********************************************/
+/* callbacks for USERPTR buffers */
+/*********************************************/
+
+static inline int vma_is_io(struct vm_area_struct *vma)
{
- struct vb2_dc_buf *buf = mem_priv;
+ return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
+}
+static int vb2_dc_get_pages(unsigned long start, struct page **pages,
+ int n_pages, struct vm_area_struct **copy_vma, int write)
+{
+ struct vm_area_struct *vma;
+ int n = 0; /* number of get pages */
+ int ret = -EFAULT;
+
+ /* entering critical section for mm access */
+ down_read(¤t->mm->mmap_sem);
+
+ vma = find_vma(current->mm, start);
+ if (!vma) {
+ printk(KERN_ERR "no vma for address %lu\n", start);
+ goto cleanup;
+ }
+
+ if (vma_is_io(vma)) {
+ unsigned long pfn;
+
+ if (vma->vm_end - start < n_pages * PAGE_SIZE) {
+ printk(KERN_ERR "vma is too small\n");
+ goto cleanup;
+ }
+
+ for (n = 0; n < n_pages; ++n, start += PAGE_SIZE) {
+ ret = follow_pfn(vma, start, &pfn);
+ if (ret) {
+ printk(KERN_ERR "no page for address %lu\n",
+ start);
+ goto cleanup;
+ }
+ pages[n] = pfn_to_page(pfn);
+ get_page(pages[n]);
+ }
+ } else {
+ n = get_user_pages(current, current->mm, start & PAGE_MASK,
+ n_pages, write, 1, pages, NULL);
+ if (n != n_pages) {
+ printk(KERN_ERR "got only %d of %d user pages\n",
+ n, n_pages);
+ goto cleanup;
+ }
+ }
+
+ *copy_vma = vb2_get_vma(vma);
+ if (!*copy_vma) {
+ printk(KERN_ERR "failed to copy vma\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* leaving critical section for mm access */
+ up_read(¤t->mm->mmap_sem);
+
+ return 0;
+
+cleanup:
+ up_read(¤t->mm->mmap_sem);
+
+ /* putting user pages if used, can be done wothout the lock */
+ while (n)
+ put_page(pages[--n]);
+
+ return ret;
+}
+
+static void vb2_dc_put_userptr(void *buf_priv)
+{
+ struct vb2_dc_buf *buf = buf_priv;
+ struct sg_table *sgt = buf->dma_sgt;
+
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+ vb2_dc_put_sgtable(sgt, !vma_is_io(buf->vma));
+ vb2_put_vma(buf->vma);
+ kfree(buf);
+}
+
+static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
+ unsigned long size, int write)
+{
+ struct vb2_dc_buf *buf;
+ unsigned long start, end, offset, offset2;
+ struct page **pages;
+ int n_pages;
+ int ret = 0;
+ struct sg_table *sgt;
+ unsigned long contig_size;
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
- return;
+ return ERR_PTR(-ENOMEM);
+
+ buf->dev = alloc_ctx;
+ buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ start = (unsigned long)vaddr & PAGE_MASK;
+ offset = (unsigned long)vaddr & ~PAGE_MASK;
+ end = PAGE_ALIGN((unsigned long)vaddr + size);
+ offset2 = end - (unsigned long)vaddr - size;
+ n_pages = (end - start) >> PAGE_SHIFT;
+
+ pages = kmalloc(n_pages * sizeof pages[0], GFP_KERNEL);
+ if (!pages) {
+ ret = -ENOMEM;
+ printk(KERN_ERR "failed to allocate pages table\n");
+ goto fail_buf;
+ }
+
+ /* extract page list from userspace mapping */
+ ret = vb2_dc_get_pages(start, pages, n_pages, &buf->vma, write);
+ if (ret) {
+ printk(KERN_ERR "failed to get user pages\n");
+ goto fail_pages;
+ }
+
+ sgt = vb2_dc_pages_to_sgt(pages, n_pages, offset, offset2);
+ if (!sgt) {
+ printk(KERN_ERR "failed to create scatterlist table\n");
+ ret = -ENOMEM;
+ goto fail_get_pages;
+ }
+
+ /* pages are no longer needed */
+ kfree(pages);
+ pages = NULL;
+
+ sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+ buf->dma_dir);
+ if (sgt->nents <= 0) {
+ printk(KERN_ERR "failed to map scatterlist\n");
+ ret = -EIO;
+ goto fail_sgt;
+ }
+
+ contig_size = vb2_dc_get_contiguous_size(sgt);
+ if (contig_size < size) {
+ printk(KERN_ERR "contiguous mapping is too small %lu/%lu\n",
+ contig_size, size);
+ ret = -EFAULT;
+ goto fail_map_sg;
+ }
+
+ buf->dma_addr = sg_dma_address(sgt->sgl);
+ buf->size = size;
+ buf->dma_sgt = sgt;
+
+ atomic_inc(&buf->refcount);
+
+ return buf;
+
+fail_map_sg:
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+fail_sgt:
+ vb2_dc_put_sgtable(sgt, 0);
+
+fail_get_pages:
+ while (pages && n_pages)
+ put_page(pages[--n_pages]);
vb2_put_vma(buf->vma);
+
+fail_pages:
+ kfree(pages); /* kfree is NULL-proof */
+
+fail_buf:
kfree(buf);
+
+ return ERR_PTR(ret);
}
+/*********************************************/
+/* DMA CONTIG exported functions */
+/*********************************************/
+
const struct vb2_mem_ops vb2_dma_contig_memops = {
- .alloc = vb2_dma_contig_alloc,
- .put = vb2_dma_contig_put,
- .cookie = vb2_dma_contig_cookie,
- .vaddr = vb2_dma_contig_vaddr,
- .mmap = vb2_dma_contig_mmap,
- .get_userptr = vb2_dma_contig_get_userptr,
- .put_userptr = vb2_dma_contig_put_userptr,
- .num_users = vb2_dma_contig_num_users,
+ .alloc = vb2_dc_alloc,
+ .put = vb2_dc_put,
+ .cookie = vb2_dc_cookie,
+ .vaddr = vb2_dc_vaddr,
+ .mmap = vb2_dc_mmap,
+ .get_userptr = vb2_dc_get_userptr,
+ .put_userptr = vb2_dc_put_userptr,
+ .prepare = vb2_dc_prepare,
+ .finish = vb2_dc_finish,
+ .num_users = vb2_dc_num_users,
};
EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
void *vb2_dma_contig_init_ctx(struct device *dev)
{
- struct vb2_dc_conf *conf;
-
- conf = kzalloc(sizeof *conf, GFP_KERNEL);
- if (!conf)
- return ERR_PTR(-ENOMEM);
-
- conf->dev = dev;
-
- return conf;
+ return dev;
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx);
void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
{
- kfree(alloc_ctx);
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 3/9] v4l: vb2: Add dma-contig allocator as dma_buf user
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 2/9] v4l: vb2-dma-contig: update and code refactoring Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 4/9] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki, Sumit Semwal
From: Sumit Semwal <sumit.semwal@ti.com>
This patch makes changes for adding dma-contig as a dma_buf user. It provides
function implementations for the {attach, detach, map, unmap}_dmabuf()
mem_ops of DMABUF memory type.
Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
[author of the original patch]
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
[integration with refactored dma-contig allocator]
---
drivers/media/video/videobuf2-dma-contig.c | 116 ++++++++++++++++++++++++++++
1 files changed, 116 insertions(+), 0 deletions(-)
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index c1dc043..746dd5f 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -35,6 +35,9 @@ struct vb2_dc_buf {
/* USERPTR related */
struct vm_area_struct *vma;
+
+ /* DMABUF related */
+ struct dma_buf_attachment *db_attach;
};
/*********************************************/
@@ -485,6 +488,115 @@ fail_buf:
}
/*********************************************/
+/* callbacks for DMABUF buffers */
+/*********************************************/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+ struct sg_table *sgt;
+ unsigned long contig_size;
+ int ret = 0;
+
+ if (WARN_ON(!buf->db_attach)) {
+ printk(KERN_ERR "trying to pin a non attached buffer\n");
+ return -EINVAL;
+ }
+
+ if (WARN_ON(buf->dma_sgt)) {
+ printk(KERN_ERR "dmabuf buffer is already pinned\n");
+ return 0;
+ }
+
+ /* get the associated scatterlist for this buffer */
+ sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
+ if (IS_ERR_OR_NULL(sgt)) {
+ printk(KERN_ERR "Error getting dmabuf scatterlist\n");
+ return -EINVAL;
+ }
+
+ /* checking if dmabuf is big enough to store contiguous chunk */
+ contig_size = vb2_dc_get_contiguous_size(sgt);
+ if (contig_size < buf->size) {
+ printk(KERN_ERR "contiguous chunk of dmabuf is too small\n");
+ ret = -EFAULT;
+ goto fail_map;
+ }
+
+ buf->dma_addr = sg_dma_address(sgt->sgl);
+ buf->dma_sgt = sgt;
+
+ return 0;
+
+fail_map:
+ dma_buf_unmap_attachment(buf->db_attach, sgt);
+
+ return ret;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+ struct sg_table *sgt = buf->dma_sgt;
+
+ if (WARN_ON(!buf->db_attach)) {
+ printk(KERN_ERR "trying to unpin a not attached buffer\n");
+ return;
+ }
+
+ if (WARN_ON(!sgt)) {
+ printk(KERN_ERR "dmabuf buffer is already unpinned\n");
+ return;
+ }
+
+ dma_buf_unmap_attachment(buf->db_attach, sgt);
+
+ buf->dma_addr = 0;
+ buf->dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+ struct vb2_dc_buf *buf = mem_priv;
+
+ if (buf->dma_addr)
+ vb2_dc_unmap_dmabuf(buf);
+
+ /* detach this attachment */
+ dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
+ kfree(buf);
+}
+
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+ unsigned long size, int write)
+{
+ struct vb2_dc_buf *buf;
+ struct dma_buf_attachment *dba;
+
+ if (dbuf->size < size)
+ return ERR_PTR(-EFAULT);
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ buf->dev = alloc_ctx;
+ /* create attachment for the dmabuf with the user device */
+ dba = dma_buf_attach(dbuf, buf->dev);
+ if (IS_ERR(dba)) {
+ printk(KERN_ERR "failed to attach dmabuf\n");
+ kfree(buf);
+ return dba;
+ }
+
+ buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ buf->size = size;
+ buf->db_attach = dba;
+
+ return buf;
+}
+
+/*********************************************/
/* DMA CONTIG exported functions */
/*********************************************/
@@ -498,6 +610,10 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
.put_userptr = vb2_dc_put_userptr,
.prepare = vb2_dc_prepare,
.finish = vb2_dc_finish,
+ .map_dmabuf = vb2_dc_map_dmabuf,
+ .unmap_dmabuf = vb2_dc_unmap_dmabuf,
+ .attach_dmabuf = vb2_dc_attach_dmabuf,
+ .detach_dmabuf = vb2_dc_detach_dmabuf,
.num_users = vb2_dc_num_users,
};
EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 4/9] v4l: add buffer exporting via dmabuf
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (2 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 3/9] v4l: vb2: Add dma-contig allocator as dma_buf user Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 5/9] v4l: vb2: " Tomasz Stanislawski
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
mmap and return a file descriptor on success.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/v4l2-compat-ioctl32.c | 1 +
drivers/media/video/v4l2-ioctl.c | 11 +++++++++++
include/linux/videodev2.h | 20 ++++++++++++++++++++
include/media/v4l2-ioctl.h | 2 ++
4 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index e6f67aa..fd157cb 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -954,6 +954,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_S_FBUF32:
case VIDIOC_OVERLAY32:
case VIDIOC_QBUF32:
+ case VIDIOC_EXPBUF:
case VIDIOC_DQBUF32:
case VIDIOC_STREAMON32:
case VIDIOC_STREAMOFF32:
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 74cab51..a125016 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -207,6 +207,7 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
[_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
[_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
+ [_IOC_NR(VIDIOC_EXPBUF)] = "VIDIOC_EXPBUF",
[_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
[_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
[_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
@@ -938,6 +939,16 @@ static long __video_do_ioctl(struct file *file,
dbgbuf(cmd, vfd, p);
break;
}
+ case VIDIOC_EXPBUF:
+ {
+ struct v4l2_exportbuffer *p = arg;
+
+ if (!ops->vidioc_expbuf)
+ break;
+
+ ret = ops->vidioc_expbuf(file, fh, p);
+ break;
+ }
case VIDIOC_DQBUF:
{
struct v4l2_buffer *p = arg;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index bb6844e..e71c787 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -680,6 +680,25 @@ struct v4l2_buffer {
#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE 0x0800
#define V4L2_BUF_FLAG_NO_CACHE_CLEAN 0x1000
+/**
+ * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
+ *
+ * @fd: file descriptor associated with DMABUF (set by driver)
+ * @mem_offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
+ * offset from the start of the device memory for this plane,
+ * (or a "cookie" that should be passed to mmap() as offset)
+ *
+ * Contains data used for exporting a video buffer as DMABUF file
+ * descriptor. Uses the same 'cookie' as mmap() syscall. All reserved fields
+ * must be set to zero.
+ */
+struct v4l2_exportbuffer {
+ __u32 fd;
+ __u32 reserved0;
+ __u32 mem_offset;
+ __u32 reserved[13];
+};
+
/*
* O V E R L A Y P R E V I E W
*/
@@ -2303,6 +2322,7 @@ struct v4l2_create_buffers {
#define VIDIOC_S_FBUF _IOW('V', 11, struct v4l2_framebuffer)
#define VIDIOC_OVERLAY _IOW('V', 14, int)
#define VIDIOC_QBUF _IOWR('V', 15, struct v4l2_buffer)
+#define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer)
#define VIDIOC_DQBUF _IOWR('V', 17, struct v4l2_buffer)
#define VIDIOC_STREAMON _IOW('V', 18, int)
#define VIDIOC_STREAMOFF _IOW('V', 19, int)
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 4df031a..d8716c6f 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -120,6 +120,8 @@ struct v4l2_ioctl_ops {
int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
+ int (*vidioc_expbuf) (struct file *file, void *fh,
+ struct v4l2_exportbuffer *e);
int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b);
int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 5/9] v4l: vb2: add buffer exporting via dmabuf
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (3 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 4/9] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 6/9] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
This patch adds extension to videobuf2-core. It allow to export a mmap buffer
as a file descriptor.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/videobuf2-core.c | 64 ++++++++++++++++++++++++++++++++++
include/media/videobuf2-core.h | 2 +
2 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index e7df560..41c4bf8 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -1553,6 +1553,70 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
}
EXPORT_SYMBOL_GPL(vb2_dqbuf);
+static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
+ unsigned int *_buffer, unsigned int *_plane);
+
+/**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q: videobuf2 queue
+ * @b: export buffer structure passed from userspace to vidioc_expbuf
+ * handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+ struct vb2_buffer *vb = NULL;
+ struct vb2_plane *vb_plane;
+ unsigned int buffer, plane;
+ int ret;
+ struct dma_buf *dbuf;
+
+ if (q->memory != V4L2_MEMORY_MMAP) {
+ dprintk(1, "Queue is not currently set up for mmap\n");
+ return -EINVAL;
+ }
+
+ if (!q->mem_ops->get_dmabuf) {
+ dprintk(1, "Queue does not support DMA buffer exporting\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Find the plane corresponding to the offset passed by userspace.
+ */
+ ret = __find_plane_by_offset(q, eb->mem_offset, &buffer, &plane);
+ if (ret) {
+ dprintk(1, "invalid offset %u\n", eb->mem_offset);
+ return ret;
+ }
+
+ vb = q->bufs[buffer];
+ vb_plane = &vb->planes[plane];
+
+ dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+ if (IS_ERR_OR_NULL(dbuf)) {
+ dprintk(1, "Failed to export buffer %d, plane %d\n",
+ buffer, plane);
+ return -EINVAL;
+ }
+
+ ret = dma_buf_fd(dbuf);
+ if (ret < 0) {
+ dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+ buffer, plane, ret);
+ return ret;
+ }
+
+ dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
+ buffer, plane, ret);
+ eb->fd = ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
/**
* __vb2_queue_cancel() - cancel and stop (pause) streaming
*
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 412c6a4..548252b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -79,6 +79,7 @@ struct vb2_mem_ops {
void (*prepare)(void *buf_priv);
void (*finish)(void *buf_priv);
void (*put)(void *buf_priv);
+ struct dma_buf *(*get_dmabuf)(void *buf_priv);
void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write);
@@ -348,6 +349,7 @@ int vb2_queue_init(struct vb2_queue *q);
void vb2_queue_release(struct vb2_queue *q);
int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 6/9] v4l: vb2-dma-contig: add support for DMABUF exporting
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (4 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 5/9] v4l: vb2: " Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 7/9] v4l: vb2-dma-contig: change map/unmap behaviour Tomasz Stanislawski
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
This patch adds support for exporting a dma-contig buffer using
DMABUF interface.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/videobuf2-dma-contig.c | 128 ++++++++++++++++++++++++++++
1 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 746dd5f..d95b23a 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -31,6 +31,7 @@ struct vb2_dc_buf {
/* MMAP related */
struct vb2_vmarea_handler handler;
atomic_t refcount;
+ struct dma_buf *dma_buf;
struct sg_table *sgt_base;
/* USERPTR related */
@@ -194,6 +195,8 @@ static void vb2_dc_put(void *buf_priv)
if (!atomic_dec_and_test(&buf->refcount))
return;
+ if (buf->dma_buf)
+ dma_buf_put(buf->dma_buf);
vb2_dc_release_sgtable(buf->sgt_base);
dma_free_coherent(buf->dev, buf->size, buf->vaddr,
buf->dma_addr);
@@ -309,6 +312,130 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
}
/*********************************************/
+/* DMABUF ops for exporters */
+/*********************************************/
+
+struct vb2_dc_attachment {
+ struct sg_table sgt;
+ enum dma_data_direction dir;
+};
+
+static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+ struct dma_buf_attachment *dbuf_attach)
+{
+ /* nothing to be done */
+ return 0;
+}
+
+static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
+ struct dma_buf_attachment *db_attach)
+{
+ struct vb2_dc_attachment *attach = db_attach->priv;
+ struct sg_table *sgt;
+
+ if (!attach)
+ return;
+
+ sgt = &attach->sgt;
+
+ dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->nents, attach->dir);
+ sg_free_table(sgt);
+ kfree(attach);
+ db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dc_dmabuf_ops_map(
+ struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
+{
+ struct dma_buf *dbuf = db_attach->dmabuf;
+ struct vb2_dc_buf *buf = dbuf->priv;
+ struct vb2_dc_attachment *attach = db_attach->priv;
+ struct sg_table *sgt;
+ struct scatterlist *rd, *wr;
+ int i, ret;
+
+ /* return previously mapped sg table */
+ if (attach)
+ return &attach->sgt;
+
+ attach = kzalloc(sizeof *attach, GFP_KERNEL);
+ if (!attach)
+ return ERR_PTR(-ENOMEM);
+
+ sgt = &attach->sgt;
+ attach->dir = dir;
+
+ /* copying the buf->base_sgt to attachment */
+ ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
+ if (ret) {
+ kfree(attach);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rd = buf->sgt_base->sgl;
+ wr = sgt->sgl;
+ for (i = 0; i < sgt->orig_nents; ++i) {
+ sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
+ rd = sg_next(rd);
+ wr = sg_next(wr);
+ }
+
+ /* mapping new sglist to the client */
+ ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+ if (ret <= 0) {
+ printk(KERN_ERR "failed to map scatterlist\n");
+ sg_free_table(sgt);
+ kfree(attach);
+ return ERR_PTR(-EIO);
+ }
+
+ db_attach->priv = attach;
+
+ return sgt;
+}
+
+static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+ struct sg_table *sgt)
+{
+ /* nothing to be done here */
+}
+
+static void vb2_dc_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+ /* drop reference obtained in vb2_dc_get_dmabuf */
+ vb2_dc_put(dbuf->priv);
+}
+
+static struct dma_buf_ops vb2_dc_dmabuf_ops = {
+ .attach = vb2_dc_dmabuf_ops_attach,
+ .detach = vb2_dc_dmabuf_ops_detach,
+ .map_dma_buf = vb2_dc_dmabuf_ops_map,
+ .unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
+ .release = vb2_dc_dmabuf_ops_release,
+};
+
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
+{
+ struct vb2_dc_buf *buf = buf_priv;
+ struct dma_buf *dbuf;
+
+ if (buf->dma_buf)
+ return buf->dma_buf;
+
+ /* dmabuf keeps reference to vb2 buffer */
+ atomic_inc(&buf->refcount);
+ dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+ if (IS_ERR(dbuf)) {
+ atomic_dec(&buf->refcount);
+ return NULL;
+ }
+
+ buf->dma_buf = dbuf;
+
+ return dbuf;
+}
+
+/*********************************************/
/* callbacks for USERPTR buffers */
/*********************************************/
@@ -603,6 +730,7 @@ static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
const struct vb2_mem_ops vb2_dma_contig_memops = {
.alloc = vb2_dc_alloc,
.put = vb2_dc_put,
+ .get_dmabuf = vb2_dc_get_dmabuf,
.cookie = vb2_dc_cookie,
.vaddr = vb2_dc_vaddr,
.mmap = vb2_dc_mmap,
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 7/9] v4l: vb2-dma-contig: change map/unmap behaviour
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (5 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 6/9] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 8/9] v4l: fimc: integrate capture i-face with dmabuf Tomasz Stanislawski
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
The DMABUF documentation says that the map_dma_buf callback should return
scatterlist that is mapped into a caller's address space. In practice, almost
none of existing implementations of DMABUF exporter does it. This patch breaks
the DMABUF specification in order to allow exchange DMABUF buffers between
other APIs like DRM.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/videobuf2-dma-contig.c | 64 ++++++++++++----------------
1 files changed, 27 insertions(+), 37 deletions(-)
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index d95b23a..32bb16b 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -315,11 +315,6 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
/* DMABUF ops for exporters */
/*********************************************/
-struct vb2_dc_attachment {
- struct sg_table sgt;
- enum dma_data_direction dir;
-};
-
static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
struct dma_buf_attachment *dbuf_attach)
{
@@ -330,17 +325,13 @@ static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
struct dma_buf_attachment *db_attach)
{
- struct vb2_dc_attachment *attach = db_attach->priv;
- struct sg_table *sgt;
+ struct sg_table *sgt = db_attach->priv;
- if (!attach)
+ if (!sgt)
return;
- sgt = &attach->sgt;
-
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->nents, attach->dir);
sg_free_table(sgt);
- kfree(attach);
+ kfree(sgt);
db_attach->priv = NULL;
}
@@ -349,26 +340,22 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
{
struct dma_buf *dbuf = db_attach->dmabuf;
struct vb2_dc_buf *buf = dbuf->priv;
- struct vb2_dc_attachment *attach = db_attach->priv;
- struct sg_table *sgt;
+ struct sg_table *sgt = db_attach->priv;
struct scatterlist *rd, *wr;
int i, ret;
/* return previously mapped sg table */
- if (attach)
- return &attach->sgt;
+ if (sgt)
+ return sgt;
- attach = kzalloc(sizeof *attach, GFP_KERNEL);
- if (!attach)
+ sgt = kzalloc(sizeof *sgt, GFP_KERNEL);
+ if (!sgt)
return ERR_PTR(-ENOMEM);
- sgt = &attach->sgt;
- attach->dir = dir;
-
/* copying the buf->base_sgt to attachment */
ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
if (ret) {
- kfree(attach);
+ kfree(sgt);
return ERR_PTR(-ENOMEM);
}
@@ -380,16 +367,7 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
wr = sg_next(wr);
}
- /* mapping new sglist to the client */
- ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
- if (ret <= 0) {
- printk(KERN_ERR "failed to map scatterlist\n");
- sg_free_table(sgt);
- kfree(attach);
- return ERR_PTR(-EIO);
- }
-
- db_attach->priv = attach;
+ db_attach->priv = sgt;
return sgt;
}
@@ -623,7 +601,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
struct vb2_dc_buf *buf = mem_priv;
struct sg_table *sgt;
unsigned long contig_size;
- int ret = 0;
+ int ret = -EFAULT;
if (WARN_ON(!buf->db_attach)) {
printk(KERN_ERR "trying to pin a non attached buffer\n");
@@ -642,12 +620,20 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return -EINVAL;
}
+ /* mapping new sglist to the client */
+ sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+ buf->dma_dir);
+ if (sgt->nents <= 0) {
+ printk(KERN_ERR "failed to map scatterlist\n");
+ goto fail_map_attachment;
+ }
+
/* checking if dmabuf is big enough to store contiguous chunk */
contig_size = vb2_dc_get_contiguous_size(sgt);
if (contig_size < buf->size) {
- printk(KERN_ERR "contiguous chunk of dmabuf is too small\n");
- ret = -EFAULT;
- goto fail_map;
+ printk(KERN_ERR "contiguous chunk of dmabuf is too small "
+ "%lu/%lu bytes\n", contig_size, buf->size);
+ goto fail_map_sg;
}
buf->dma_addr = sg_dma_address(sgt->sgl);
@@ -655,7 +641,10 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
return 0;
-fail_map:
+fail_map_sg:
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+
+fail_map_attachment:
dma_buf_unmap_attachment(buf->db_attach, sgt);
return ret;
@@ -676,6 +665,7 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv)
return;
}
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
dma_buf_unmap_attachment(buf->db_attach, sgt);
buf->dma_addr = 0;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 8/9] v4l: fimc: integrate capture i-face with dmabuf
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (6 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 7/9] v4l: vb2-dma-contig: change map/unmap behaviour Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 9/9] v4l: s5p-tv: mixer: integrate " Tomasz Stanislawski
2012-03-20 15:15 ` [RFCv2 PATCH 0/9] Integration of videobuf2 " Semwal, Sumit
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/Kconfig | 1 +
drivers/media/video/s5p-fimc/fimc-capture.c | 11 ++++++++++-
2 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 9495b6a..c9963f0 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1099,6 +1099,7 @@ config VIDEO_SAMSUNG_S5P_FIMC
VIDEO_V4L2_SUBDEV_API && EXPERIMENTAL
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
+ select DMA_SHARED_BUFFER
---help---
This is a v4l2 driver for Samsung S5P and EXYNOS4 camera
host interface and video postprocessor.
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index a9e9653..7ecc36b 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -1011,6 +1011,14 @@ static int fimc_cap_qbuf(struct file *file, void *priv,
return vb2_qbuf(&fimc->vid_cap.vbq, buf);
}
+static int fimc_cap_expbuf(struct file *file, void *priv,
+ struct v4l2_exportbuffer *eb)
+{
+ struct fimc_dev *fimc = video_drvdata(file);
+
+ return vb2_expbuf(&fimc->vid_cap.vbq, eb);
+}
+
static int fimc_cap_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
@@ -1081,6 +1089,7 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
.vidioc_qbuf = fimc_cap_qbuf,
.vidioc_dqbuf = fimc_cap_dqbuf,
+ .vidioc_expbuf = fimc_cap_expbuf,
.vidioc_streamon = fimc_cap_streamon,
.vidioc_streamoff = fimc_cap_streamoff,
@@ -1463,7 +1472,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
q = &fimc->vid_cap.vbq;
memset(q, 0, sizeof(*q));
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- q->io_modes = VB2_MMAP | VB2_USERPTR;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
q->drv_priv = fimc->vid_cap.ctx;
q->ops = &fimc_capture_qops;
q->mem_ops = &vb2_dma_contig_memops;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [RFCv2 PATCH 9/9] v4l: s5p-tv: mixer: integrate with dmabuf
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (7 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 8/9] v4l: fimc: integrate capture i-face with dmabuf Tomasz Stanislawski
@ 2012-03-06 11:38 ` Tomasz Stanislawski
2012-03-20 15:15 ` [RFCv2 PATCH 0/9] Integration of videobuf2 " Semwal, Sumit
9 siblings, 0 replies; 13+ messages in thread
From: Tomasz Stanislawski @ 2012-03-06 11:38 UTC (permalink / raw)
To: linux-media
Cc: m.szyprowski, t.stanislaws, kyungmin.park, hverkuil,
laurent.pinchart, sumit.semwal, daeinki
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/s5p-tv/Kconfig | 1 +
drivers/media/video/s5p-tv/mixer_video.c | 12 +++++++++++-
2 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
index f248b28..2e80126 100644
--- a/drivers/media/video/s5p-tv/Kconfig
+++ b/drivers/media/video/s5p-tv/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_SAMSUNG_S5P_TV
bool "Samsung TV driver for S5P platform (experimental)"
depends on PLAT_S5P && PM_RUNTIME
depends on EXPERIMENTAL
+ select DMA_SHARED_BUFFER
default n
---help---
Say Y here to enable selecting the TV output devices for
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index f7ca5cc..f08edbf 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -697,6 +697,15 @@ static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
}
+static int mxr_expbuf(struct file *file, void *priv,
+ struct v4l2_exportbuffer *eb)
+{
+ struct mxr_layer *layer = video_drvdata(file);
+
+ mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+ return vb2_expbuf(&layer->vb_queue, eb);
+}
+
static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct mxr_layer *layer = video_drvdata(file);
@@ -724,6 +733,7 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
.vidioc_querybuf = mxr_querybuf,
.vidioc_qbuf = mxr_qbuf,
.vidioc_dqbuf = mxr_dqbuf,
+ .vidioc_expbuf = mxr_expbuf,
/* Streaming control */
.vidioc_streamon = mxr_streamon,
.vidioc_streamoff = mxr_streamoff,
@@ -1074,7 +1084,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
layer->vb_queue = (struct vb2_queue) {
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
- .io_modes = VB2_MMAP | VB2_USERPTR,
+ .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF,
.drv_priv = layer,
.buf_struct_size = sizeof(struct mxr_buffer),
.ops = &mxr_video_qops,
--
1.7.5.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support
2012-03-06 11:38 ` [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support Tomasz Stanislawski
@ 2012-03-20 15:04 ` Semwal, Sumit
0 siblings, 0 replies; 13+ messages in thread
From: Semwal, Sumit @ 2012-03-20 15:04 UTC (permalink / raw)
To: Tomasz Stanislawski
Cc: linux-media, m.szyprowski, kyungmin.park, hverkuil,
laurent.pinchart, daeinki
On Tue, Mar 6, 2012 at 5:08 PM, Tomasz Stanislawski
<t.stanislaws@samsung.com> wrote:
> This patch contains fixes to DMABUF support in vb2-core.
> - fixes number of arguments of call_memop macro
> - fixes setup of plane length
> - fixes handling of error pointers
>
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Sumit Semwal <sumit.semwal@linaro.org>
> ---
> drivers/media/video/videobuf2-core.c | 24 +++++++++++-------------
> include/media/videobuf2-core.h | 6 +++---
> 2 files changed, 14 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
> index 951cb56..e7df560 100644
> --- a/drivers/media/video/videobuf2-core.c
> +++ b/drivers/media/video/videobuf2-core.c
> @@ -118,7 +118,7 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
> void *mem_priv = vb->planes[plane].mem_priv;
>
> if (mem_priv) {
> - call_memop(q, plane, detach_dmabuf, mem_priv);
> + call_memop(q, detach_dmabuf, mem_priv);
> dma_buf_put(vb->planes[plane].dbuf);
> vb->planes[plane].dbuf = NULL;
> vb->planes[plane].mem_priv = NULL;
> @@ -905,6 +905,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
> }
> if (b->memory == V4L2_MEMORY_DMABUF) {
> for (plane = 0; plane < vb->num_planes; ++plane) {
> + v4l2_planes[plane].bytesused =
> + b->m.planes[plane].bytesused;
> v4l2_planes[plane].m.fd = b->m.planes[plane].m.fd;
> }
> }
> @@ -1052,17 +1054,13 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> if (IS_ERR_OR_NULL(dbuf)) {
> dprintk(1, "qbuf: invalid dmabuf fd for "
> "plane %d\n", plane);
> - ret = PTR_ERR(dbuf);
> + ret = -EINVAL;
> goto err;
> }
>
> - /* this doesn't get filled in until __fill_vb2_buffer(),
> - * since it isn't known until after dma_buf_get()..
> - */
> - planes[plane].length = dbuf->size;
> -
> /* Skip the plane if already verified */
> if (dbuf == vb->planes[plane].dbuf) {
> + planes[plane].length = dbuf->size;
> dma_buf_put(dbuf);
> continue;
> }
> @@ -1072,7 +1070,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>
> /* Release previously acquired memory if present */
> if (vb->planes[plane].mem_priv) {
> - call_memop(q, plane, detach_dmabuf,
> + call_memop(q, detach_dmabuf,
> vb->planes[plane].mem_priv);
> dma_buf_put(vb->planes[plane].dbuf);
> }
> @@ -1080,8 +1078,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> vb->planes[plane].mem_priv = NULL;
>
> /* Acquire each plane's memory */
> - mem_priv = q->mem_ops->attach_dmabuf(
> - q->alloc_ctx[plane], dbuf);
> + mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane],
> + dbuf, q->plane_sizes[plane], write);
> if (IS_ERR(mem_priv)) {
> dprintk(1, "qbuf: failed acquiring dmabuf "
> "memory for plane %d\n", plane);
> @@ -1089,6 +1087,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> goto err;
> }
>
> + planes[plane].length = dbuf->size;
> vb->planes[plane].dbuf = dbuf;
> vb->planes[plane].mem_priv = mem_priv;
> }
> @@ -1098,8 +1097,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> * the buffer(s)..
> */
> for (plane = 0; plane < vb->num_planes; ++plane) {
> - ret = q->mem_ops->map_dmabuf(
> - vb->planes[plane].mem_priv, write);
> + ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv);
> if (ret) {
> dprintk(1, "qbuf: failed mapping dmabuf "
> "memory for plane %d\n", plane);
> @@ -1527,7 +1525,7 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> */
> if (q->memory == V4L2_MEMORY_DMABUF)
> for (plane = 0; plane < vb->num_planes; ++plane)
> - call_memop(q, plane, unmap_dmabuf,
> + call_memop(q, unmap_dmabuf,
> vb->planes[plane].mem_priv);
>
> switch (vb->state) {
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index d8b8171..412c6a4 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -88,10 +88,10 @@ struct vb2_mem_ops {
> * in the vb2 core, and vb2_mem_ops really just need to get/put the
> * sglist (and make sure that the sglist fits it's needs..)
> */
> - void *(*attach_dmabuf)(void *alloc_ctx,
> - struct dma_buf *dbuf);
> + void *(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
> + unsigned long size, int write);
> void (*detach_dmabuf)(void *buf_priv);
> - int (*map_dmabuf)(void *buf_priv, int write);
> + int (*map_dmabuf)(void *buf_priv);
> void (*unmap_dmabuf)(void *buf_priv);
>
> void *(*vaddr)(void *buf_priv);
> --
> 1.7.5.4
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
` (8 preceding siblings ...)
2012-03-06 11:38 ` [RFCv2 PATCH 9/9] v4l: s5p-tv: mixer: integrate " Tomasz Stanislawski
@ 2012-03-20 15:15 ` Semwal, Sumit
2012-03-22 11:27 ` Laurent Pinchart
9 siblings, 1 reply; 13+ messages in thread
From: Semwal, Sumit @ 2012-03-20 15:15 UTC (permalink / raw)
To: Tomasz Stanislawski
Cc: linux-media, m.szyprowski, kyungmin.park, hverkuil,
laurent.pinchart, daeinki
Hi Tomasz,
On Tue, Mar 6, 2012 at 5:08 PM, Tomasz Stanislawski
<t.stanislaws@samsung.com> wrote:
> Hello everyone,
> This patchset is an incremental patch to patchset created by Sumit Semwal [1].
> The patches are dedicated to help find a better solution for support of buffer
> sharing by V4L2 API. It is expected to start discussion on the final
> installment for dma-buf in vb2-dma-contig allocator. Current version of the
> patches contain little documentation. It is going to be fixed after achieving
> consensus about design for buffer exporting. Moreover the API between vb2-core
> and the allocator should be revised.
I like your approach in general quite a bit.
May I request you, though, to maybe split it over into two portions -
the preparation patches, and the exporter portion. This would help as
the exporter portion is quite dependent on dma_get_pages and
dma-mapping patches. (Maybe also indirectly on DRM prime?)
With that split, we could try to target the preparation patches for
3.4 while we continue to debate on the exporter patches? I just saw
the dma-mapping pull request from Marek, so the dependencies might
become available soon.
If you agree, then I can post the patch version of my 'v4l2 as dma-buf
user' patches, [except the patch that you've included in this series]
so we can try to hit 3.4 merge window.
>
<snip>
Best regards,
~Sumit.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf
2012-03-20 15:15 ` [RFCv2 PATCH 0/9] Integration of videobuf2 " Semwal, Sumit
@ 2012-03-22 11:27 ` Laurent Pinchart
0 siblings, 0 replies; 13+ messages in thread
From: Laurent Pinchart @ 2012-03-22 11:27 UTC (permalink / raw)
To: Semwal, Sumit
Cc: Tomasz Stanislawski, linux-media, m.szyprowski, kyungmin.park,
hverkuil, daeinki
Hi Sumit,
On Tuesday 20 March 2012 20:45:00 Semwal, Sumit wrote:
> On Tue, Mar 6, 2012 at 5:08 PM, Tomasz Stanislawski wrote:
> > Hello everyone,
> > This patchset is an incremental patch to patchset created by Sumit Semwal
> > [1]. The patches are dedicated to help find a better solution for support
> > of buffer sharing by V4L2 API. It is expected to start discussion on the
> > final installment for dma-buf in vb2-dma-contig allocator. Current
> > version of the patches contain little documentation. It is going to be
> > fixed after achieving consensus about design for buffer exporting.
> > Moreover the API between vb2-core and the allocator should be revised.
>
> I like your approach in general quite a bit.
>
> May I request you, though, to maybe split it over into two portions -
> the preparation patches, and the exporter portion. This would help as
> the exporter portion is quite dependent on dma_get_pages and
> dma-mapping patches. (Maybe also indirectly on DRM prime?)
>
> With that split, we could try to target the preparation patches for
> 3.4 while we continue to debate on the exporter patches? I just saw
> the dma-mapping pull request from Marek, so the dependencies might
> become available soon.
>
> If you agree, then I can post the patch version of my 'v4l2 as dma-buf
> user' patches, [except the patch that you've included in this series]
> so we can try to hit 3.4 merge window.
I've raised a couple of questions regarding the first patch, I'm afraid we
will likely miss 3.4 :-/ If you consider important to get the patches in 3.4 I
can try working with Tomasz to fix them ASAP.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-03-22 11:26 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-06 11:38 [RFCv2 PATCH 0/9] Integration of videobuf2 with dmabuf Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 1/9] v4l: vb2: fixes for DMABUF support Tomasz Stanislawski
2012-03-20 15:04 ` Semwal, Sumit
2012-03-06 11:38 ` [RFCv2 PATCH 2/9] v4l: vb2-dma-contig: update and code refactoring Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 3/9] v4l: vb2: Add dma-contig allocator as dma_buf user Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 4/9] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 5/9] v4l: vb2: " Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 6/9] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 7/9] v4l: vb2-dma-contig: change map/unmap behaviour Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 8/9] v4l: fimc: integrate capture i-face with dmabuf Tomasz Stanislawski
2012-03-06 11:38 ` [RFCv2 PATCH 9/9] v4l: s5p-tv: mixer: integrate " Tomasz Stanislawski
2012-03-20 15:15 ` [RFCv2 PATCH 0/9] Integration of videobuf2 " Semwal, Sumit
2012-03-22 11:27 ` Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).