From: Andrey Grodzovsky <[email protected]>

Use new functions so flip failures can be gracefully handled

v2:
Avoid -EINVAL returned from amdgpu_crtc_prepare_flip in some
error cases, it is not allowed according to expected
return values for atomic_commit hook.

Change-Id: Ie04af6f0c56ee822ddb9f24fb77f367b4e31c620
Signed-off-by: Andrey Grodzovsky <[email protected]>
Acked-by: Harry Wentland <[email protected]>
Reviewed-by: Andrey Grodzovsky <[email protected]>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c    | 96 +++++++++++++++++++---
 1 file changed, 83 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
index d1a11d93af7a..a26749854ec7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
@@ -1647,6 +1647,7 @@ static void clear_unrelated_fields(struct drm_plane_state 
*state)
 static bool page_flip_needed(
        const struct drm_plane_state *new_state,
        const struct drm_plane_state *old_state,
+       struct drm_pending_vblank_event *event,
        bool commit_surface_required)
 {
        struct drm_plane_state old_state_tmp;
@@ -1676,7 +1677,7 @@ static bool page_flip_needed(
        old_state_tmp = *old_state;
        new_state_tmp = *new_state;
 
-       if (!new_state->crtc->state->event)
+       if (!event)
                return false;
 
        amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb);
@@ -2485,17 +2486,21 @@ int amdgpu_dm_atomic_commit(
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_display_manager *dm = &adev->dm;
        struct drm_plane *plane;
+       struct drm_plane_state *new_plane_state;
        struct drm_plane_state *old_plane_state;
        uint32_t i;
        int32_t ret = 0;
        uint32_t commit_streams_count = 0;
        uint32_t new_crtcs_count = 0;
+       uint32_t flip_crtcs_count = 0;
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state;
-
        const struct dc_stream *commit_streams[MAX_STREAMS];
        struct amdgpu_crtc *new_crtcs[MAX_STREAMS];
        const struct dc_stream *new_stream;
+       struct drm_crtc *flip_crtcs[MAX_STREAMS];
+       struct amdgpu_flip_work *work[MAX_STREAMS] = {0};
+       struct amdgpu_bo *new_abo[MAX_STREAMS] = {0};
 
        /* In this step all new fb would be pinned */
 
@@ -2511,6 +2516,61 @@ int amdgpu_dm_atomic_commit(
                        return ret;
        }
 
+       /* Page flip if needed */
+       for_each_plane_in_state(state, plane, new_plane_state, i) {
+               struct drm_plane_state *old_plane_state = plane->state;
+               struct drm_crtc *crtc = new_plane_state->crtc;
+               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+               struct drm_framebuffer *fb = new_plane_state->fb;
+               struct drm_crtc_state *crtc_state;
+
+               if (!fb || !crtc)
+                       continue;
+
+               crtc_state = drm_atomic_get_crtc_state(state, crtc);
+
+               if (!crtc_state->planes_changed || !crtc_state->active)
+                       continue;
+
+               if (page_flip_needed(
+                               new_plane_state,
+                               old_plane_state,
+                               crtc_state->event,
+                               false)) {
+                       ret = amdgpu_crtc_prepare_flip(crtc,
+                                                       fb,
+                                                       crtc_state->event,
+                                                       acrtc->flip_flags,
+                                                       
drm_crtc_vblank_count(crtc),
+                                                       &work[flip_crtcs_count],
+                                                       
&new_abo[flip_crtcs_count]);
+
+                       if (ret) {
+                               /* According to atomic_commit hook API, EINVAL 
is not allowed */
+                               if (unlikely(ret == -EINVAL))
+                                       ret = -ENOMEM;
+
+                               DRM_ERROR("Atomic commit: Flip for  crtc id %d: 
[%p], "
+                                                                       
"failed, errno = %d\n",
+                                                                       
acrtc->crtc_id,
+                                                                       acrtc,
+                                                                       ret);
+                               /* cleanup all flip configurations which
+                                * succeeded in this commit
+                                */
+                               for (i = 0; i < flip_crtcs_count; i++)
+                                       amdgpu_crtc_cleanup_flip_ctx(
+                                                       work[i],
+                                                       new_abo[i]);
+
+                               return ret;
+                       }
+
+                       flip_crtcs[flip_crtcs_count] = crtc;
+                       flip_crtcs_count++;
+               }
+       }
+
        /*
         * This is the point of no return - everything below never fails except
         * when the hw goes bonghits. Which means we can commit the new state on
@@ -2699,7 +2759,10 @@ int amdgpu_dm_atomic_commit(
                 * 1. This commit is not a page flip.
                 * 2. This commit is a page flip, and streams are created.
                 */
-               if (!page_flip_needed(plane_state, old_plane_state, true) ||
+               if (!page_flip_needed(
+                               plane_state,
+                               old_plane_state,
+                               crtc->state->event, true) ||
                                action == DM_COMMIT_ACTION_DPMS_ON ||
                                action == DM_COMMIT_ACTION_SET) {
                        list_for_each_entry(connector,
@@ -2755,7 +2818,8 @@ int amdgpu_dm_atomic_commit(
 
        }
 
-       /* Page flip if needed */
+       /* Do actual flip */
+       flip_crtcs_count = 0;
        for_each_plane_in_state(state, plane, old_plane_state, i) {
                struct drm_plane_state *plane_state = plane->state;
                struct drm_crtc *crtc = plane_state->crtc;
@@ -2766,16 +2830,19 @@ int amdgpu_dm_atomic_commit(
                        !crtc->state->active)
                        continue;
 
-               if (page_flip_needed(plane_state, old_plane_state, false)) {
-                       ret = amdgpu_crtc_page_flip_target(crtc,
-                                                          fb,
-                                                          crtc->state->event,
-                                                          acrtc->flip_flags,
-                                                          
drm_crtc_vblank_count(crtc));
+               if (page_flip_needed(
+                               plane_state,
+                               old_plane_state,
+                               crtc->state->event,
+                               false)) {
+                               amdgpu_crtc_submit_flip(
+                                                       crtc,
+                                                   fb,
+                                                   work[flip_crtcs_count],
+                                                   new_abo[i]);
+                                flip_crtcs_count++;
                        /*clean up the flags for next usage*/
                        acrtc->flip_flags = 0;
-                       if (ret)
-                               return ret;
                }
        }
 
@@ -3127,6 +3194,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                        struct drm_connector *connector;
                        struct dm_connector_state *dm_state = NULL;
                        enum dm_commit_action action;
+                       struct drm_crtc_state *crtc_state;
+
 
                        if (!fb || !crtc || crtc_set[i] != crtc ||
                                !crtc->state->planes_changed || 
!crtc->state->active)
@@ -3138,8 +3207,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                         * 1. This commit is not a page flip.
                         * 2. This commit is a page flip, and streams are 
created.
                         */
+                       crtc_state = drm_atomic_get_crtc_state(state, crtc);
                        if (!page_flip_needed(plane_state, old_plane_state,
-                                             true) ||
+                                       crtc_state->event, true) ||
                                        action == DM_COMMIT_ACTION_DPMS_ON ||
                                        action == DM_COMMIT_ACTION_SET) {
                                struct dc_surface *surface;
-- 
2.9.3

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to