summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/mgag200/mgag200_mode.c
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2022-05-02 17:25:14 +0300
committerThomas Zimmermann <tzimmermann@suse.de>2022-05-05 10:18:54 +0300
commit931e3f3a0e997c41eafbc88e4fc07ba9fef28f29 (patch)
tree435c7eafdc66bc24e65a3f5bb84ca5a9cc07de59 /drivers/gpu/drm/mgag200/mgag200_mode.c
parentf870231fdd6ce2c6c040a3584a2eac97ae473780 (diff)
downloadlinux-931e3f3a0e997c41eafbc88e4fc07ba9fef28f29.tar.xz
drm/mgag200: Protect concurrent access to I/O registers with lock
Add a mutex lock to protect concurrent access to I/O registers against each other. This happens between invocation of commit- tail functions and get-mode operations. Both with use the CRTC index registers MGA1064_GEN_IO_DATA and MGA1064_GEN_IO_CTL. Concurrent access can lead to failed mode-setting operations. v2: * fix typo in commit description (Jocelyn) * add comment to explain rmmio_lock Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220502142514.2174-4-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/mgag200/mgag200_mode.c')
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 6e18d3bbd720..abde7655477d 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -881,6 +881,14 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
.y2 = fb->height,
};
+ /*
+ * Concurrent operations could possibly trigger a call to
+ * drm_connector_helper_funcs.get_modes by trying to read the
+ * display modes. Protect access to I/O registers by acquiring
+ * the I/O-register lock.
+ */
+ mutex_lock(&mdev->rmmio_lock);
+
if (mdev->type == G200_WB || mdev->type == G200_EW3)
mgag200_g200wb_hold_bmc(mdev);
@@ -904,6 +912,8 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
mgag200_enable_display(mdev);
mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
+
+ mutex_unlock(&mdev->rmmio_lock);
}
static void
@@ -963,8 +973,12 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
if (!fb)
return;
+ mutex_lock(&mdev->rmmio_lock);
+
if (drm_atomic_helper_damage_merged(old_state, state, &damage))
mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
+
+ mutex_unlock(&mdev->rmmio_lock);
}
static struct drm_crtc_state *