Skip to content

Commit

Permalink
drm/vmwgfx: Implement basic pm operations.
Browse files Browse the repository at this point in the history
Currently we really only support S3, since the device doesn't support
saving of the 3D state.

On S3/S4, move all buffer objects to swappable memory and take down
GMR bindings. We need to do that from a PM notifier since we can't
do persistant memory allocations from the standard PM callbacks.

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 Jan 14, 2010
1 parent e99e1e7 commit d9f36a0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
62 changes: 61 additions & 1 deletion drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx";

static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static void vmw_master_init(struct vmw_master *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);

static void vmw_print_capabilities(uint32_t capabilities)
{
Expand Down Expand Up @@ -352,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
vmw_fb_init(dev_priv);
}

dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);

return 0;

out_no_device:
Expand Down Expand Up @@ -386,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev)

DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");

unregister_pm_notifier(&dev_priv->pm_nb);

if (!dev_priv->stealth) {
vmw_fb_close(dev_priv);
vmw_kms_close(dev_priv);
Expand Down Expand Up @@ -651,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev)
drm_put_dev(dev);
}

static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr)
{
struct vmw_private *dev_priv =
container_of(nb, struct vmw_private, pm_nb);
struct vmw_master *vmaster = dev_priv->active_master;

switch (val) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
ttm_suspend_lock(&vmaster->lock);

/**
* This empties VRAM and unbinds all GMR bindings.
* Buffer contents is moved to swappable memory.
*/
ttm_bo_swapout_all(&dev_priv->bdev);
break;
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
ttm_suspend_unlock(&vmaster->lock);
break;
case PM_RESTORE_PREPARE:
break;
case PM_POST_RESTORE:
break;
default:
break;
}
return 0;
}

/**
* These might not be needed with the virtual SVGA device.
*/

int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}

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 struct drm_driver driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_MODESET,
Expand Down Expand Up @@ -690,7 +748,9 @@ static struct drm_driver driver = {
.name = VMWGFX_DRIVER_NAME,
.id_table = vmw_pci_id_list,
.probe = vmw_probe,
.remove = vmw_remove
.remove = vmw_remove,
.suspend = vmw_pci_suspend,
.resume = vmw_pci_resume
},
.name = VMWGFX_DRIVER_NAME,
.desc = VMWGFX_DRIVER_DESC,
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "drmP.h"
#include "vmwgfx_drm.h"
#include "drm_hashtab.h"
#include "linux/suspend.h"
#include "ttm/ttm_bo_driver.h"
#include "ttm/ttm_object.h"
#include "ttm/ttm_lock.h"
Expand Down Expand Up @@ -258,6 +259,7 @@ struct vmw_private {

struct vmw_master *active_master;
struct vmw_master fbdev_master;
struct notifier_block pm_nb;
};

static inline struct vmw_private *vmw_priv(struct drm_device *dev)
Expand Down

0 comments on commit d9f36a0

Please sign in to comment.