]> Pileus Git - ~andy/linux/blobdiff - drivers/media/v4l2-core/videobuf2-dma-contig.c
Merge tag 'for-3.8-rc1' of git://gitorious.org/linux-pwm/linux-pwm
[~andy/linux] / drivers / media / v4l2-core / videobuf2-dma-contig.c
index 78c281c55ad7a9e62226b5ad5acaa26d390ebeca..10beaee7f0ae592ae88803d7720d298a20beac0d 100644 (file)
@@ -148,6 +148,7 @@ static void vb2_dc_put(void *buf_priv)
                kfree(buf->sgt_base);
        }
        dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+       put_device(buf->dev);
        kfree(buf);
 }
 
@@ -161,6 +162,9 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
+       /* align image size to PAGE_SIZE */
+       size = PAGE_ALIGN(size);
+
        buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
        if (!buf->vaddr) {
                dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
@@ -168,7 +172,8 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
                return ERR_PTR(-ENOMEM);
        }
 
-       buf->dev = dev;
+       /* Prevent the device from being released while the buffer is used */
+       buf->dev = get_device(dev);
        buf->size = size;
 
        buf->handler.refcount = &buf->refcount;
@@ -489,6 +494,18 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
        struct vm_area_struct *vma;
        struct sg_table *sgt;
        unsigned long contig_size;
+       unsigned long dma_align = dma_get_cache_alignment();
+
+       /* Only cache aligned DMA transfers are reliable */
+       if (!IS_ALIGNED(vaddr | size, dma_align)) {
+               pr_debug("user data must be aligned to %lu bytes\n", dma_align);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!size) {
+               pr_debug("size is zero\n");
+               return ERR_PTR(-EINVAL);
+       }
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)