summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2015-06-23 09:25:02 +0200
committerThomas Hellstrom <thellstrom@vmware.com>2015-06-23 09:40:10 +0200
commit370a85e9c25bc91d9a92655a250ad336a8b89735 (patch)
treebaf820e837d58dc841ed15598d50ff82f404cb2a
parent78e1ab55c7cdfb87d1ab08e02a4dc5422aaef810 (diff)
vmwgfx: Fix a hibernation error path
If fifo resources for some reason are active when we hibernate (which is an error in itself), the hibernation code refuses to hibernate and enters an error path. A recent code rewrite caused a regression that caused the device not to be setup properly when recovering from the initial stages of hibernation. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
-rw-r--r--vmwgfx_drv.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/vmwgfx_drv.c b/vmwgfx_drv.c
index 5ad195a..692ece3 100644
--- a/vmwgfx_drv.c
+++ b/vmwgfx_drv.c
@@ -356,27 +356,26 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
return ret;
}
-
-static int vmw_request_device(struct vmw_private *dev_priv)
+/**
+ * vmw_request_device_late - Perform late device setup
+ *
+ * @dev_priv: Pointer to device private.
+ *
+ * This function performs setup of otables and enables large command
+ * buffer submission. These tasks are split out to a separate function
+ * because it reverts vmw_release_device_early and is intended to be used
+ * by an error path in the hibernation code.
+ */
+static int vmw_request_device_late(struct vmw_private *dev_priv)
{
int ret;
- ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Unable to initialize FIFO.\n");
- return ret;
- }
- vmw_fence_fifo_up(dev_priv->fman);
- dev_priv->cman = vmw_cmdbuf_man_create(dev_priv);
- if (IS_ERR(dev_priv->cman))
- dev_priv->cman = NULL;
-
if (dev_priv->has_mob) {
ret = vmw_otables_setup(dev_priv);
if (unlikely(ret != 0)) {
DRM_ERROR("Unable to initialize "
"guest Memory OBjects.\n");
- goto out_no_mob;
+ return ret;
}
}
@@ -391,6 +390,27 @@ static int vmw_request_device(struct vmw_private *dev_priv)
}
}
+ return 0;
+}
+
+static int vmw_request_device(struct vmw_private *dev_priv)
+{
+ int ret;
+
+ ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Unable to initialize FIFO.\n");
+ return ret;
+ }
+ vmw_fence_fifo_up(dev_priv->fman);
+ dev_priv->cman = vmw_cmdbuf_man_create(dev_priv);
+ if (IS_ERR(dev_priv->cman))
+ dev_priv->cman = NULL;
+
+ ret = vmw_request_device_late(dev_priv);
+ if (ret)
+ goto out_no_mob;
+
ret = vmw_dummy_query_bo_create(dev_priv);
if (unlikely(ret != 0))
goto out_no_query_bo;
@@ -1341,6 +1361,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
break;
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
+ vmw_fence_fifo_up(dev_priv->fman);
ttm_suspend_unlock(&dev_priv->reservation_sem);
break;
default:
@@ -1401,6 +1422,7 @@ static int vmw_pm_freeze(struct device *kdev)
DRM_ERROR("Can't hibernate while 3D resources are active.\n");
if (dev_priv->enable_fb)
vmw_fifo_resource_inc(dev_priv);
+ WARN_ON(vmw_request_device_late(dev_priv));
dev_priv->suspended = false;
return -EBUSY;
}