Commit 7fbd721a authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

drm/vmwgfx: Add new-style PM hooks to improve hibernation behavior

Add the new-style PM hooks prepare and complete. This allows us to
power up the device again after the hibernation image has been created, and
display output will thus be active until the VM is finally powered off.
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 094e0fa8
......@@ -752,34 +752,10 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
*/
ttm_bo_swapout_all(&dev_priv->bdev);
/**
* Release 3d reference held by fbdev and potentially
* stop fifo.
*/
dev_priv->suspended = true;
if (dev_priv->enable_fb)
vmw_3d_resource_dec(dev_priv);
break;
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
case PM_POST_RESTORE:
if (!dev_priv->suspended) {
printk(KERN_WARNING
"[%s] Driver is not suspended at resume"
" point.\n", VMWGFX_DRIVER_NAME);
break;
}
/**
* Reclaim 3d reference held by fbdev and potentially
* start fifo.
*/
if (dev_priv->enable_fb)
vmw_3d_resource_inc(dev_priv);
dev_priv->suspended = false;
ttm_suspend_unlock(&vmaster->lock);
break;
......@@ -795,7 +771,7 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
* These might not be needed with the virtual SVGA device.
*/
int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
......@@ -812,13 +788,81 @@ int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
int vmw_pci_resume(struct pci_dev *pdev)
static int vmw_pci_resume(struct pci_dev *pdev)
{
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
return pci_enable_device(pdev);
}
static int vmw_pm_suspend(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct pm_message dummy;
dummy.event = 0;
return vmw_pci_suspend(pdev, dummy);
}
static int vmw_pm_resume(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
return vmw_pci_resume(pdev);
}
static int vmw_pm_prepare(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
/**
* Release 3d reference held by fbdev and potentially
* stop fifo.
*/
dev_priv->suspended = true;
if (dev_priv->enable_fb)
vmw_3d_resource_dec(dev_priv);
if (dev_priv->num_3d_resources != 0) {
DRM_INFO("Can't suspend or hibernate "
"while 3D resources are active.\n");
if (dev_priv->enable_fb)
vmw_3d_resource_inc(dev_priv);
dev_priv->suspended = false;
return -EBUSY;
}
return 0;
}
static void vmw_pm_complete(struct device *kdev)
{
struct pci_dev *pdev = to_pci_dev(kdev);
struct drm_device *dev = pci_get_drvdata(pdev);
struct vmw_private *dev_priv = vmw_priv(dev);
/**
* Reclaim 3d reference held by fbdev and potentially
* start fifo.
*/
if (dev_priv->enable_fb)
vmw_3d_resource_inc(dev_priv);
dev_priv->suspended = false;
}
static const struct dev_pm_ops vmw_pm_ops = {
.prepare = vmw_pm_prepare,
.complete = vmw_pm_complete,
.suspend = vmw_pm_suspend,
.resume = vmw_pm_resume,
};
static struct drm_driver driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_MODESET,
......@@ -852,15 +896,16 @@ static struct drm_driver driver = {
#if defined(CONFIG_COMPAT)
.compat_ioctl = drm_compat_ioctl,
#endif
},
},
.pci_driver = {
.name = VMWGFX_DRIVER_NAME,
.id_table = vmw_pci_id_list,
.probe = vmw_probe,
.remove = vmw_remove,
.suspend = vmw_pci_suspend,
.resume = vmw_pci_resume
},
.name = VMWGFX_DRIVER_NAME,
.id_table = vmw_pci_id_list,
.probe = vmw_probe,
.remove = vmw_remove,
.driver = {
.pm = &vmw_pm_ops
}
},
.name = VMWGFX_DRIVER_NAME,
.desc = VMWGFX_DRIVER_DESC,
.date = VMWGFX_DRIVER_DATE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment