Commit 87b7ebc2 authored by Rodrigo Siqueira's avatar Rodrigo Siqueira Committed by Alex Deucher
Browse files

drm/amd/display: Fix green screen issue after suspend

[why]
We have seen a green screen after resume from suspend in a Raven system
connected with two displays (HDMI and DP) on X based system. We noticed
that this issue is related to bad DCC metadata from user space which may
generate hangs and consequently an underflow on HUBP. After taking a
deep look at the code path we realized that after resume we try to
restore the commit with the DCC enabled framebuffer but the framebuffer
is no longer valid.

[how]
This problem was only reported on Raven based system and after suspend,
for this reason, this commit adds a new parameter on
fill_plane_dcc_attributes() to give the option of disabling DCC
programmatically. In summary, for disabling DCC we first verify if is a
Raven system and if it is in suspend; if both conditions are true we
disable DCC temporarily, otherwise, it is enabled.

Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1099


Co-developed-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
parent 718a5569
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -3340,7 +3340,8 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev,
			  const union dc_tiling_info *tiling_info,
			  const uint64_t info,
			  struct dc_plane_dcc_param *dcc,
			  struct dc_plane_address *address)
			  struct dc_plane_address *address,
			  bool force_disable_dcc)
{
	struct dc *dc = adev->dm.dc;
	struct dc_dcc_surface_param input;
@@ -3352,6 +3353,9 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev,
	memset(&input, 0, sizeof(input));
	memset(&output, 0, sizeof(output));

	if (force_disable_dcc)
		return 0;

	if (!offset)
		return 0;

@@ -3401,7 +3405,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
			     union dc_tiling_info *tiling_info,
			     struct plane_size *plane_size,
			     struct dc_plane_dcc_param *dcc,
			     struct dc_plane_address *address)
			     struct dc_plane_address *address,
			     bool force_disable_dcc)
{
	const struct drm_framebuffer *fb = &afb->base;
	int ret;
@@ -3507,7 +3512,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,

		ret = fill_plane_dcc_attributes(adev, afb, format, rotation,
						plane_size, tiling_info,
						tiling_flags, dcc, address);
						tiling_flags, dcc, address,
						force_disable_dcc);
		if (ret)
			return ret;
	}
@@ -3599,7 +3605,8 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
			    const struct drm_plane_state *plane_state,
			    const uint64_t tiling_flags,
			    struct dc_plane_info *plane_info,
			    struct dc_plane_address *address)
			    struct dc_plane_address *address,
			    bool force_disable_dcc)
{
	const struct drm_framebuffer *fb = plane_state->fb;
	const struct amdgpu_framebuffer *afb =
@@ -3681,7 +3688,8 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
					   plane_info->rotation, tiling_flags,
					   &plane_info->tiling_info,
					   &plane_info->plane_size,
					   &plane_info->dcc, address);
					   &plane_info->dcc, address,
					   force_disable_dcc);
	if (ret)
		return ret;

@@ -3704,6 +3712,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
	struct dc_plane_info plane_info;
	uint64_t tiling_flags;
	int ret;
	bool force_disable_dcc = false;

	ret = fill_dc_scaling_info(plane_state, &scaling_info);
	if (ret)
@@ -3718,9 +3727,11 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
	if (ret)
		return ret;

	force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
	ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags,
					  &plane_info,
					  &dc_plane_state->address);
					  &dc_plane_state->address,
					  force_disable_dcc);
	if (ret)
		return ret;

@@ -5342,6 +5353,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
	uint64_t tiling_flags;
	uint32_t domain;
	int r;
	bool force_disable_dcc = false;

	dm_plane_state_old = to_dm_plane_state(plane->state);
	dm_plane_state_new = to_dm_plane_state(new_state);
@@ -5400,11 +5412,13 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
			dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
		struct dc_plane_state *plane_state = dm_plane_state_new->dc_state;

		force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
		fill_plane_buffer_attributes(
			adev, afb, plane_state->format, plane_state->rotation,
			tiling_flags, &plane_state->tiling_info,
			&plane_state->plane_size, &plane_state->dcc,
			&plane_state->address);
			&plane_state->address,
			force_disable_dcc);
	}

	return 0;
@@ -6676,7 +6690,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
		fill_dc_plane_info_and_addr(
			dm->adev, new_plane_state, tiling_flags,
			&bundle->plane_infos[planes_count],
			&bundle->flip_addrs[planes_count].address);
			&bundle->flip_addrs[planes_count].address,
			false);

		DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
				 new_plane_state->plane->index,
				 bundle->plane_infos[planes_count].dcc.enable);

		bundle->surface_updates[planes_count].plane_info =
			&bundle->plane_infos[planes_count];
@@ -8096,7 +8115,8 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
				ret = fill_dc_plane_info_and_addr(
					dm->adev, new_plane_state, tiling_flags,
					plane_info,
					&flip_addr->address);
					&flip_addr->address,
					false);
				if (ret)
					goto cleanup;