V4L/DVB (13165): videobuf do not force buffer size to be multiple of PAGE_SIZE
authorTuukka Toivonen <tuukka.o.toivonen@nokia.com>
Thu, 23 Jul 2009 13:56:25 +0000 (10:56 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:40:40 +0000 (18:40 -0200)
When the image size (bytesperline*height) is not multiple
of PAGE_SIZE, v4l2 rounded the required buffer size to
be multiple of PAGE_SIZE. This prevented user space
to store images directly into userptr buffers which were
not multiple of PAGE_SIZE. This constraint is removed.

The start address is still assumed to be required
page-aligned, ie., when v4l2 allocates mmap buffers,
the offset between different buffers is page-aligned.

Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/videobuf-core.c
drivers/media/video/videobuf-dma-sg.c

index 8e93c6f25c83ae4cab47bc715712b56ff5aa059a..a96b08d3df5a853c5f5c15fac86f54c70bf6e157 100644 (file)
@@ -360,7 +360,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q,
                q->bufs[i]->bsize  = bsize;
                switch (memory) {
                case V4L2_MEMORY_MMAP:
-                       q->bufs[i]->boff  = bsize * i;
+                       q->bufs[i]->boff = PAGE_ALIGN(bsize) * i;
                        break;
                case V4L2_MEMORY_USERPTR:
                case V4L2_MEMORY_OVERLAY:
@@ -430,9 +430,8 @@ int videobuf_reqbufs(struct videobuf_queue *q,
                count = VIDEO_MAX_FRAME;
        size = 0;
        q->ops->buf_setup(q, &count, &size);
-       size = PAGE_ALIGN(size);
        dprintk(1, "reqbufs: bufs=%d, size=0x%x [%d pages total]\n",
-               count, size, (count*size)>>PAGE_SHIFT);
+               count, size, (count*PAGE_ALIGN(size))>>PAGE_SHIFT);
 
        retval = __videobuf_mmap_setup(q, count, size, req->memory);
        if (retval < 0) {
@@ -1099,7 +1098,7 @@ int videobuf_cgmbuf(struct videobuf_queue *q,
        mbuf->size   = 0;
        for (i = 0; i < mbuf->frames; i++) {
                mbuf->offsets[i]  = q->bufs[i]->boff;
-               mbuf->size       += q->bufs[i]->bsize;
+               mbuf->size       += PAGE_ALIGN(q->bufs[i]->bsize);
        }
 
        return 0;
index 032ebae0134a7190a1c1c3e4e50054eaafee8523..a583d394696e05dcb1a22feaf1bd35f0a8b63f68 100644 (file)
@@ -588,7 +588,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                        retval = -EBUSY;
                        goto done;
                }
-               size += q->bufs[last]->bsize;
+               size += PAGE_ALIGN(q->bufs[last]->bsize);
                if (size == (vma->vm_end - vma->vm_start))
                        break;
        }
@@ -610,7 +610,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
                        continue;
                q->bufs[i]->map   = map;
                q->bufs[i]->baddr = vma->vm_start + size;
-               size += q->bufs[i]->bsize;
+               size += PAGE_ALIGN(q->bufs[i]->bsize);
        }
 
        map->count    = 1;