summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Salido <salidoa@google.com>2023-02-10 17:14:01 -0800
committerTreeHugger Robot <treehugger-gerrit@google.com>2023-02-15 07:59:27 +0000
commite5b81df11cab774e0ef7cc8d3bd734fd3b7b1483 (patch)
treef0ff746d88a133d9ce46a599f9f02bc7ae559ecc
parent4b3506a3f2a3918662e160d3fb8ae01ea1fdcdab (diff)
downloaddisplay-e5b81df11cab774e0ef7cc8d3bd734fd3b7b1483.tar.gz
drm: samsung: recovery: isolate recovery only to a single pipeline
Current recovery mechanism is resetting all interfaces (via the call to drm_mode_config_reset). This leads to inconsistent state, and unnecessarily modifying other display pipelines. Instead isolate the recovery sequence to only the crtc provided. Bug: 267877897 Change-Id: Ib6358ade88eb322d79194c062f9125c31e4cb7eb Signed-off-by: Adrian Salido <salidoa@google.com>
-rw-r--r--samsung/exynos_drm_recovery.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/samsung/exynos_drm_recovery.c b/samsung/exynos_drm_recovery.c
index 093a1ba..8963147 100644
--- a/samsung/exynos_drm_recovery.c
+++ b/samsung/exynos_drm_recovery.c
@@ -28,6 +28,52 @@
#include "exynos_drm_decon.h"
#include "exynos_drm_recovery.h"
+static struct drm_atomic_state *_duplicate_active_crtc_state(struct drm_crtc *crtc,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_atomic_state *state;
+ struct drm_crtc_state *crtc_state;
+ int err;
+
+ state = drm_atomic_state_alloc(dev);
+ if (!state)
+ return ERR_PTR(-ENOMEM);
+
+ state->acquire_ctx = ctx;
+
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state)) {
+ err = PTR_ERR(crtc_state);
+ goto free_state;
+ }
+
+ if (!crtc_state->active) {
+ pr_warn("crtc[%s]: skipping duplication of inactive crtc state\n", crtc->name);
+ err = -EINVAL;
+ goto free_state;
+ }
+
+ err = drm_atomic_add_affected_planes(state, crtc);
+ if (err)
+ goto free_state;
+
+ err = drm_atomic_add_affected_connectors(state, crtc);
+ if (err)
+ goto free_state;
+
+ /* clear the acquire context so that it isn't accidentally reused */
+ state->acquire_ctx = NULL;
+
+free_state:
+ if (err < 0) {
+ drm_atomic_state_put(state);
+ state = ERR_PTR(err);
+ }
+
+ return state;
+}
+
static void exynos_recovery_handler(struct work_struct *work)
{
struct exynos_recovery *recovery = container_of(work,
@@ -49,7 +95,7 @@ static void exynos_recovery_handler(struct work_struct *work)
drm_modeset_acquire_init(&ctx, 0);
- rcv_state = drm_atomic_helper_duplicate_state(dev, &ctx);
+ rcv_state = _duplicate_active_crtc_state(crtc, &ctx);
if (IS_ERR(rcv_state)) {
ret = PTR_ERR(rcv_state);
goto out_drop_locks;
@@ -57,6 +103,7 @@ static void exynos_recovery_handler(struct work_struct *work)
state = drm_atomic_state_alloc(dev);
if (!state) {
+ drm_atomic_state_put(rcv_state);
ret = -ENOMEM;
goto out_drop_locks;
}
@@ -102,7 +149,6 @@ retry:
if (ret)
goto out;
- drm_mode_config_reset(dev);
ret = drm_atomic_helper_commit_duplicated_state(rcv_state, &ctx);
if (ret)
goto out;