Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/komeda: Fix handling of atomic commits in the atomic_commit_tail hook

Komeda driver relies on the generic DRM atomic helper functions to handle
commits. It only implements an atomic_commit_tail hook for the
mode_config_helper_funcs and even that one is pretty close to the generic
implementation with the exception of additional dma_fence signalling.

What the generic helper framework doesn't do is waiting for the actual
hardware to signal that the commit parameters have been written into the
appropriate registers. As we signal CRTC events only on the irq handlers,
we need to flush the configuration and wait for the hardware to respond.

Add the Komeda specific implementation for atomic_commit_hw_done() that
flushes and waits for flip done before calling drm_atomic_helper_commit_hw_done().

The fix was prompted by a patch from Carsten Haitzler where he was trying to
solve the same issue but in a different way that I think can lead to wrong
event signaling to userspace.

Reported-by: Carsten Haitzler <carsten.haitzler@arm.com>
Tested-by: Carsten Haitzler <carsten.haitzler@arm.com>
Reviewed-by: Carsten Haitzler <carsten.haitzler@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com

+24 -3
+2 -2
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
··· 235 235 crtc->state->event = NULL; 236 236 drm_crtc_send_vblank_event(crtc, event); 237 237 } else { 238 - DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n", 238 + DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n", 239 239 drm_crtc_index(&kcrtc->base)); 240 240 } 241 241 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); ··· 286 286 komeda_crtc_do_flush(crtc, old); 287 287 } 288 288 289 - static void 289 + void 290 290 komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, 291 291 struct completion *input_flip_done) 292 292 {
+20 -1
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
··· 69 69 .minor = 1, 70 70 }; 71 71 72 + static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state) 73 + { 74 + struct drm_device *dev = state->dev; 75 + struct komeda_kms_dev *kms = to_kdev(dev); 76 + int i; 77 + 78 + for (i = 0; i < kms->n_crtcs; i++) { 79 + struct komeda_crtc *kcrtc = &kms->crtcs[i]; 80 + 81 + if (kcrtc->base.state->active) { 82 + struct completion *flip_done = NULL; 83 + if (kcrtc->base.state->event) 84 + flip_done = kcrtc->base.state->event->base.completion; 85 + komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done); 86 + } 87 + } 88 + drm_atomic_helper_commit_hw_done(state); 89 + } 90 + 72 91 static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) 73 92 { 74 93 struct drm_device *dev = old_state->dev; ··· 100 81 101 82 drm_atomic_helper_commit_modeset_enables(dev, old_state); 102 83 103 - drm_atomic_helper_commit_hw_done(old_state); 84 + komeda_kms_atomic_commit_hw_done(old_state); 104 85 105 86 drm_atomic_helper_wait_for_flip_done(dev, old_state); 106 87
+2
drivers/gpu/drm/arm/display/komeda/komeda_kms.h
··· 183 183 184 184 void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, 185 185 struct komeda_events *evts); 186 + void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, 187 + struct completion *input_flip_done); 186 188 187 189 struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); 188 190 void komeda_kms_detach(struct komeda_kms_dev *kms);