drm/amd/display: Recreate private_obj->state during S3 resume
authorLeo Li <sunpeng.li@amd.com>
Tue, 19 Mar 2019 23:29:16 +0000 (19:29 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 10 Apr 2019 18:53:28 +0000 (13:53 -0500)
[Why]

When entering S3, amdgpu first calls DRM to cache the current atomic
state, then commit the 'all-disabled' state. This sets dc->current_state
to point at the private atomic object's dm_atomic_state->context, as
any regular atomic commit would.

Afterwards, amdgpu_dm calls dc_set_power_state() with S3 power state.
This invalidates dc->current_state by wiping it to 0, consequently
wiping dm_atomic_state->context.

During resume, the cached atomic state is restored. When getting the
private object however, the dm_atomic_state - containing the wiped
context - is duplicated into the atomic state. This causes DC validation
to fail during atomic check, as necessary function pointers in dc_state
are now NULL.

[How]

Recreate the private object's dm_atomic_state->context during resume,
restoring any static values such as function pointers.

A TODO item is added to move static read-only values out of dc_state -
they shouldn't be there anyways.

Signed-off-by: Leo Li <sunpeng.li@amd.com>
Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 1db85cd..0ea715c 100644 (file)
@@ -983,9 +983,16 @@ static int dm_resume(void *handle)
        struct drm_plane *plane;
        struct drm_plane_state *new_plane_state;
        struct dm_plane_state *dm_new_plane_state;
+       struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state);
        enum dc_connection_type new_connection_type = dc_connection_none;
        int i;
 
+       /* Recreate dc_state - DC invalidates it when setting power state to S3. */
+       dc_release_state(dm_state->context);
+       dm_state->context = dc_create_state(dm->dc);
+       /* TODO: Remove dc_state->dccg, use dc->dccg directly. */
+       dc_resource_state_construct(dm->dc, dm_state->context);
+
        /* power on hardware */
        dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);