[PATCH 2/4] drm/amd/display: Rework vrr flip throttling for late vblank irq.

Kazlauskas, Nicholas Nicholas.Kazlauskas at amd.com
Mon Mar 18 17:59:33 UTC 2019


On 3/18/19 1:19 PM, Mario Kleiner wrote:
> For throttling to work correctly, we always need a baseline vblank
> count last_flip_vblank that increments at start of front-porch.
> 
> This is the case for drm_crtc_vblank_count() in non-VRR mode, where
> the vblank irq fires at start of front-porch and triggers DRM core
> vblank handling, but it is no longer the case in VRR mode, where
> core vblank handling is done later, after end of front-porch.
> 
> Therefore drm_crtc_vblank_count() is no longer useful for this.
> We also can't use drm_crtc_accurate_vblank_count(), as that would
> screw up vblank timestamps in VRR mode when called in front-porch.
> 
> To solve this, use the cooked hardware vblank counter returned by
> amdgpu_get_vblank_counter_kms() instead, as that one is cooked to
> always increment at start of front-porch, independent of when
> vblank related irq's fire.
> 
> This patch allows vblank irq handling to happen anywhere within
> vblank of even after it, without a negative impact on flip
> throttling, so followup patches can shift the vblank core
> handling trigger point wherever they need it.
> 
> Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas at amd.com>

Functionally drm_crtc_accurate_vblank_count is the same as 
amdgpu_get_vblank_counter_kms for querying purposes, so this works.

It's a nice cleanup for commit planes too since we no longer grab the 
DRM vblank count only to immediately subtract it off again.

> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h          |  2 +-
>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++----------
>   2 files changed, 14 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 889e443..add238f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -406,7 +406,7 @@ struct amdgpu_crtc {
>   	struct amdgpu_flip_work *pflip_works;
>   	enum amdgpu_flip_status pflip_status;
>   	int deferred_flip_completion;
> -	u64 last_flip_vblank;
> +	u32 last_flip_vblank;
>   	/* pll sharing */
>   	struct amdgpu_atom_ss ss;
>   	bool ss_enabled;
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index c1c3815..85e4f87 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -286,7 +286,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
>   	}
>   
>   	/* Update to correct count(s) if racing with vblank irq */
> -	amdgpu_crtc->last_flip_vblank = drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
> +	drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
>   
>   	/* wake up userspace */
>   	if (amdgpu_crtc->event) {
> @@ -298,6 +298,14 @@ static void dm_pflip_high_irq(void *interrupt_params)
>   	} else
>   		WARN_ON(1);
>   
> +	/* Keep track of vblank of this flip for flip throttling. We use the
> +	 * cooked hw counter, as that one incremented at start of this vblank
> +	 * of pageflip completion, so last_flip_vblank is the forbidden count
> +	 * for queueing new pageflips if vsync + VRR is enabled.
> +	 */
> +	amdgpu_crtc->last_flip_vblank = amdgpu_get_vblank_counter_kms(adev->ddev,
> +							amdgpu_crtc->crtc_id);
> +
>   	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
>   	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
>   
> @@ -4769,9 +4777,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   	unsigned long flags;
>   	struct amdgpu_bo *abo;
>   	uint64_t tiling_flags;
> -	uint32_t target, target_vblank;
> -	uint64_t last_flip_vblank;
> -	bool vrr_active = acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE;
> +	uint32_t target_vblank, last_flip_vblank;
> +	bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
>   	bool pflip_present = false;
>   
>   	struct {
> @@ -4918,7 +4925,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   			 * clients using the GLX_OML_sync_control extension or
>   			 * DRI3/Present extension with defined target_msc.
>   			 */
> -			last_flip_vblank = drm_crtc_vblank_count(pcrtc);
> +			last_flip_vblank = amdgpu_get_vblank_counter_kms(dm->ddev, acrtc_attach->crtc_id);
>   		}
>   		else {
>   			/* For variable refresh rate mode only:
> @@ -4934,11 +4941,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
>   			spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
>   		}
>   
> -		target = (uint32_t)last_flip_vblank + wait_for_vblank;
> -
> -		/* Prepare wait for target vblank early - before the fence-waits */
> -		target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) +
> -				amdgpu_get_vblank_counter_kms(pcrtc->dev, acrtc_attach->crtc_id);
> +		target_vblank = last_flip_vblank + wait_for_vblank;
>   
>   		/*
>   		 * Wait until we're out of the vertical blank period before the one
> 



More information about the amd-gfx mailing list