[media] videobuf2: add gfp_flags
authorHans Verkuil <hans.verkuil@cisco.com>
Fri, 1 Mar 2013 18:44:20 +0000 (15:44 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 21 Mar 2013 16:17:51 +0000 (13:17 -0300)
Some drivers have special memory requirements for their buffers, usually
related to DMA (e.g. GFP_DMA or __GFP_DMA32). Make it possible to specify
additional GFP flags for those buffers by adding a gfp_flags field to
vb2_queue.
Note that this field will be replaced in the future with a different
mechanism, but that is still work in progress and we need this feature
now so we won't be able to convert drivers with such requirements to vb2.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Federico Vaga <federico.vaga@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/media/v4l2-core/videobuf2-vmalloc.c
include/media/videobuf2-core.h

index be0448161c60035cccd868dda1cd5937938e9ffd..70827feb87b4904a3c429b2689915abf9171d7a2 100644 (file)
@@ -57,7 +57,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
        /* Allocate memory for all planes in this buffer */
        for (plane = 0; plane < vb->num_planes; ++plane) {
                mem_priv = call_memop(q, alloc, q->alloc_ctx[plane],
-                                     q->plane_sizes[plane]);
+                                     q->plane_sizes[plane], q->gfp_flags);
                if (IS_ERR_OR_NULL(mem_priv))
                        goto free;
 
index 10beaee7f0ae592ae88803d7720d298a20beac0d..ae35d255a43016cc325db28899a2351b83f4d02f 100644 (file)
@@ -152,7 +152,7 @@ static void vb2_dc_put(void *buf_priv)
        kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
        struct vb2_dc_conf *conf = alloc_ctx;
        struct device *dev = conf->dev;
@@ -165,7 +165,8 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
        /* align image size to PAGE_SIZE */
        size = PAGE_ALIGN(size);
 
-       buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
+       buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
+                                               GFP_KERNEL | gfp_flags);
        if (!buf->vaddr) {
                dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
                kfree(buf);
index 25c3b360e1adf1cdfdce19f80c59f847d38f18b4..952776fafe2ca91ccd58c50853a8843f871ed085 100644 (file)
@@ -33,7 +33,7 @@ struct vb2_dma_sg_buf {
 
 static void vb2_dma_sg_put(void *buf_priv);
 
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
        struct vb2_dma_sg_buf *buf;
        int i;
@@ -60,7 +60,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
                goto fail_pages_array_alloc;
 
        for (i = 0; i < buf->sg_desc.num_pages; ++i) {
-               buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
+               buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO |
+                                          __GFP_NOWARN | gfp_flags);
                if (NULL == buf->pages[i])
                        goto fail_pages_alloc;
                sg_set_page(&buf->sg_desc.sglist[i],
index a47fd4f589a14bc9a466eee544a582659e25babd..313d9771b2bc9499e0d02e389b4ad480282fcb79 100644 (file)
@@ -35,11 +35,11 @@ struct vb2_vmalloc_buf {
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 {
        struct vb2_vmalloc_buf *buf;
 
-       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags);
        if (!buf)
                return NULL;
 
index a2d4274507805cbda90b10b0aa653d05cb2c8059..d88a098d1affccf3da0c7fe79d5519a4e5475193 100644 (file)
@@ -27,7 +27,9 @@ struct vb2_fileio_data;
  *             return NULL on failure or a pointer to allocator private,
  *             per-buffer data on success; the returned private structure
  *             will then be passed as buf_priv argument to other ops in this
- *             structure
+ *             structure. Additional gfp_flags to use when allocating the
+ *             are also passed to this operation. These flags are from the
+ *             gfp_flags field of vb2_queue.
  * @put:       inform the allocator that the buffer will no longer be used;
  *             usually will result in the allocator freeing the buffer (if
  *             no other users of this buffer are present); the buf_priv
@@ -79,7 +81,7 @@ struct vb2_fileio_data;
  *                               unmap_dmabuf.
  */
 struct vb2_mem_ops {
-       void            *(*alloc)(void *alloc_ctx, unsigned long size);
+       void            *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
        void            (*put)(void *buf_priv);
        struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
@@ -302,6 +304,9 @@ struct v4l2_fh;
  * @buf_struct_size: size of the driver-specific buffer structure;
  *             "0" indicates the driver doesn't want to use a custom buffer
  *             structure type, so sizeof(struct vb2_buffer) will is used
+ * @gfp_flags: additional gfp flags used when allocating the buffers.
+ *             Typically this is 0, but it may be e.g. GFP_DMA or __GFP_DMA32
+ *             to force the buffer allocation to a specific memory zone.
  *
  * @memory:    current memory type used
  * @bufs:      videobuf buffer structures
@@ -327,6 +332,7 @@ struct vb2_queue {
        void                            *drv_priv;
        unsigned int                    buf_struct_size;
        u32                             timestamp_type;
+       gfp_t                           gfp_flags;
 
 /* private: internal use only */
        enum v4l2_memory                memory;