summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vmwgfx_drv.c13
-rw-r--r--vmwgfx_drv.h1
-rw-r--r--vmwgfx_kms.c11
-rw-r--r--vmwgfx_kms.h1
4 files changed, 25 insertions, 1 deletions
diff --git a/vmwgfx_drv.c b/vmwgfx_drv.c
index a70d499..49c2fb1 100644
--- a/vmwgfx_drv.c
+++ b/vmwgfx_drv.c
@@ -1369,6 +1369,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv)
*/
void vmw_svga_disable(struct vmw_private *dev_priv)
{
+ /*
+ * Disabling SVGA will turn off device modesetting capabilities, so
+ * notify KMS about that so that it doesn't cache atomic state that
+ * isn't valid anymore, for example crtcs turned on.
+ * Strictly we'd want to do this under the SVGA lock (or an SVGA mutex),
+ * but vmw_kms_lost_device() takes the reservation sem and thus we'll
+ * end up with lock order reversal. Thus, a master may actually perform
+ * a new modeset just after we call vmw_kms_lost_device() and race with
+ * vmw_svga_disable(), but that should at worst cause atomic KMS state
+ * to be inconsistent with the device, causing modesetting problems.
+ *
+ */
+ vmw_kms_lost_device(dev_priv->dev);
ttm_write_lock(&dev_priv->reservation_sem, false);
spin_lock(&dev_priv->svga_lock);
if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
diff --git a/vmwgfx_drv.h b/vmwgfx_drv.h
index dda8813..e55b749 100644
--- a/vmwgfx_drv.h
+++ b/vmwgfx_drv.h
@@ -944,6 +944,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
void vmw_kms_legacy_hotspot(struct drm_device *dev, struct drm_file *file_priv,
int crtc_id, __s32 *hot_x, __s32 *hot_y);
+void vmw_kms_lost_device(struct drm_device *dev);
int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
diff --git a/vmwgfx_kms.c b/vmwgfx_kms.c
index a33b056..1ae22ca 100644
--- a/vmwgfx_kms.c
+++ b/vmwgfx_kms.c
@@ -2903,3 +2903,14 @@ int vmw_kms_set_config(struct drm_mode_set *set,
return drm_atomic_helper_set_config(set, ctx);
}
+
+
+/**
+ * vmw_kms_lost_device - Notify kms that modesetting capabilities will be lost
+ *
+ * @dev: Pointer to the drm device
+ */
+void vmw_kms_lost_device(struct drm_device *dev)
+{
+ drm_atomic_helper_shutdown(dev);
+}
diff --git a/vmwgfx_kms.h b/vmwgfx_kms.h
index 2446c48..73e428c 100644
--- a/vmwgfx_kms.h
+++ b/vmwgfx_kms.h
@@ -447,5 +447,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
int vmw_kms_set_config(struct drm_mode_set *set,
struct drm_modeset_acquire_ctx *ctx);
-
#endif