diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0936-drm-amd-display-Add-fast-path-for-cursor-plane-updat.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/0936-drm-amd-display-Add-fast-path-for-cursor-plane-updat.patch | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0936-drm-amd-display-Add-fast-path-for-cursor-plane-updat.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0936-drm-amd-display-Add-fast-path-for-cursor-plane-updat.patch new file mode 100644 index 00000000..6fb15a02 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0936-drm-amd-display-Add-fast-path-for-cursor-plane-updat.patch @@ -0,0 +1,261 @@ +From 6c53653e379a3ac6080c5df4de54e47f6f16e3ff Mon Sep 17 00:00:00 2001 +From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> +Date: Wed, 5 Dec 2018 14:59:07 -0500 +Subject: [PATCH 0936/2940] drm/amd/display: Add fast path for cursor plane + updates + +[Why] +Legacy cursor plane updates from drm helpers go through the full +atomic codepath. A high volume of cursor updates through this slow +code path can cause subsequent page-flips to skip vblank intervals +since each individual update is slow. + +This problem is particularly noticeable for the compton compositor. + +[How] +A fast path for cursor plane updates is added by using DRM asynchronous +commit support provided by async_check and async_update. These don't do +a full state/flip_done dependency stall and they don't block other +commit work. + +However, DC still expects itself to be single-threaded for anything +that can issue register writes. Screen corruption or hangs can occur +if write sequences overlap. Every call that potentially perform +register writes needs to be guarded for asynchronous updates to work. +The dc_lock mutex was added for this. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106175 + +Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> +Acked-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> +Reviewed-by Leo Li <sunpeng.li@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 67 ++++++++++++++++++- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 8 +++ + 2 files changed, 73 insertions(+), 2 deletions(-) + +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 4e6ebf30b54e..6f6d11d98f37 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -57,6 +57,7 @@ + + #include <drm/drmP.h> + #include <drm/drm_atomic.h> ++#include <drm/drm_atomic_uapi.h> + #include <drm/drm_atomic_helper.h> + #include <drm/drm_dp_mst_helper.h> + #include <drm/drm_fb_helper.h> +@@ -135,6 +136,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, + + static void prepare_flip_isr(struct amdgpu_crtc *acrtc); + ++static void handle_cursor_update(struct drm_plane *plane, ++ struct drm_plane_state *old_plane_state); + + static const enum drm_plane_type dm_plane_type_default[AMDGPU_MAX_PLANES] = { + DRM_PLANE_TYPE_PRIMARY, +@@ -402,6 +405,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) + /* Zero all the fields */ + memset(&init_data, 0, sizeof(init_data)); + ++ mutex_init(&adev->dm.dc_lock); ++ + if(amdgpu_dm_irq_init(adev)) { + DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); + goto error; +@@ -516,6 +521,9 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) + /* DC Destroy TODO: Replace destroy DAL */ + if (adev->dm.dc) + dc_destroy(&adev->dm.dc); ++ ++ mutex_destroy(&adev->dm.dc_lock); ++ + return; + } + +@@ -3647,10 +3655,43 @@ static int dm_plane_atomic_check(struct drm_plane *plane, + return -EINVAL; + } + ++static int dm_plane_atomic_async_check(struct drm_plane *plane, ++ struct drm_plane_state *new_plane_state) ++{ ++ /* Only support async updates on cursor planes. */ ++ if (plane->type != DRM_PLANE_TYPE_CURSOR) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static void dm_plane_atomic_async_update(struct drm_plane *plane, ++ struct drm_plane_state *new_state) ++{ ++ struct drm_plane_state *old_state = ++ drm_atomic_get_old_plane_state(new_state->state, plane); ++ ++ if (plane->state->fb != new_state->fb) ++ drm_atomic_set_fb_for_plane(plane->state, new_state->fb); ++ ++ plane->state->src_x = new_state->src_x; ++ plane->state->src_y = new_state->src_y; ++ plane->state->src_w = new_state->src_w; ++ plane->state->src_h = new_state->src_h; ++ plane->state->crtc_x = new_state->crtc_x; ++ plane->state->crtc_y = new_state->crtc_y; ++ plane->state->crtc_w = new_state->crtc_w; ++ plane->state->crtc_h = new_state->crtc_h; ++ ++ handle_cursor_update(plane, old_state); ++} ++ + static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { + .prepare_fb = dm_plane_helper_prepare_fb, + .cleanup_fb = dm_plane_helper_cleanup_fb, + .atomic_check = dm_plane_atomic_check, ++ .atomic_async_check = dm_plane_atomic_async_check, ++ .atomic_async_update = dm_plane_atomic_async_update + }; + + /* +@@ -4342,6 +4383,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, + static void handle_cursor_update(struct drm_plane *plane, + struct drm_plane_state *old_plane_state) + { ++ struct amdgpu_device *adev = plane->dev->dev_private; + struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); + struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; + struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; +@@ -4366,9 +4408,12 @@ static void handle_cursor_update(struct drm_plane *plane, + + if (!position.enable) { + /* turn off cursor */ +- if (crtc_state && crtc_state->stream) ++ if (crtc_state && crtc_state->stream) { ++ mutex_lock(&adev->dm.dc_lock); + dc_stream_set_cursor_position(crtc_state->stream, + &position); ++ mutex_unlock(&adev->dm.dc_lock); ++ } + return; + } + +@@ -4386,6 +4431,7 @@ static void handle_cursor_update(struct drm_plane *plane, + attributes.pitch = attributes.width; + + if (crtc_state->stream) { ++ mutex_lock(&adev->dm.dc_lock); + if (!dc_stream_set_cursor_attributes(crtc_state->stream, + &attributes)) + DRM_ERROR("DC failed to set cursor attributes\n"); +@@ -4393,6 +4439,7 @@ static void handle_cursor_update(struct drm_plane *plane, + if (!dc_stream_set_cursor_position(crtc_state->stream, + &position)) + DRM_ERROR("DC failed to set cursor position\n"); ++ mutex_unlock(&adev->dm.dc_lock); + } + } + +@@ -4608,6 +4655,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, + &acrtc_state->stream->vrr_infopacket; + } + ++ mutex_lock(&adev->dm.dc_lock); + dc_commit_updates_for_stream(adev->dm.dc, + surface_updates, + 1, +@@ -4615,6 +4663,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, + &stream_update, + &surface_updates->surface, + state); ++ mutex_unlock(&adev->dm.dc_lock); + + DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", + __func__, +@@ -4629,6 +4678,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, + * with a dc_plane_state and follow the atomic model a bit more closely here. + */ + static bool commit_planes_to_stream( ++ struct amdgpu_display_manager *dm, + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, +@@ -4705,11 +4755,13 @@ static bool commit_planes_to_stream( + updates[i].scaling_info = &scaling_info[i]; + } + ++ mutex_lock(&dm->dc_lock); + dc_commit_updates_for_stream( + dc, + updates, + new_plane_count, + dc_stream, stream_update, plane_states, state); ++ mutex_unlock(&dm->dc_lock); + + kfree(flip_addr); + kfree(plane_info); +@@ -4815,7 +4867,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, + + dc_stream_attach->abm_level = acrtc_state->abm_level; + +- if (false == commit_planes_to_stream(dm->dc, ++ if (false == commit_planes_to_stream(dm, ++ dm->dc, + plane_states_constructed, + planes_count, + acrtc_state, +@@ -4983,7 +5036,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + + if (dc_state) { + dm_enable_per_frame_crtc_master_sync(dc_state); ++ mutex_lock(&dm->dc_lock); + WARN_ON(!dc_commit_state(dm->dc, dc_state)); ++ mutex_unlock(&dm->dc_lock); + } + + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { +@@ -5045,6 +5100,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + + /*TODO How it works with MPO ?*/ + if (!commit_planes_to_stream( ++ dm, + dm->dc, + status->plane_states, + status->plane_count, +@@ -5937,6 +5993,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, + ret = -EINVAL; + goto fail; + } ++ } else if (state->legacy_cursor_update) { ++ /* ++ * This is a fast cursor update coming from the plane update ++ * helper, check if it can be done asynchronously for better ++ * performance. ++ */ ++ state->async_update = !drm_atomic_helper_async_check(dev, state); + } + + /* Must be success */ +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +index d7403b03ef07..67f5d7fae009 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +@@ -132,6 +132,14 @@ struct amdgpu_display_manager { + + struct drm_modeset_lock atomic_obj_lock; + ++ /** ++ * @dc_lock: ++ * ++ * Guards access to DC functions that can issue register write ++ * sequences. ++ */ ++ struct mutex dc_lock; ++ + /** + *@irq_handler_list_low_tab: + * +-- +2.17.1 + |