diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2015-06-23 09:25:02 +0200 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2015-06-23 09:40:10 +0200 |
commit | 370a85e9c25bc91d9a92655a250ad336a8b89735 (patch) | |
tree | baf820e837d58dc841ed15598d50ff82f404cb2a | |
parent | 78e1ab55c7cdfb87d1ab08e02a4dc5422aaef810 (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.c | 48 |
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; } |