drm/amd/display: add basic atomic check for cursor plane
authorSimon Ser <contact@emersion.fr>
Mon, 30 Mar 2020 09:23:21 +0000 (09:23 +0000)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 7 May 2020 20:24:45 +0000 (16:24 -0400)
This patch adds a basic cursor check when an atomic test-only commit is
performed. The position and size of the cursor plane is checked.

This should fix user-space relying on atomic checks to assign buffers to
planes.

Signed-off-by: Simon Ser <contact@emersion.fr>
Reported-by: Roman Gilg <subdiff@gmail.com>
References: https://github.com/emersion/libliftoff/issues/46
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Harry Wentland <hwentlan@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 bd1052c88fb08ac9d8fa8cb018b7f13fcff1f541..296c817e5f913fc389ea9b0559900f59220bef02 100644 (file)
@@ -7885,6 +7885,7 @@ static int dm_update_plane_state(struct dc *dc,
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
        struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
+       struct amdgpu_crtc *new_acrtc;
        bool needs_reset;
        int ret = 0;
 
@@ -7894,9 +7895,30 @@ static int dm_update_plane_state(struct dc *dc,
        dm_new_plane_state = to_dm_plane_state(new_plane_state);
        dm_old_plane_state = to_dm_plane_state(old_plane_state);
 
-       /*TODO Implement atomic check for cursor plane */
-       if (plane->type == DRM_PLANE_TYPE_CURSOR)
+       /*TODO Implement better atomic check for cursor plane */
+       if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+               if (!enable || !new_plane_crtc ||
+                       drm_atomic_plane_disabling(plane->state, new_plane_state))
+                       return 0;
+
+               new_acrtc = to_amdgpu_crtc(new_plane_crtc);
+
+               if ((new_plane_state->crtc_w > new_acrtc->max_cursor_width) ||
+                       (new_plane_state->crtc_h > new_acrtc->max_cursor_height)) {
+                       DRM_DEBUG_ATOMIC("Bad cursor size %d x %d\n",
+                                                        new_plane_state->crtc_w, new_plane_state->crtc_h);
+                       return -EINVAL;
+               }
+
+               if (new_plane_state->crtc_x <= -new_acrtc->max_cursor_width ||
+                       new_plane_state->crtc_y <= -new_acrtc->max_cursor_height) {
+                       DRM_DEBUG_ATOMIC("Bad cursor position %d, %d\n",
+                                                        new_plane_state->crtc_x, new_plane_state->crtc_y);
+                       return -EINVAL;
+               }
+
                return 0;
+       }
 
        needs_reset = should_reset_plane(state, plane, old_plane_state,
                                         new_plane_state);