mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 22:26:55 +00:00
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
This commit is contained in:
parent
f870231fdd
commit
931e3f3a0e
3 changed files with 21 additions and 0 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include <drm/drm_drv.h>
|
#include <drm/drm_drv.h>
|
||||||
#include <drm/drm_file.h>
|
#include <drm/drm_file.h>
|
||||||
#include <drm/drm_ioctl.h>
|
#include <drm/drm_ioctl.h>
|
||||||
|
#include <drm/drm_managed.h>
|
||||||
#include <drm/drm_module.h>
|
#include <drm/drm_module.h>
|
||||||
#include <drm/drm_pciids.h>
|
#include <drm/drm_pciids.h>
|
||||||
|
|
||||||
|
@ -65,6 +66,11 @@ static int mgag200_regs_init(struct mga_device *mdev)
|
||||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||||
u32 option, option2;
|
u32 option, option2;
|
||||||
u8 crtcext3;
|
u8 crtcext3;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = drmm_mutex_init(dev, &mdev->rmmio_lock);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
switch (mdev->type) {
|
switch (mdev->type) {
|
||||||
case G200_PCI:
|
case G200_PCI:
|
||||||
|
|
|
@ -213,6 +213,7 @@ struct mga_device {
|
||||||
struct drm_device base;
|
struct drm_device base;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
struct mutex rmmio_lock; /* Protects access to rmmio */
|
||||||
resource_size_t rmmio_base;
|
resource_size_t rmmio_base;
|
||||||
resource_size_t rmmio_size;
|
resource_size_t rmmio_size;
|
||||||
void __iomem *rmmio;
|
void __iomem *rmmio;
|
||||||
|
|
|
@ -881,6 +881,14 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
||||||
.y2 = fb->height,
|
.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)
|
if (mdev->type == G200_WB || mdev->type == G200_EW3)
|
||||||
mgag200_g200wb_hold_bmc(mdev);
|
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_enable_display(mdev);
|
||||||
|
|
||||||
mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
|
mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
|
||||||
|
|
||||||
|
mutex_unlock(&mdev->rmmio_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -963,8 +973,12 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
|
||||||
if (!fb)
|
if (!fb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mutex_lock(&mdev->rmmio_lock);
|
||||||
|
|
||||||
if (drm_atomic_helper_damage_merged(old_state, state, &damage))
|
if (drm_atomic_helper_damage_merged(old_state, state, &damage))
|
||||||
mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
|
mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
|
||||||
|
|
||||||
|
mutex_unlock(&mdev->rmmio_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_crtc_state *
|
static struct drm_crtc_state *
|
||||||
|
|
Loading…
Reference in a new issue