Skip to content

Commit 098e5ed

Browse files
Hans Verkuiltorvalds
authored andcommitted
media: videobuf2-core: take mmap_lock in vb2_get_unmapped_area()
While vb2_mmap took the mmap_lock mutex, vb2_get_unmapped_area didn't. Add this. Also take this opportunity to move the 'q->memory != VB2_MEMORY_MMAP' check and vb2_fileio_is_active() check into __find_plane_by_offset() so both vb2_mmap and vb2_get_unmapped_area do the same checks. Since q->memory is checked while mmap_lock is held, also take that lock in reqbufs and create_bufs when it is set, and set it back to MEMORY_UNKNOWN on error. Fixes: f035eb4 ("[media] videobuf2: fix lockdep warning") Signed-off-by: Hans Verkuil <[email protected]> Acked-by: Tomasz Figa <[email protected]> Reviewed-by: Ricardo Ribalda <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 8ed710d commit 098e5ed

File tree

1 file changed

+73
-29
lines changed

1 file changed

+73
-29
lines changed

drivers/media/common/videobuf2/videobuf2-core.c

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,13 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
813813
num_buffers = max_t(unsigned int, *count, q->min_buffers_needed);
814814
num_buffers = min_t(unsigned int, num_buffers, VB2_MAX_FRAME);
815815
memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
816+
/*
817+
* Set this now to ensure that drivers see the correct q->memory value
818+
* in the queue_setup op.
819+
*/
820+
mutex_lock(&q->mmap_lock);
816821
q->memory = memory;
822+
mutex_unlock(&q->mmap_lock);
817823
set_queue_coherency(q, non_coherent_mem);
818824

819825
/*
@@ -823,22 +829,27 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
823829
ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
824830
plane_sizes, q->alloc_devs);
825831
if (ret)
826-
return ret;
832+
goto error;
827833

828834
/* Check that driver has set sane values */
829-
if (WARN_ON(!num_planes))
830-
return -EINVAL;
835+
if (WARN_ON(!num_planes)) {
836+
ret = -EINVAL;
837+
goto error;
838+
}
831839

832840
for (i = 0; i < num_planes; i++)
833-
if (WARN_ON(!plane_sizes[i]))
834-
return -EINVAL;
841+
if (WARN_ON(!plane_sizes[i])) {
842+
ret = -EINVAL;
843+
goto error;
844+
}
835845

836846
/* Finally, allocate buffers and video memory */
837847
allocated_buffers =
838848
__vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes);
839849
if (allocated_buffers == 0) {
840850
dprintk(q, 1, "memory allocation failed\n");
841-
return -ENOMEM;
851+
ret = -ENOMEM;
852+
goto error;
842853
}
843854

844855
/*
@@ -879,7 +890,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
879890
if (ret < 0) {
880891
/*
881892
* Note: __vb2_queue_free() will subtract 'allocated_buffers'
882-
* from q->num_buffers.
893+
* from q->num_buffers and it will reset q->memory to
894+
* VB2_MEMORY_UNKNOWN.
883895
*/
884896
__vb2_queue_free(q, allocated_buffers);
885897
mutex_unlock(&q->mmap_lock);
@@ -895,6 +907,12 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
895907
q->waiting_for_buffers = !q->is_output;
896908

897909
return 0;
910+
911+
error:
912+
mutex_lock(&q->mmap_lock);
913+
q->memory = VB2_MEMORY_UNKNOWN;
914+
mutex_unlock(&q->mmap_lock);
915+
return ret;
898916
}
899917
EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
900918

@@ -906,20 +924,27 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
906924
unsigned int num_planes = 0, num_buffers, allocated_buffers;
907925
unsigned plane_sizes[VB2_MAX_PLANES] = { };
908926
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT;
927+
bool no_previous_buffers = !q->num_buffers;
909928
int ret;
910929

911930
if (q->num_buffers == VB2_MAX_FRAME) {
912931
dprintk(q, 1, "maximum number of buffers already allocated\n");
913932
return -ENOBUFS;
914933
}
915934

