Skip to content

Commit

Permalink
drm/vc4: Flush stale dlist entries if allocation fails
Browse files Browse the repository at this point in the history
This is largely for debug at present.
For reasons unknown we are not getting the end of frame interrupts
that should trigger a sweep of stale dlist entries.

On allocation failure clear out ALL stale entries, and retry the
allocation. Log the interrupt status so we have debug regarding
whether the HVS believes the interrupt is enabled.

Signed-off-by: Dave Stevenson <[email protected]>
  • Loading branch information
6by9 committed Jan 22, 2024
1 parent 6fc2e0b commit e6e38c1
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions drivers/gpu/drm/vc4/vc4_hvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,9 @@ static void vc4_hvs_irq_clear_eof(struct vc4_hvs *hvs,
hvs->eof_irq[channel].enabled = false;
}

static void vc4_hvs_free_dlist_entry_locked(struct vc4_hvs *hvs,
struct vc4_hvs_dlist_allocation *alloc);

static struct vc4_hvs_dlist_allocation *
vc4_hvs_alloc_dlist_entry(struct vc4_hvs *hvs,
unsigned int channel,
Expand All @@ -642,6 +645,7 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs *hvs,
struct vc4_dev *vc4 = hvs->vc4;
struct drm_device *dev = &vc4->base;
struct vc4_hvs_dlist_allocation *alloc;
struct vc4_hvs_dlist_allocation *cur, *next;
unsigned long flags;
int ret;

Expand All @@ -659,9 +663,26 @@ vc4_hvs_alloc_dlist_entry(struct vc4_hvs *hvs,
dlist_count);
spin_unlock_irqrestore(&hvs->mm_lock, flags);
if (ret) {
drm_err(dev, "Failed to allocate DLIST entry. Requested size=%zu. ret=%d\n",
dlist_count, ret);
return ERR_PTR(ret);
drm_err(dev, "Failed to allocate DLIST entry. Requested size=%zu. ret=%d. DISPCTRL is %08x\n",
dlist_count, ret, HVS_READ(SCALER_DISPCTRL));

/* This should never happen as stale entries should get released
* as the frame counter interrupt triggers.
* However we've seen this fail for reasons currently unknown.
* Free all stale entries now so we should be able to complete
* this allocation.
*/
spin_lock_irqsave(&hvs->mm_lock, flags);
list_for_each_entry_safe(cur, next, &hvs->stale_dlist_entries, node) {
vc4_hvs_free_dlist_entry_locked(hvs, cur);
}

ret = drm_mm_insert_node(&hvs->dlist_mm, &alloc->mm_node,
dlist_count);
spin_unlock_irqrestore(&hvs->mm_lock, flags);

if (ret)
return ERR_PTR(ret);
}

alloc->channel = channel;
Expand Down

0 comments on commit e6e38c1

Please sign in to comment.