#include <drm/drm_drv.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_module.h>
 #include <drm/drm_pciids.h>
 
        struct pci_dev *pdev = to_pci_dev(dev->dev);
        u32 option, option2;
        u8 crtcext3;
+       int ret;
+
+       ret = drmm_mutex_init(dev, &mdev->rmmio_lock);
+       if (ret)
+               return ret;
 
        switch (mdev->type) {
        case G200_PCI:
 
                .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);
 
        mgag200_enable_display(mdev);
 
        mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
+
+       mutex_unlock(&mdev->rmmio_lock);
 }
 
 static void
        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 *