@@ -813,7 +813,13 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
813
813
num_buffers = max_t (unsigned int , * count , q -> min_buffers_needed );
814
814
num_buffers = min_t (unsigned int , num_buffers , VB2_MAX_FRAME );
815
815
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 );
816
821
q -> memory = memory ;
822
+ mutex_unlock (& q -> mmap_lock );
817
823
set_queue_coherency (q , non_coherent_mem );
818
824
819
825
/*
@@ -823,22 +829,27 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
823
829
ret = call_qop (q , queue_setup , q , & num_buffers , & num_planes ,
824
830
plane_sizes , q -> alloc_devs );
825
831
if (ret )
826
- return ret ;
832
+ goto error ;
827
833
828
834
/* 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
+ }
831
839
832
840
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
+ }
835
845
836
846
/* Finally, allocate buffers and video memory */
837
847
allocated_buffers =
838
848
__vb2_queue_alloc (q , memory , num_buffers , num_planes , plane_sizes );
839
849
if (allocated_buffers == 0 ) {
840
850
dprintk (q , 1 , "memory allocation failed\n" );
841
- return - ENOMEM ;
851
+ ret = - ENOMEM ;
852
+ goto error ;
842
853
}
843
854
844
855
/*
@@ -879,7 +890,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
879
890
if (ret < 0 ) {
880
891
/*
881
892
* 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.
883
895
*/
884
896
__vb2_queue_free (q , allocated_buffers );
885
897
mutex_unlock (& q -> mmap_lock );
@@ -895,6 +907,12 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
895
907
q -> waiting_for_buffers = !q -> is_output ;
896
908
897
909
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 ;
898
916
}
899
917
EXPORT_SYMBOL_GPL (vb2_core_reqbufs );
900
918
@@ -906,20 +924,27 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
906
924
unsigned int num_planes = 0 , num_buffers , allocated_buffers ;
907
925
unsigned plane_sizes [VB2_MAX_PLANES ] = { };
908
926
bool non_coherent_mem = flags & V4L2_MEMORY_FLAG_NON_COHERENT ;
927
+ bool no_previous_buffers = !q -> num_buffers ;
909
928
int ret ;
910
929
911
930
if (q -> num_buffers == VB2_MAX_FRAME ) {
912
931
dprintk (q , 1 , "maximum number of buffers already allocated\n" );
913
932
return - ENOBUFS ;
914
933
}
915
934
916
- if (! q -> num_buffers ) {
935
+ if (no_previous_buffers ) {
917
936
if (q -> waiting_in_dqbuf && * count ) {
918
937
dprintk (q , 1 , "another dup()ped fd is waiting for a buffer\n" );
919
938
return - EBUSY ;
920
939
}
921
940
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 );
922
946
q -> memory = memory ;
947
+ mutex_unlock (& q -> mmap_lock );
923
948
q -> waiting_for_buffers = !q -> is_output ;
924
949
set_queue_coherency (q , non_coherent_mem );
925
950
} else {
@@ -945,14 +970,15 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
945
970
ret = call_qop (q , queue_setup , q , & num_buffers ,
946
971
& num_planes , plane_sizes , q -> alloc_devs );
947
972
if (ret )
948
- return ret ;
973
+ goto error ;
949
974
950
975
/* Finally, allocate buffers and video memory */
951
976
allocated_buffers = __vb2_queue_alloc (q , memory , num_buffers ,
952
977
num_planes , plane_sizes );
953
978
if (allocated_buffers == 0 ) {
954
979
dprintk (q , 1 , "memory allocation failed\n" );
955
- return - ENOMEM ;
980
+ ret = - ENOMEM ;
981
+ goto error ;
956
982
}
957
983
958
984
/*
@@ -983,7 +1009,8 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
983
1009
if (ret < 0 ) {
984
1010
/*
985
1011
* 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.
987
1014
*/
988
1015
__vb2_queue_free (q , allocated_buffers );
989
1016
mutex_unlock (& q -> mmap_lock );
@@ -998,6 +1025,14 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
998
1025
* count = allocated_buffers ;
999
1026
1000
1027
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 ;
1001
1036
}
1002
1037
EXPORT_SYMBOL_GPL (vb2_core_create_bufs );
1003
1038
@@ -2164,6 +2199,22 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
2164
2199
struct vb2_buffer * vb ;
2165
2200
unsigned int buffer , plane ;
2166
2201
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
+
2167
2218
/*
2168
2219
* Go over all buffers and their planes, comparing the given offset
2169
2220
* 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)
2265
2316
int ret ;
2266
2317
unsigned long length ;
2267
2318
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
-
2273
2319
/*
2274
2320
* Check memory area access mode.
2275
2321
*/
@@ -2291,14 +2337,9 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
2291
2337
2292
2338
mutex_lock (& q -> mmap_lock );
2293
2339
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
-
2300
2340
/*
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.
2302
2343
*/
2303
2344
ret = __find_plane_by_offset (q , off , & buffer , & plane );
2304
2345
if (ret )
@@ -2351,22 +2392,25 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
2351
2392
void * vaddr ;
2352
2393
int ret ;
2353
2394
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 );
2358
2396
2359
2397
/*
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.
2361
2400
*/
2362
2401
ret = __find_plane_by_offset (q , off , & buffer , & plane );
2363
2402
if (ret )
2364
- return ret ;
2403
+ goto unlock ;
2365
2404
2366
2405
vb = q -> bufs [buffer ];
2367
2406
2368
2407
vaddr = vb2_plane_vaddr (vb , plane );
2408
+ mutex_unlock (& q -> mmap_lock );
2369
2409
return vaddr ? (unsigned long )vaddr : - EINVAL ;
2410
+
2411
+ unlock :
2412
+ mutex_unlock (& q -> mmap_lock );
2413
+ return ret ;
2370
2414
}
2371
2415
EXPORT_SYMBOL_GPL (vb2_get_unmapped_area );
2372
2416
#endif
0 commit comments