V4L/DVB: v4l videobuf: add videobuf_buffer *buf as argument to mmap_mapper

mmap_mapper should operate on a buffer, not on a complete queue. So let
the videobuf-core find the correct buffer instead of duplicating that
code in each mmap_mapper implementation.

The dma-sg implementation has backwards compatibility code for handling
the V4L1_COMPAT layer. This code is now under the v4L1_COMPAT config option.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2010-03-28 09:09:05 -03:00 committed by Mauro Carvalho Chehab
parent 37111039c9
commit 0b62b73778
5 changed files with 67 additions and 92 deletions

View file

@ -1123,15 +1123,29 @@ EXPORT_SYMBOL_GPL(videobuf_poll_stream);
int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma)
{
int retval;
int rc = -EINVAL;
int i;
MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n");
return -EINVAL;
}
mutex_lock(&q->vb_lock);
retval = CALL(q, mmap_mapper, q, vma);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
struct videobuf_buffer *buf = q->bufs[i];
if (buf && buf->memory == V4L2_MEMORY_MMAP &&
buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) {
rc = CALL(q, mmap_mapper, q, buf, vma);
break;
}
}
mutex_unlock(&q->vb_lock);
return retval;
return rc;
}
EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);

View file

@ -264,51 +264,33 @@ static int __videobuf_iolock(struct videobuf_queue *q,
}
static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct videobuf_buffer *buf,
struct vm_area_struct *vma)
{
struct videobuf_dma_contig_memory *mem;
struct videobuf_mapping *map;
unsigned int first;
int retval;
unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long size;
dev_dbg(q->dev, "%s\n", __func__);
if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
return -EINVAL;
/* look for first buffer to map */
for (first = 0; first < VIDEO_MAX_FRAME; first++) {
if (!q->bufs[first])
continue;
if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
continue;
if (q->bufs[first]->boff == offset)
break;
}
if (VIDEO_MAX_FRAME == first) {
dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n",
offset);
return -EINVAL;
}
/* create mapping + update buffer list */
map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
if (!map)
return -ENOMEM;
q->bufs[first]->map = map;
buf->map = map;
map->start = vma->vm_start;
map->end = vma->vm_end;
map->q = q;
q->bufs[first]->baddr = vma->vm_start;
buf->baddr = vma->vm_start;
mem = q->bufs[first]->priv;
mem = buf->priv;
BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
mem->size = PAGE_ALIGN(buf->bsize);
mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
&mem->dma_handle, GFP_KERNEL);
if (!mem->vaddr) {
@ -341,8 +323,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
map, q, vma->vm_start, vma->vm_end,
(long int) q->bufs[first]->bsize,
vma->vm_pgoff, first);
(long int)buf->bsize,
vma->vm_pgoff, buf->i);
videobuf_vm_open(vma);

View file

@ -549,22 +549,15 @@ static int __videobuf_sync(struct videobuf_queue *q,
}
static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct vm_area_struct *vma)
struct videobuf_buffer *buf,
struct vm_area_struct *vma)
{
struct videobuf_dma_sg_memory *mem;
struct videobuf_dma_sg_memory *mem = buf->priv;
struct videobuf_mapping *map;
unsigned int first, last, size, i;
int retval;
retval = -EINVAL;
if (!(vma->vm_flags & VM_WRITE)) {
dprintk(1, "mmap app bug: PROT_WRITE please\n");
goto done;
}
if (!(vma->vm_flags & VM_SHARED)) {
dprintk(1, "mmap app bug: MAP_SHARED please\n");
goto done;
}
/* This function maintains backwards compatibility with V4L1 and will
* map more than one buffer if the vma length is equal to the combined
@ -574,44 +567,48 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
* TODO: Allow drivers to specify if they support this mode
*/
BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
/* look for first buffer to map */
for (first = 0; first < VIDEO_MAX_FRAME; first++) {
if (NULL == q->bufs[first])
continue;
mem = q->bufs[first]->priv;
BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
continue;
if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT))
if (buf == q->bufs[first]) {
size = PAGE_ALIGN(q->bufs[first]->bsize);
break;
}
}
/* paranoia, should never happen since buf is always valid. */
if (VIDEO_MAX_FRAME == first) {
dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n",
(vma->vm_pgoff << PAGE_SHIFT));
(vma->vm_pgoff << PAGE_SHIFT));
goto done;
}
/* look for last buffer to map */
for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) {
if (NULL == q->bufs[last])
continue;
if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
continue;
if (q->bufs[last]->map) {
retval = -EBUSY;
last = first;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
if (size != (vma->vm_end - vma->vm_start)) {
/* look for last buffer to map */
for (last = first + 1; last < VIDEO_MAX_FRAME; last++) {
if (NULL == q->bufs[last])
continue;
if (V4L2_MEMORY_MMAP != q->bufs[last]->memory)
continue;
if (q->bufs[last]->map) {
retval = -EBUSY;
goto done;
}
size += PAGE_ALIGN(q->bufs[last]->bsize);
if (size == (vma->vm_end - vma->vm_start))
break;
}
if (VIDEO_MAX_FRAME == last) {
dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n",
(vma->vm_end - vma->vm_start));
goto done;
}
size += PAGE_ALIGN(q->bufs[last]->bsize);
if (size == (vma->vm_end - vma->vm_start))
break;
}
if (VIDEO_MAX_FRAME == last) {
dprintk(1, "mmap app bug: size invalid [size=0x%lx]\n",
(vma->vm_end - vma->vm_start));
goto done;
}
#endif
/* create mapping + update buffer list */
retval = -ENOMEM;

View file

@ -236,47 +236,28 @@ static int __videobuf_sync(struct videobuf_queue *q,
}
static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct vm_area_struct *vma)
struct videobuf_buffer *buf,
struct vm_area_struct *vma)
{
struct videobuf_vmalloc_memory *mem;
struct videobuf_mapping *map;
unsigned int first;
int retval, pages;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
dprintk(1, "%s\n", __func__);
if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
return -EINVAL;
/* look for first buffer to map */
for (first = 0; first < VIDEO_MAX_FRAME; first++) {
if (NULL == q->bufs[first])
continue;
if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
continue;
if (q->bufs[first]->boff == offset)
break;
}
if (VIDEO_MAX_FRAME == first) {
dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n",
(vma->vm_pgoff << PAGE_SHIFT));
return -EINVAL;
}
/* create mapping + update buffer list */
map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
if (NULL == map)
return -ENOMEM;
q->bufs[first]->map = map;
buf->map = map;
map->start = vma->vm_start;
map->end = vma->vm_end;
map->q = q;
q->bufs[first]->baddr = vma->vm_start;
buf->baddr = vma->vm_start;
mem = q->bufs[first]->priv;
mem = buf->priv;
BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
@ -302,8 +283,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
map, q, vma->vm_start, vma->vm_end,
(long int) q->bufs[first]->bsize,
vma->vm_pgoff, first);
(long int)buf->bsize,
vma->vm_pgoff, buf->i);
videobuf_vm_open(vma);

View file

@ -135,7 +135,8 @@ struct videobuf_qtype_ops {
int (*sync) (struct videobuf_queue *q,
struct videobuf_buffer *buf);
int (*mmap_mapper) (struct videobuf_queue *q,
struct vm_area_struct *vma);
struct videobuf_buffer *buf,
struct vm_area_struct *vma);
};
struct videobuf_queue {