Skip to content

Commit

Permalink
drm/vmwgfx: Add new-style PM hooks to improve hibernation behavior
Browse files Browse the repository at this point in the history
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: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Thomas Hellstrom authored and Dave Airlie committed Oct 6, 2010
1 parent 094e0fa commit 7fbd721
Showing 1 changed file with 79 additions and 34 deletions.
113 changes: 79 additions & 34 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 7fbd721

Please sign in to comment.