Patrick Williams | 2194f50 | 2022-10-16 14:26:09 -0500 | [diff] [blame] | 1 | From 3bfadb22e58bdf7691f80f403dd85794f2b86ad6 Mon Sep 17 00:00:00 2001 |
| 2 | From: Liviu Dudau <liviu.dudau@arm.com> |
| 3 | Date: Fri, 8 Jul 2022 16:39:21 +0100 |
| 4 | Subject: [PATCH] drm/komeda: Fix handling of atomic commits in the |
| 5 | atomic_commit_tail hook |
| 6 | |
| 7 | Komeda driver relies on the generic DRM atomic helper functions to handle |
| 8 | commits. It only implements an atomic_commit_tail hook for the |
| 9 | mode_config_helper_funcs and even that one is pretty close to the generic |
| 10 | implementation with the exception of additional dma_fence signalling. |
| 11 | |
| 12 | What the generic helper framework doesn't do is waiting for the actual |
| 13 | hardware to signal that the commit parameters have been written into the |
| 14 | appropriate registers. As we signal CRTC events only on the irq handlers, |
| 15 | we need to flush the configuration and wait for the hardware to respond. |
| 16 | |
| 17 | Add the Komeda specific implementation for atomic_commit_hw_done() that |
| 18 | flushes and waits for flip done before calling drm_atomic_helper_commit_hw_done(). |
| 19 | |
| 20 | The fix was prompted by a patch from Carsten Haitzler where he was trying to |
| 21 | solve the same issue but in a different way that I think can lead to wrong |
| 22 | event signaling to userspace. |
| 23 | |
| 24 | Upstream-Status: Backport [https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com] |
| 25 | Reported-by: Carsten Haitzler <carsten.haitzler@arm.com> |
| 26 | Tested-by: Carsten Haitzler <carsten.haitzler@arm.com> |
| 27 | Reviewed-by: Carsten Haitzler <carsten.haitzler@arm.com> |
| 28 | Signed-off-by: Liviu Dudau <liviu.dudau@arm.com> |
| 29 | Link: https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com |
| 30 | Signed-off-by: Ben Horgan <ben.horgan@arm.com> |
| 31 | Change-Id: I0bd92150120eb929692c1d38c4d1077d38401cdd |
| 32 | Signed-off-by: Rupinderjit Singh <rupinderjit.singh@arm.com> |
| 33 | --- |
| 34 | .../gpu/drm/arm/display/komeda/komeda_crtc.c | 4 ++-- |
| 35 | .../gpu/drm/arm/display/komeda/komeda_kms.c | 21 ++++++++++++++++++- |
| 36 | .../gpu/drm/arm/display/komeda/komeda_kms.h | 2 ++ |
| 37 | 3 files changed, 24 insertions(+), 3 deletions(-) |
| 38 | |
| 39 | diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c |
| 40 | index 59172acb9738..292f533d8cf0 100644 |
| 41 | --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c |
| 42 | +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c |
| 43 | @@ -235,7 +235,7 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, |
| 44 | crtc->state->event = NULL; |
| 45 | drm_crtc_send_vblank_event(crtc, event); |
| 46 | } else { |
| 47 | - DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n", |
| 48 | + DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n", |
| 49 | drm_crtc_index(&kcrtc->base)); |
| 50 | } |
| 51 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
| 52 | @@ -286,7 +286,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc, |
| 53 | komeda_crtc_do_flush(crtc, old); |
| 54 | } |
| 55 | |
| 56 | -static void |
| 57 | +void |
| 58 | komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, |
| 59 | struct completion *input_flip_done) |
| 60 | { |
| 61 | diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c |
| 62 | index 8b2be8a9a27d..c434fb43d82c 100644 |
| 63 | --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c |
| 64 | +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c |
| 65 | @@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = { |
| 66 | .minor = 1, |
| 67 | }; |
| 68 | |
| 69 | +static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state) |
| 70 | +{ |
| 71 | + struct drm_device *dev = state->dev; |
| 72 | + struct komeda_kms_dev *kms = to_kdev(dev); |
| 73 | + int i; |
| 74 | + |
| 75 | + for (i = 0; i < kms->n_crtcs; i++) { |
| 76 | + struct komeda_crtc *kcrtc = &kms->crtcs[i]; |
| 77 | + |
| 78 | + if (kcrtc->base.state->active) { |
| 79 | + struct completion *flip_done = NULL; |
| 80 | + if (kcrtc->base.state->event) |
| 81 | + flip_done = kcrtc->base.state->event->base.completion; |
| 82 | + komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done); |
| 83 | + } |
| 84 | + } |
| 85 | + drm_atomic_helper_commit_hw_done(state); |
| 86 | +} |
| 87 | + |
| 88 | static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) |
| 89 | { |
| 90 | struct drm_device *dev = old_state->dev; |
| 91 | @@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) |
| 92 | |
| 93 | drm_atomic_helper_commit_modeset_enables(dev, old_state); |
| 94 | |
| 95 | - drm_atomic_helper_commit_hw_done(old_state); |
| 96 | + komeda_kms_atomic_commit_hw_done(old_state); |
| 97 | |
| 98 | drm_atomic_helper_wait_for_flip_done(dev, old_state); |
| 99 | |
| 100 | diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h |
| 101 | index 456f3c435719..bf6e8fba5061 100644 |
| 102 | --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h |
| 103 | +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h |
| 104 | @@ -182,6 +182,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms); |
| 105 | |
| 106 | void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, |
| 107 | struct komeda_events *evts); |
| 108 | +void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, |
| 109 | + struct completion *input_flip_done); |
| 110 | |
| 111 | struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); |
| 112 | void komeda_kms_detach(struct komeda_kms_dev *kms); |
| 113 | -- |
| 114 | 2.25.1 |
| 115 | |