Prechádzať zdrojové kódy

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>
Hans Verkuil 15 rokov pred
rodič
commit
0b62b73778

+ 17 - 3
drivers/media/video/videobuf-core.c

@@ -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);
 

+ 8 - 26
drivers/media/video/videobuf-dma-contig.c

@@ -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);
 

+ 33 - 36
drivers/media/video/videobuf-dma-sg.c

@@ -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;

+ 7 - 26
drivers/media/video/videobuf-vmalloc.c

@@ -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);
 

+ 2 - 1
include/media/videobuf-core.h

@@ -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 {