916-
if (!q->num_buffers) {
935+
if (no_previous_buffers) {
917936
if (q->waiting_in_dqbuf && *count) {
918937
dprintk(q, 1, "another dup()ped fd is waiting for a buffer\n");
919938
return -EBUSY;
920939
}
921940
memset(q->alloc_devs, 0, sizeof(q->alloc_devs));
941+
/*
942+
* Set this now to ensure that drivers see the correct q->memory
943+
* value in the queue_setup op.
944+
*/
945+
mutex_lock(&q->mmap_lock);
922946
q->memory = memory;
947+
mutex_unlock(&q->mmap_lock);
923948
q->waiting_for_buffers = !q->is_output;
924949
set_queue_coherency(q, non_coherent_mem);
925950
} else {
@@ -945,14 +970,15 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
945970
ret = call_qop(q, queue_setup, q, &num_buffers,
946971
&num_planes, plane_sizes, q->alloc_devs);
947972
if (ret)
948-
return ret;
973+
goto error;
949974

950975
/* Finally, allocate buffers and video memory */
951976
allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
952977
num_planes, plane_sizes);
953978
if (allocated_buffers == 0) {
954979
dprintk(q, 1, "memory allocation failed\n");
955-
return -ENOMEM;
980+
ret = -ENOMEM;
981+
goto error;
956982
}
957983

958984
/*
@@ -983,7 +1009,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
9831009
if (ret < 0) {
9841010
/*
9851011
* Note: __vb2_queue_free() will subtract 'allocated_buffers'
986-
* from q->num_buffers.
1012+
* from q->num_buffers and it will reset q->memory to
1013+
* VB2_MEMORY_UNKNOWN.
9871014
*/
9881015
__vb2_queue_free(q, allocated_buffers);
9891016
mutex_unlock(&q->mmap_lock);
@@ -998,6 +1025,14 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
9981025
*count = allocated_buffers;
9991026

10001027
return 0;
1028+
1029+
error:
1030+
if (no_previous_buffers) {
1031+
mutex_lock(&q->mmap_lock);
1032+
q->memory = VB2_MEMORY_UNKNOWN;
1033+
mutex_unlock(&q->mmap_lock);
1034+
}
1035+
return ret;
10011036
}
10021037
EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
10031038

@@ -2164,6 +2199,22 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
21642199
struct vb2_buffer *vb;
21652200
unsigned int buffer, plane;
21662201

2202+
/*
2203+
* Sanity checks to ensure the lock is held, MEMORY_MMAP is
2204+
* used and fileio isn't active.
2205+
*/
2206+
lockdep_assert_held(&q->mmap_lock);
2207+
2208+
if (q->memory != VB2_MEMORY_MMAP) {
2209+
dprintk(q, 1, "queue is not currently set up for mmap\n");
2210+
return -EINVAL;
2211+
}
2212+
2213+
if (vb2_fileio_is_active(q)) {
2214+
dprintk(q, 1, "file io in progress\n");
2215+
return -EBUSY;
2216+
}
2217+
21672218
/*
21682219
* Go over all buffers and their planes, comparing the given offset
21692220
* with an offset assigned to each plane. If a match is found,
@@ -2265,11 +2316,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
22652316
int ret;
22662317
unsigned long length;
22672318

2268-
if (q->memory != VB2_MEMORY_MMAP) {
2269-
dprintk(q, 1, "queue is not currently set up for mmap\n");
2270-
return -EINVAL;
2271-
}
2272-
22732319
/*
22742320
* Check memory area access mode.
22752321
*/
@@ -2291,14 +2337,9 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
22912337

22922338
mutex_lock(&q->mmap_lock);
22932339

2294-
if (vb2_fileio_is_active(q)) {
2295-
dprintk(q, 1, "mmap: file io in progress\n");
2296-
ret = -EBUSY;
2297-
goto unlock;
2298-
}
2299-
23002340
/*
2301-
* Find the plane corresponding to the offset passed by userspace.
2341+
* Find the plane corresponding to the offset passed by userspace. This
2342+
* will return an error if not MEMORY_MMAP or file I/O is in progress.
23022343
*/
23032344
ret = __find_plane_by_offset(q, off, &buffer, &plane);
23042345
if (ret)
@@ -2351,22 +2392,25 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
23512392
void *vaddr;
23522393
int ret;
23532394

2354-
if (q->memory != VB2_MEMORY_MMAP) {
2355-
dprintk(q, 1, "queue is not currently set up for mmap\n");
2356-
return -EINVAL;
2357-
}
2395+
mutex_lock(&q->mmap_lock);
23582396

23592397
/*
2360-
* Find the plane corresponding to the offset passed by userspace.
2398+
* Find the plane corresponding to the offset passed by userspace. This
2399+
* will return an error if not MEMORY_MMAP or file I/O is in progress.
23612400
*/
23622401
ret = __find_plane_by_offset(q, off, &buffer, &plane);
23632402
if (ret)
2364-
return ret;
2403+
goto unlock;
23652404

23662405
vb = q->bufs[buffer];
23672406

23682407
vaddr = vb2_plane_vaddr(vb, plane);
2408+
mutex_unlock(&q->mmap_lock);
23692409
return vaddr ? (unsigned long)vaddr : -EINVAL;
2410+
2411+
unlock:
2412+
mutex_unlock(&q->mmap_lock);
2413+
return ret;
23702414
}
23712415
EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
23722416
#endif

0 commit comments

Comments
 (0)