forked from Minki/linux
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:
parent
37111039c9
commit
0b62b73778
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user