summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2022-07-28 15:40:53 +0300
committerThomas Zimmermann <tzimmermann@suse.de>2022-07-29 17:01:25 +0300
commit2d70b9a1482e09f8465452c4655ffe20c605d526 (patch)
treee7497583fbf6a6c88ccd82eb702bd910e5a852bf /drivers/gpu/drm
parent9382ec27acb2f5a43dc3c3b77036f898a498ba60 (diff)
downloadlinux-2d70b9a1482e09f8465452c4655ffe20c605d526.tar.xz
drm/mgag200: Acquire I/O-register lock in atomic_commit_tail function
Hold I/O-register lock in atomic_commit_tail to protect all pipeline updates at once. Protects against concurrent I/O access in get-modes helper. Complex modesetting operations involve mode changes, plane updates and possibly BMC updates. Make all this atomic wrt to reading display modes via EDID. It's not so much an issue with simple-KMS helpers, but will become necessary for using regular atomic helpers. v4: * remove empty line Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> Tested-by: Jocelyn Falempe <jfalempe@redhat.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220728124103.30159-5-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 11a88ef9d664..6635d8745851 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/iosys-map.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_crtc_helper.h>
@@ -702,14 +703,6 @@ 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);
@@ -741,8 +734,6 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
/* Always scanout image at VRAM offset 0 */
mgag200_set_startadd(mdev, (u32)0);
mgag200_set_offset(mdev, fb);
-
- mutex_unlock(&mdev->rmmio_lock);
}
static void
@@ -812,8 +803,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
if (!fb)
return;
- mutex_lock(&mdev->rmmio_lock);
-
if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data);
@@ -824,8 +813,6 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
/* Always scanout image at VRAM offset 0 */
mgag200_set_startadd(mdev, (u32)0);
mgag200_set_offset(mdev, fb);
-
- mutex_unlock(&mdev->rmmio_lock);
}
static struct drm_crtc_state *
@@ -903,6 +890,25 @@ static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
* Mode config
*/
+static void mgag200_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
+{
+ struct mga_device *mdev = to_mga_device(state->dev);
+
+ /*
+ * 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);
+ drm_atomic_helper_commit_tail(state);
+ mutex_unlock(&mdev->rmmio_lock);
+}
+
+static const struct drm_mode_config_helper_funcs mgag200_mode_config_helper_funcs = {
+ .atomic_commit_tail = mgag200_mode_config_helper_atomic_commit_tail,
+};
+
/* Calculates a mode's required memory bandwidth (in KiB/sec). */
static uint32_t mgag200_calculate_mode_bandwidth(const struct drm_display_mode *mode,
unsigned int bits_per_pixel)
@@ -983,6 +989,7 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra
dev->mode_config.preferred_depth = 24;
dev->mode_config.fb_base = mdev->vram_res->start;
dev->mode_config.funcs = &mgag200_mode_config_funcs;
+ dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;
return 0;
}