@@ -294,12 +294,12 @@ struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
294
294
if (!vc4_state )
295
295
return NULL ;
296
296
297
- memset (& vc4_state -> lbm , 0 , sizeof (vc4_state -> lbm ));
298
-
299
297
for (i = 0 ; i < DRM_FORMAT_MAX_PLANES ; i ++ ) {
300
298
if (vc4_state -> upm_handle [i ])
301
299
refcount_inc (& hvs -> upm_refcounts [vc4_state -> upm_handle [i ]].refcount );
302
300
}
301
+ if (vc4_state -> lbm_handle )
302
+ refcount_inc (& hvs -> lbm_refcounts [vc4_state -> lbm_handle ].refcount );
303
303
304
304
vc4_state -> dlist_initialized = 0 ;
305
305
@@ -319,6 +319,21 @@ struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
319
319
return & vc4_state -> base ;
320
320
}
321
321
322
+ static void vc4_plane_release_lbm_ida (struct vc4_hvs * hvs , unsigned int lbm_handle )
323
+ {
324
+ struct vc4_lbm_refcounts * refcount = & hvs -> lbm_refcounts [lbm_handle ];
325
+ unsigned long irqflags ;
326
+
327
+ spin_lock_irqsave (& hvs -> mm_lock , irqflags );
328
+ drm_mm_remove_node (& refcount -> lbm );
329
+ spin_unlock_irqrestore (& hvs -> mm_lock , irqflags );
330
+ refcount -> lbm .start = 0 ;
331
+ refcount -> lbm .size = 0 ;
332
+ refcount -> size = 0 ;
333
+
334
+ ida_free (& hvs -> lbm_handles , lbm_handle );
335
+ }
336
+
322
337
static void vc4_plane_release_upm_ida (struct vc4_hvs * hvs , unsigned int upm_handle )
323
338
{
324
339
struct vc4_upm_refcounts * refcount = & hvs -> upm_refcounts [upm_handle ];
@@ -342,12 +357,13 @@ void vc4_plane_destroy_state(struct drm_plane *plane,
342
357
struct vc4_plane_state * vc4_state = to_vc4_plane_state (state );
343
358
unsigned int i ;
344
359
345
- if (drm_mm_node_allocated ( & vc4_state -> lbm ) ) {
346
- unsigned long irqflags ;
360
+ if (vc4_state -> lbm_handle ) {
361
+ struct vc4_lbm_refcounts * refcount ;
347
362
348
- spin_lock_irqsave (& hvs -> mm_lock , irqflags );
349
- drm_mm_remove_node (& vc4_state -> lbm );
350
- spin_unlock_irqrestore (& hvs -> mm_lock , irqflags );
363
+ refcount = & hvs -> lbm_refcounts [vc4_state -> lbm_handle ];
364
+
365
+ if (refcount_dec_and_test (& refcount -> refcount ))
366
+ vc4_plane_release_lbm_ida (hvs , vc4_state -> lbm_handle );
351
367
}
352
368
353
369
for (i = 0 ; i < DRM_FORMAT_MAX_PLANES ; i ++ ) {
@@ -939,10 +955,14 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
939
955
{
940
956
struct drm_device * drm = state -> plane -> dev ;
941
957
struct vc4_dev * vc4 = to_vc4_dev (drm );
958
+ struct vc4_hvs * hvs = vc4 -> hvs ;
942
959
struct drm_plane * plane = state -> plane ;
943
960
struct vc4_plane_state * vc4_state = to_vc4_plane_state (state );
961
+ struct vc4_lbm_refcounts * refcount ;
944
962
unsigned long irqflags ;
963
+ int lbm_handle ;
945
964
u32 lbm_size ;
965
+ int ret ;
946
966
947
967
lbm_size = vc4_lbm_size (state );
948
968
if (!lbm_size )
@@ -966,29 +986,71 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
966
986
/* Allocate the LBM memory that the HVS will use for temporary
967
987
* storage due to our scaling/format conversion.
968
988
*/
969
- if (!drm_mm_node_allocated (& vc4_state -> lbm )) {
970
- int ret ;
989
+ lbm_handle = vc4_state -> lbm_handle ;
990
+ if (lbm_handle &&
991
+ hvs -> lbm_refcounts [lbm_handle ].size == lbm_size ) {
992
+ /* Allocation is the same size as the previous user of
993
+ * the plane. Keep the allocation.
994
+ */
995
+ vc4_state -> lbm_handle = lbm_handle ;
996
+ } else {
997
+ if (lbm_handle &&
998
+ refcount_dec_and_test (& hvs -> lbm_refcounts [lbm_handle ].refcount )) {
999
+ vc4_plane_release_lbm_ida (hvs , lbm_handle );
1000
+ vc4_state -> lbm_handle = 0 ;
1001
+ }
1002
+
1003
+ lbm_handle = ida_alloc_range (& hvs -> lbm_handles , 1 ,
1004
+ VC4_NUM_LBM_HANDLES ,
1005
+ GFP_KERNEL );
1006
+ if (lbm_handle < 0 ) {
1007
+ drm_err (drm , "Out of lbm_handles\n" );
1008
+ return lbm_handle ;
1009
+ }
1010
+ vc4_state -> lbm_handle = lbm_handle ;
1011
+
1012
+ refcount = & hvs -> lbm_refcounts [lbm_handle ];
1013
+ refcount_set (& refcount -> refcount , 1 );
1014
+ refcount -> size = lbm_size ;
971
1015
972
- spin_lock_irqsave (& vc4 -> hvs -> mm_lock , irqflags );
1016
+ spin_lock_irqsave (& hvs -> mm_lock , irqflags );
973
1017
ret = drm_mm_insert_node_generic (& vc4 -> hvs -> lbm_mm ,
974
- & vc4_state -> lbm ,
1018
+ & refcount -> lbm ,
975
1019
lbm_size , 1 ,
976
1020
0 , 0 );
977
- spin_unlock_irqrestore (& vc4 -> hvs -> mm_lock , irqflags );
1021
+ spin_unlock_irqrestore (& hvs -> mm_lock , irqflags );
978
1022
979
1023
if (ret ) {
980
1024
drm_err (drm , "Failed to allocate LBM entry: %d\n" , ret );
1025
+ refcount_set (& refcount -> refcount , 0 );
1026
+ ida_free (& hvs -> lbm_handles , lbm_handle );
1027
+ vc4_state -> lbm_handle = 0 ;
981
1028
return ret ;
982
1029
}
983
- } else {
984
- WARN_ON_ONCE (lbm_size != vc4_state -> lbm .size );
985
1030
}
986
1031
987
- vc4_state -> dlist [vc4_state -> lbm_offset ] = vc4_state -> lbm .start ;
1032
+ vc4_state -> dlist [vc4_state -> lbm_offset ] = hvs -> lbm_refcounts [ lbm_handle ]. lbm .start ;
988
1033
989
1034
return 0 ;
990
1035
}
991
1036
1037
+ static void vc4_plane_free_lbm (struct drm_plane_state * state )
1038
+ {
1039
+ struct vc4_plane_state * vc4_state = to_vc4_plane_state (state );
1040
+ struct drm_device * drm = state -> plane -> dev ;
1041
+ struct vc4_dev * vc4 = to_vc4_dev (drm );
1042
+ struct vc4_hvs * hvs = vc4 -> hvs ;
1043
+ unsigned int lbm_handle ;
1044
+
1045
+ lbm_handle = vc4_state -> lbm_handle ;
1046
+ if (!lbm_handle )
1047
+ return ;
1048
+
1049
+ if (refcount_dec_and_test (& hvs -> lbm_refcounts [lbm_handle ].refcount ))
1050
+ vc4_plane_release_lbm_ida (hvs , lbm_handle );
1051
+ vc4_state -> lbm_handle = 0 ;
1052
+ }
1053
+
992
1054
static int vc6_plane_allocate_upm (struct drm_plane_state * state )
993
1055
{
994
1056
const struct drm_format_info * info = state -> fb -> format ;
@@ -2174,9 +2236,10 @@ int vc4_plane_atomic_check(struct drm_plane *plane,
2174
2236
struct drm_plane_state * old_plane_state =
2175
2237
drm_atomic_get_old_plane_state (state , plane );
2176
2238
2177
- if (vc4 -> gen >= VC4_GEN_6_C && old_plane_state &&
2178
- plane_enabled (old_plane_state )) {
2179
- vc6_plane_free_upm (new_plane_state );
2239
+ if (old_plane_state && plane_enabled (old_plane_state )) {
2240
+ if (vc4 -> gen >= VC4_GEN_6_C )
2241
+ vc6_plane_free_upm (new_plane_state );
2242
+ vc4_plane_free_lbm (new_plane_state );
2180
2243
}
2181
2244
return 0 ;
2182
2245
}
0 commit comments