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 111fbfbbf299bf6c0772b37974d174fd6dd9874e..52b368bb99ea9609d01ad7b53d9813e57e2fa03b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8183,6 +8183,46 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { +#ifdef AMDKCL_WORKAROUND_DRM_4_10_0_RHEL_7_4 + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; + struct dm_crtc_state *dm_old_crtc_state; + struct amdgpu_device *adev = drm_to_adev(dev); + int i; + + /* + * We evade vblank and pflip interrupts on CRTCs that are undergoing + * a modeset, being disabled, or have no active planes. + * + * It's done in atomic commit rather than commit tail for now since + * some of these interrupt handlers access the current CRTC state and + * potentially the stream pointer itself. + * + * Since the atomic state is swapped within atomic commit and not within + * commit tail this would leave to new state (that hasn't been committed yet) + * being accesssed from within the handlers. + * + * TODO: Fix this so we can do this in commit tail and not have to block + * in atomic check. + */ +#if !defined(for_each_oldnew_crtc_in_state) + for_each_crtc_in_state(state, crtc, new_crtc_state, i) { + old_crtc_state = crtc->state; +#else + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { +#endif + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + + if (old_crtc_state->active && + (!new_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state))) { + manage_dm_interrupts(adev, acrtc, false); + dc_stream_release(dm_old_crtc_state->stream); + } + } +#endif /* * Add check here for SoC's that support hardware cursor plane, to * unset legacy_cursor_update @@ -8269,6 +8309,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dc_resource_state_copy_construct_current(dm->dc, dc_state); } +#if !defined(AMDKCL_WORKAROUND_DRM_4_10_0_RHEL_7_4) #if !defined(for_each_oldnew_crtc_in_state) for_each_crtc_in_state(state, crtc, new_crtc_state, i) { old_crtc_state = crtc->state; @@ -8286,6 +8327,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dc_stream_release(dm_old_crtc_state->stream); } } +#endif /* update changed items */ #if !defined(for_each_oldnew_crtc_in_state) diff --git a/include/kcl/backport/kcl_drm_crtc.h b/include/kcl/backport/kcl_drm_crtc.h index 4a8d7553436069c1bf82885b24b44c4871057a74..9345da78faeedfb9f9f146ae705d857db740540d 100644 --- a/include/kcl/backport/kcl_drm_crtc.h +++ b/include/kcl/backport/kcl_drm_crtc.h @@ -17,4 +17,9 @@ int _kcl_drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc } #define drm_crtc_init_with_planes _kcl_drm_crtc_init_with_planes #endif + +#if DRM_VERSION_CODE == DRM_VERSION(4, 10, 0) && defined(OS_NAME_RHEL_7_4) +#define AMDKCL_WORKAROUND_DRM_4_10_0_RHEL_7_4 +#endif + #endif