Commit 0b62b737 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 37111039
...@@ -1123,15 +1123,29 @@ EXPORT_SYMBOL_GPL(videobuf_poll_stream); ...@@ -1123,15 +1123,29 @@ EXPORT_SYMBOL_GPL(videobuf_poll_stream);
int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) 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); 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); 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); mutex_unlock(&q->vb_lock);
return retval; return rc;
} }
EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
......
...@@ -264,51 +264,33 @@ static int __videobuf_iolock(struct videobuf_queue *q, ...@@ -264,51 +264,33 @@ static int __videobuf_iolock(struct videobuf_queue *q,
} }
static int __videobuf_mmap_mapper(struct videobuf_queue *q, static int __videobuf_mmap_mapper(struct videobuf_queue *q,
struct videobuf_buffer *buf,
struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
struct videobuf_dma_contig_memory *mem; struct videobuf_dma_contig_memory *mem;
struct videobuf_mapping *map; struct videobuf_mapping *map;
unsigned int first;
int retval; int retval;
unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long size;
dev_dbg(q->dev, "%s\n", __func__); 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 */ /* create mapping + update buffer list */
map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
q->bufs[first]->map = map; buf->map = map;
map->start = vma->vm_start; map->start = vma->vm_start;
map->end = vma->vm_end; map->end = vma->vm_end;
map->q = q; 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); BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_DC_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->vaddr = dma_alloc_coherent(q->dev, mem->size,
&mem->dma_handle, GFP_KERNEL); &mem->dma_handle, GFP_KERNEL);
if (!mem->vaddr) { if (!mem->vaddr) {
...@@ -341,8 +323,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, ...@@ -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", dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
map, q, vma->vm_start, vma->vm_end, map, q, vma->vm_start, vma->vm_end,
(long int) q->bufs[first]->bsize, (long int)buf->bsize,
vma->vm_pgoff, first); vma->vm_pgoff, buf->i);
videobuf_vm_open(vma); videobuf_vm_open(vma);
......
...@@ -549,22 +549,15 @@ static int __videobuf_sync(struct videobuf_queue *q, ...@@ -549,22 +549,15 @@ static int __videobuf_sync(struct videobuf_queue *q,
} }
static int __videobuf_mmap_mapper(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; struct videobuf_mapping *map;
unsigned int first, last, size, i; unsigned int first, last, size, i;
int retval; int retval;
retval = -EINVAL; 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 /* This function maintains backwards compatibility with V4L1 and will
* map more than one buffer if the vma length is equal to the combined * 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, ...@@ -574,44 +567,48 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
* TODO: Allow drivers to specify if they support this mode * 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 */ /* look for first buffer to map */
for (first = 0; first < VIDEO_MAX_FRAME; first++) { for (first = 0; first < VIDEO_MAX_FRAME; first++) {
if (NULL == q->bufs[first]) if (buf == q->bufs[first]) {
continue; size = PAGE_ALIGN(q->bufs[first]->bsize);
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))
break; break;
}
} }
/* paranoia, should never happen since buf is always valid. */
if (VIDEO_MAX_FRAME == first) { if (VIDEO_MAX_FRAME == first) {
dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n", dprintk(1, "mmap app bug: offset invalid [offset=0x%lx]\n",
(vma->vm_pgoff << PAGE_SHIFT)); (vma->vm_pgoff << PAGE_SHIFT));
goto done; goto done;
} }
/* look for last buffer to map */ last = first;
for (size = 0, last = first; last < VIDEO_MAX_FRAME; last++) { #ifdef CONFIG_VIDEO_V4L1_COMPAT
if (NULL == q->bufs[last]) if (size != (vma->vm_end - vma->vm_start)) {
continue; /* look for last buffer to map */
if (V4L2_MEMORY_MMAP != q->bufs[last]->memory) for (last = first + 1; last < VIDEO_MAX_FRAME; last++) {
continue; if (NULL == q->bufs[last])
if (q->bufs[last]->map) { continue;
retval = -EBUSY; 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; 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 */ /* create mapping + update buffer list */
retval = -ENOMEM; retval = -ENOMEM;
......
...@@ -236,47 +236,28 @@ static int __videobuf_sync(struct videobuf_queue *q, ...@@ -236,47 +236,28 @@ static int __videobuf_sync(struct videobuf_queue *q,
} }
static int __videobuf_mmap_mapper(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_vmalloc_memory *mem;
struct videobuf_mapping *map; struct videobuf_mapping *map;
unsigned int first;
int retval, pages; int retval, pages;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
dprintk(1, "%s\n", __func__); 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 */ /* create mapping + update buffer list */
map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL); map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
if (NULL == map) if (NULL == map)
return -ENOMEM; return -ENOMEM;
q->bufs[first]->map = map; buf->map = map;
map->start = vma->vm_start; map->start = vma->vm_start;
map->end = vma->vm_end; map->end = vma->vm_end;
map->q = q; 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); BUG_ON(!mem);
MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM); MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
...@@ -302,8 +283,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, ...@@ -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", dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
map, q, vma->vm_start, vma->vm_end, map, q, vma->vm_start, vma->vm_end,
(long int) q->bufs[first]->bsize, (long int)buf->bsize,
vma->vm_pgoff, first); vma->vm_pgoff, buf->i);
videobuf_vm_open(vma); videobuf_vm_open(vma);
......
...@@ -135,7 +135,8 @@ struct videobuf_qtype_ops { ...@@ -135,7 +135,8 @@ struct videobuf_qtype_ops {
int (*sync) (struct videobuf_queue *q, int (*sync) (struct videobuf_queue *q,
struct videobuf_buffer *buf); struct videobuf_buffer *buf);
int (*mmap_mapper) (struct videobuf_queue *q, int (*mmap_mapper) (struct videobuf_queue *q,
struct vm_area_struct *vma); struct videobuf_buffer *buf,
struct vm_area_struct *vma);
}; };
struct videobuf_queue { struct videobuf_queue {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment