Skip to content

Commit 6dafd55

Browse files
mripardpelwell
authored andcommitted
Revert "drm/vc4: hvs: Defer dlist slots deallocation"
This reverts commit e99a1b6.
1 parent 575197e commit 6dafd55

File tree

4 files changed

+23
-184
lines changed

4 files changed

+23
-184
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,14 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc,
998998
struct vc4_dev *vc4 = to_vc4_dev(crtc->dev);
999999
struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state);
10001000

1001-
vc4_hvs_mark_dlist_entry_stale(vc4->hvs, vc4_state->mm);
1002-
vc4_state->mm = NULL;
1001+
if (drm_mm_node_allocated(&vc4_state->mm)) {
1002+
unsigned long flags;
1003+
1004+
spin_lock_irqsave(&vc4->hvs->mm_lock, flags);
1005+
drm_mm_remove_node(&vc4_state->mm);
1006+
spin_unlock_irqrestore(&vc4->hvs->mm_lock, flags);
1007+
1008+
}
10031009

10041010
drm_atomic_helper_crtc_destroy_state(crtc, state);
10051011
}

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,6 @@ struct vc4_hvs {
335335
struct drm_mm lbm_mm;
336336
spinlock_t mm_lock;
337337

338-
struct list_head stale_dlist_entries;
339-
struct work_struct free_dlist_work;
340-
341338
struct drm_mm_node mitchell_netravali_filter;
342339

343340
struct debugfs_regset32 regset;
@@ -576,16 +573,10 @@ struct drm_connector *vc4_get_crtc_connector(struct drm_crtc *crtc,
576573
struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
577574
struct drm_crtc_state *state);
578575

579-
struct vc4_hvs_dlist_allocation {
580-
struct list_head node;
581-
struct drm_mm_node mm_node;
582-
unsigned int channel;
583-
u8 target_frame_count;
584-
};
585-
586576
struct vc4_crtc_state {
587577
struct drm_crtc_state base;
588-
struct vc4_hvs_dlist_allocation *mm;
578+
/* Dlist area for this CRTC configuration. */
579+
struct drm_mm_node mm;
589580
bool txp_armed;
590581
unsigned int assigned_channel;
591582

@@ -972,8 +963,6 @@ extern struct platform_driver vc4_hvs_driver;
972963
void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int output);
973964
int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output);
974965
u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo);
975-
void vc4_hvs_mark_dlist_entry_stale(struct vc4_hvs *hvs,
976-
struct vc4_hvs_dlist_allocation *alloc);
977966
int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state);
978967
void vc4_hvs_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state);
979968
void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state);

drivers/gpu/drm/vc4/vc4_hvs.c

Lines changed: 13 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
536392
u8 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

774631
static 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

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@
234234
# define SCALER_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 2))
235235
/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
236236
# define SCALER_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 2))
237-
# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
238237

239238
# define SCALER_DISPCTRL_SLVRDEIRQ BIT(6)
240239
# define SCALER_DISPCTRL_SLVWREIRQ BIT(5)

0 commit comments

Comments
 (0)