Flushing the fbdev's shadow buffer requires vmap'ing the BO memory, which in turn requires pinning the BO. While being pinned, the BO cannot be moved into VRAM for scanout. Consequently, a concurrent modeset operation that involves the fbdev framebuffer would likely fail. Resolve this problem be acquiring the modeset lock of the planes that use the fbdev framebuffer. On non-atomic drivers, also acquire the mode-config lock. This serializes the flushing of the framebuffer with concurrent modeset operations. Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/gpu/drm/drm_fb_helper.c | 43 +++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5a22c744378c..af485c71a42a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -394,20 +394,59 @@ static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper, static int drm_fb_helper_damage_blit(struct drm_fb_helper *fb_helper, struct drm_clip_rect *clip) { + struct drm_device *dev = fb_helper->dev; + struct drm_framebuffer *fb = fb_helper->fb; struct drm_client_buffer *buffer = fb_helper->buffer; + struct drm_modeset_acquire_ctx ctx; + struct drm_framebuffer *plane_fb; + struct drm_plane *plane; struct dma_buf_map map, dst; int ret; + if (!drm_drv_uses_atomic_modeset(dev)) + mutex_lock(&dev->mode_config.mutex); + + drm_modeset_acquire_init(&ctx, 0); + +retry: + drm_for_each_plane(plane, dev) { + ret = drm_modeset_lock(&plane->mutex, &ctx); + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } else if (ret) { + goto out; + } + + if (drm_drv_uses_atomic_modeset(dev)) + plane_fb = plane->state->fb; + else + plane_fb = plane->fb; + + if (plane_fb != fb) { + drm_modeset_unlock(&plane->mutex); + continue; + } + } + ret = drm_client_buffer_vmap(buffer, &map); if (ret) - return ret; + goto out; dst = map; drm_fb_helper_damage_blit_real(fb_helper, clip, &dst); drm_client_buffer_vunmap(buffer); - return 0; +out: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + if (!drm_drv_uses_atomic_modeset(dev)) + mutex_unlock(&dev->mode_config.mutex); + + return ret; } static void drm_fb_helper_damage_work(struct work_struct *work) -- 2.29.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel