@@ -389,150 +389,6 @@ static void vc5_hvs_update_gamma_lut(struct vc4_hvs *hvs,
389389 vc5_hvs_lut_load (hvs , vc4_crtc );
390390}
391391
392- static void vc4_hvs_irq_enable_eof (const struct vc4_hvs * hvs ,
393- unsigned int channel )
394- {
395- u32 irq_mask = hvs -> hvs5 ?
396- SCALER5_DISPCTRL_DSPEIEOF (channel ) :
397- SCALER_DISPCTRL_DSPEIEOF (channel );
398-
399- HVS_WRITE (SCALER_DISPCTRL ,
400- HVS_READ (SCALER_DISPCTRL ) | irq_mask );
401- }
402-
403- static void vc4_hvs_irq_clear_eof (const struct vc4_hvs * hvs ,
404- unsigned int channel )
405- {
406- u32 irq_mask = hvs -> hvs5 ?
407- SCALER5_DISPCTRL_DSPEIEOF (channel ) :
408- SCALER_DISPCTRL_DSPEIEOF (channel );
409-
410- HVS_WRITE (SCALER_DISPCTRL ,
411- HVS_READ (SCALER_DISPCTRL ) & ~irq_mask );
412- }
413-
414- static struct vc4_hvs_dlist_allocation *
415- vc4_hvs_alloc_dlist_entry (struct vc4_hvs * hvs ,
416- unsigned int channel ,
417- size_t dlist_count )
418- {
419- struct vc4_hvs_dlist_allocation * alloc ;
420- unsigned long flags ;
421- int ret ;
422-
423- if (channel == VC4_HVS_CHANNEL_DISABLED )
424- return NULL ;
425-
426- alloc = kzalloc (sizeof (* alloc ), GFP_KERNEL );
427- if (!alloc )
428- return ERR_PTR (- ENOMEM );
429-
430- spin_lock_irqsave (& hvs -> mm_lock , flags );
431- ret = drm_mm_insert_node (& hvs -> dlist_mm , & alloc -> mm_node ,
432- dlist_count );
433- spin_unlock_irqrestore (& hvs -> mm_lock , flags );
434- if (ret )
435- return ERR_PTR (ret );
436-
437- alloc -> channel = channel ;
438-
439- return alloc ;
440- }
441-
442- void vc4_hvs_mark_dlist_entry_stale (struct vc4_hvs * hvs ,
443- struct vc4_hvs_dlist_allocation * alloc )
444- {
445- unsigned long flags ;
446- u8 frcnt ;
447-
448- if (!alloc )
449- return ;
450-
451- if (!drm_mm_node_allocated (& alloc -> mm_node ))
452- return ;
453-
454- frcnt = vc4_hvs_get_fifo_frame_count (hvs , alloc -> channel );
455- alloc -> target_frame_count = (frcnt + 1 ) & ((1 << 6 ) - 1 );
456-
457- spin_lock_irqsave (& hvs -> mm_lock , flags );
458-
459- list_add_tail (& alloc -> node , & hvs -> stale_dlist_entries );
460-
461- HVS_WRITE (SCALER_DISPSTAT , SCALER_DISPSTAT_EOF (alloc -> channel ));
462- vc4_hvs_irq_enable_eof (hvs , alloc -> channel );
463-
464- spin_unlock_irqrestore (& hvs -> mm_lock , flags );
465- }
466-
467- static void vc4_hvs_schedule_dlist_sweep (struct vc4_hvs * hvs ,
468- unsigned int channel )
469- {
470- unsigned long flags ;
471-
472- spin_lock_irqsave (& hvs -> mm_lock , flags );
473-
474- if (!list_empty (& hvs -> stale_dlist_entries ))
475- queue_work (system_unbound_wq , & hvs -> free_dlist_work );
476-
477- vc4_hvs_irq_clear_eof (hvs , channel );
478-
479- spin_unlock_irqrestore (& hvs -> mm_lock , flags );
480- }
481-
482- /*
483- * Frame counts are essentially sequence numbers over 6 bits, and we
484- * thus can use sequence number arithmetic and follow the RFC1982 to
485- * implement proper comparison between them.
486- */
487- static bool vc4_hvs_frcnt_lte (u8 cnt1 , u8 cnt2 )
488- {
489- return (s8 )((cnt1 << 2 ) - (cnt2 << 2 )) <= 0 ;
490- }
491-
492- /*
493- * Some atomic commits (legacy cursor updates, mostly) will not wait for
494- * the next vblank and will just return once the commit has been pushed
495- * to the hardware.
496- *
497- * On the hardware side, our HVS stores the planes parameters in its
498- * context RAM, and will use part of the RAM to store data during the
499- * frame rendering.
500- *
501- * This interacts badly if we get multiple commits before the next
502- * vblank since we could end up overwriting the DLIST entries used by
503- * previous commits if our dlist allocation reuses that entry. In such a
504- * case, we would overwrite the data currently being used by the
505- * hardware, resulting in a corrupted frame.
506- *
507- * In order to work around this, we'll queue the dlist entries in a list
508- * once the associated CRTC state is destroyed. The HVS only allows us
509- * to know which entry is being active, but not which one are no longer
510- * being used, so in order to avoid freeing entries that are still used
511- * by the hardware we add a guesstimate of the frame count where our
512- * entry will no longer be used, and thus will only free those entries
513- * when we will have reached that frame count.
514- */
515- static void vc4_hvs_dlist_free_work (struct work_struct * work )
516- {
517- struct vc4_hvs * hvs = container_of (work , struct vc4_hvs , free_dlist_work );
518- struct vc4_hvs_dlist_allocation * cur , * next ;
519- unsigned long flags ;
520-
521- spin_lock_irqsave (& hvs -> mm_lock , flags );
522- list_for_each_entry_safe (cur , next , & hvs -> stale_dlist_entries , node ) {
523- u8 frcnt ;
524-
525- frcnt = vc4_hvs_get_fifo_frame_count (hvs , cur -> channel );
526- if (!vc4_hvs_frcnt_lte (cur -> target_frame_count , frcnt ))
527- continue ;
528-
529- list_del (& cur -> node );
530- drm_mm_remove_node (& cur -> mm_node );
531- kfree (cur );
532- }
533- spin_unlock_irqrestore (& hvs -> mm_lock , flags );
534- }
535-
536392u8 vc4_hvs_get_fifo_frame_count (struct vc4_hvs * hvs , unsigned int fifo )
537393{
538394 u8 field = 0 ;
@@ -732,12 +588,13 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
732588{
733589 struct drm_crtc_state * crtc_state = drm_atomic_get_new_crtc_state (state , crtc );
734590 struct vc4_crtc_state * vc4_state = to_vc4_crtc_state (crtc_state );
735- struct vc4_hvs_dlist_allocation * alloc ;
736591 struct drm_device * dev = crtc -> dev ;
737592 struct vc4_dev * vc4 = to_vc4_dev (dev );
738593 struct drm_plane * plane ;
594+ unsigned long flags ;
739595 const struct drm_plane_state * plane_state ;
740596 u32 dlist_count = 0 ;
597+ int ret ;
741598
742599 /* The pixelvalve can only feed one encoder (and encoders are
743600 * 1:1 with connectors.)
@@ -750,11 +607,12 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
750607
751608 dlist_count ++ ; /* Account for SCALER_CTL0_END. */
752609
753- alloc = vc4_hvs_alloc_dlist_entry (vc4 -> hvs , vc4_state -> assigned_channel , dlist_count );
754- if (IS_ERR (alloc ))
755- return PTR_ERR (alloc );
756-
757- vc4_state -> mm = alloc ;
610+ spin_lock_irqsave (& vc4 -> hvs -> mm_lock , flags );
611+ ret = drm_mm_insert_node (& vc4 -> hvs -> dlist_mm , & vc4_state -> mm ,
612+ dlist_count );
613+ spin_unlock_irqrestore (& vc4 -> hvs -> mm_lock , flags );
614+ if (ret )
615+ return ret ;
758616
759617 return vc4_hvs_gamma_check (crtc , state );
760618}
@@ -766,9 +624,8 @@ static void vc4_hvs_install_dlist(struct drm_crtc *crtc)
766624 struct vc4_hvs * hvs = vc4 -> hvs ;
767625 struct vc4_crtc_state * vc4_state = to_vc4_crtc_state (crtc -> state );
768626
769- WARN_ON (!vc4_state -> mm );
770627 HVS_WRITE (SCALER_DISPLISTX (vc4_state -> assigned_channel ),
771- vc4_state -> mm -> mm_node .start );
628+ vc4_state -> mm .start );
772629}
773630
774631static void vc4_hvs_update_dlist (struct drm_crtc * crtc )
@@ -793,10 +650,8 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
793650 spin_unlock_irqrestore (& dev -> event_lock , flags );
794651 }
795652
796- WARN_ON (!vc4_state -> mm );
797-
798653 spin_lock_irqsave (& vc4_crtc -> irq_lock , flags );
799- vc4_crtc -> current_dlist = vc4_state -> mm -> mm_node .start ;
654+ vc4_crtc -> current_dlist = vc4_state -> mm .start ;
800655 spin_unlock_irqrestore (& vc4_crtc -> irq_lock , flags );
801656}
802657
@@ -853,7 +708,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
853708 struct vc4_plane_state * vc4_plane_state ;
854709 bool debug_dump_regs = false;
855710 bool enable_bg_fill = false;
856- u32 __iomem * dlist_start , * dlist_next ;
711+ u32 __iomem * dlist_start = vc4 -> hvs -> dlist + vc4_state -> mm .start ;
712+ u32 __iomem * dlist_next = dlist_start ;
857713 unsigned int zpos = 0 ;
858714 bool found = false;
859715
@@ -865,9 +721,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
865721 vc4_hvs_dump_state (hvs );
866722 }
867723
868- dlist_start = vc4 -> hvs -> dlist + vc4_state -> mm -> mm_node .start ;
869- dlist_next = dlist_start ;
870-
871724 /* Copy all the active planes' dlist contents to the hardware dlist. */
872725 do {
873726 found = false;
@@ -901,8 +754,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
901754 writel (SCALER_CTL0_END , dlist_next );
902755 dlist_next ++ ;
903756
904- WARN_ON (!vc4_state -> mm );
905- WARN_ON_ONCE (dlist_next - dlist_start != vc4_state -> mm -> mm_node .size );
757+ WARN_ON_ONCE (dlist_next - dlist_start != vc4_state -> mm .size );
906758
907759 if (enable_bg_fill )
908760 /* This sets a black background color fill, as is the case
@@ -1007,11 +859,6 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
1007859
1008860 irqret = IRQ_HANDLED ;
1009861 }
1010-
1011- if (status & SCALER_DISPSTAT_EOF (channel )) {
1012- vc4_hvs_schedule_dlist_sweep (hvs , channel );
1013- irqret = IRQ_HANDLED ;
1014- }
1015862 }
1016863
1017864 /* Clear every per-channel interrupt flag. */
@@ -1069,8 +916,6 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
1069916 hvs -> dlist = hvs -> regs + SCALER5_DLIST_START ;
1070917
1071918 spin_lock_init (& hvs -> mm_lock );
1072- INIT_LIST_HEAD (& hvs -> stale_dlist_entries );
1073- INIT_WORK (& hvs -> free_dlist_work , vc4_hvs_dlist_free_work );
1074919
1075920 /* Set up the HVS display list memory manager. We never
1076921 * overwrite the setup from the bootloader (just 128b out of
0 commit comments