mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] DRM support for new pm_ops hooks
@ 2008-06-17 22:06 Jesse Barnes
  2008-06-18 20:35 ` Rafael J. Wysocki
  0 siblings, 1 reply; 2+ messages in thread
From: Jesse Barnes @ 2008-06-17 22:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: Rafael Wysocki, Dave Airlie

[-- Attachment #1: Type: text/plain, Size: 405 bytes --]

The PCI linux-next branch has support for the new PM ops hooks, so I thought I 
should refresh the DRM support for suspend/resume based on the new stuff.

I think we can get away with having drivers provide just save/restore hooks 
and let the core take care of the rest.  When we flesh out the 
prepare/complete hooks we may need another driver callback, not sure yet.

How does it look?

Thanks,
Jesse


[-- Attachment #2: i915-new-pm-ops-2.patch --]
[-- Type: text/x-diff, Size: 6912 bytes --]

diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 0764b66..f9d3eae 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -570,8 +570,8 @@ struct drm_driver {
 	void (*postclose) (struct drm_device *, struct drm_file *);
 	void (*lastclose) (struct drm_device *);
 	int (*unload) (struct drm_device *);
-	int (*suspend) (struct drm_device *, pm_message_t state);
-	int (*resume) (struct drm_device *);
+	int (*save) (struct drm_device *);
+	int (*restore) (struct drm_device *);
 	int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
 	void (*dma_ready) (struct drm_device *);
 	int (*dma_quiescent) (struct drm_device *);
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index af211a0..1cf426e 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -22,42 +22,107 @@
 #define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
 
 /**
- * drm_sysfs_suspend - DRM class suspend hook
+ * drm_prepare - DRM class prepare hook
  * @dev: Linux device to suspend
- * @state: power state to enter
  *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its suspend hook, if present.
+ * Suspend any DRM activity by putting clients to sleep, but don't touch
+ * hardware.
+ *
+ * Gets called before suspend, freeze, and poweroff.  Sleeping ok (though
+ * don't rely on userspace).
+ *
+ * Should prevent new DMA requests, device registration, etc., as well
+ * as wait for any outstanding requests to complete (except for maybe
+ * distant vblank events).
+ */
+static int drm_prepare(struct device *dev)
+{
+	/* FIXME: call into drivers etc. as needed */
+	return 0;
+}
+
+/**
+ * drm_complete - DRM class complete hook
+ * @dev: Linux device to suspend
+ *
+ * Finish a resume or restore.  Called after resume, thaw, and restore (or
+ * if suspend, freeze or poweroff fail).
  */
-static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+static void drm_complete(struct device *dev)
+{
+}
+
+static int drm_sysfs_save(struct device *dev)
 {
 	struct drm_minor *drm_minor = to_drm_minor(dev);
 	struct drm_device *drm_dev = drm_minor->dev;
 
-	if (drm_dev->driver->suspend)
-		return drm_dev->driver->suspend(drm_dev, state);
+	if (drm_dev->driver->save)
+		return drm_dev->driver->save(drm_dev);
+
+	return 0;
+}
+
+static int drm_sysfs_restore(struct device *dev)
+{
+	struct drm_minor *drm_minor = to_drm_minor(dev);
+	struct drm_device *drm_dev = drm_minor->dev;
+
+	if (drm_dev->driver->restore)
+		return drm_dev->driver->restore(drm_dev);
 
 	return 0;
 }
 
 /**
- * drm_sysfs_resume - DRM class resume hook
- * @dev: Linux device to resume
+ * drm_sysfs_poweroff - DRM class poweroff hook
+ * @dev: Linux device to power off
  *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its resume hook, if present.
+ * Put a device into low power state for suspend or hibernate
  */
-static int drm_sysfs_resume(struct device *dev)
+static int drm_sysfs_poweroff(struct device *dev)
 {
 	struct drm_minor *drm_minor = to_drm_minor(dev);
 	struct drm_device *drm_dev = drm_minor->dev;
 
-	if (drm_dev->driver->resume)
-		return drm_dev->driver->resume(drm_dev);
+	/* Shut down the device */
+	pci_disable_device(drm_dev->pdev);
+	pci_set_power_state(drm_dev->pdev, PCI_D3hot);
 
 	return 0;
 }
 
+/**
+ * drm_sysfs_suspend - DRM class suspend hook
+ * @dev: Linux device to suspend
+ *
+ * Just figures out what the actual struct drm_device associated with
+ * @dev is and calls its suspend hook, if present.
+ */
+static int drm_sysfs_suspend(struct device *dev)
+{
+	int ret = 0;
+
+	/* Suspend is just save, poweroff */
+	ret = drm_sysfs_save(dev);
+	if (ret)
+		return ret;
+
+	return drm_sysfs_poweroff(dev);
+}
+
+/**
+ * drm_sysfs_resume - DRM class resume hook
+ * @dev: Linux device to resume
+ *
+ * Just figures out what the actual struct drm_device associated with
+ * @dev is and calls its resume hook, if present.
+ */
+static int drm_sysfs_resume(struct device *dev)
+{
+	return drm_sysfs_restore(dev);
+}
+
 /* Display the version of drm_core. This doesn't work right in current design */
 static ssize_t version_show(struct class *dev, char *buf)
 {
@@ -67,6 +132,16 @@ static ssize_t version_show(struct class *dev, char *buf)
 
 static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
 
+static struct pm_ops drm_pm_ops = {
+	.prepare = drm_prepare,
+	.complete = drm_complete,
+	.poweroff = drm_sysfs_poweroff,
+	.suspend = drm_sysfs_suspend,
+	.resume = drm_sysfs_resume,
+	.freeze = drm_sysfs_save,
+	.restore = drm_sysfs_restore,
+};
+
 /**
  * drm_sysfs_create - create a struct drm_sysfs_class structure
  * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
@@ -89,8 +164,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
 		goto err_out;
 	}
 
-	class->suspend = drm_sysfs_suspend;
-	class->resume = drm_sysfs_resume;
+	class->pm = &drm_pm_ops;
 
 	err = class_create_file(class, &class_attr_version);
 	if (err)
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index e8f3d68..a014aa9 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -239,7 +239,7 @@ static void i915_restore_vga(struct drm_device *dev)
 
 }
 
-static int i915_suspend(struct drm_device *dev, pm_message_t state)
+static int i915_save(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
@@ -250,10 +250,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 		return -ENODEV;
 	}
 
-	if (state.event == PM_EVENT_PRETHAW)
-		return 0;
-
-	pci_save_state(dev->pdev);
 	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
 	/* Display arbitration control */
@@ -371,24 +367,15 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
 	i915_save_vga(dev);
 
-	if (state.event == PM_EVENT_SUSPEND) {
-		/* Shut down the device */
-		pci_disable_device(dev->pdev);
-		pci_set_power_state(dev->pdev, PCI_D3hot);
-	}
-
 	return 0;
 }
 
-static int i915_resume(struct drm_device *dev)
+static int i915_restore(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int i;
 
 	pci_set_power_state(dev->pdev, PCI_D0);
-	pci_restore_state(dev->pdev);
-	if (pci_enable_device(dev->pdev))
-		return -1;
 
 	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
@@ -544,10 +531,10 @@ static struct drm_driver driver = {
 	    DRIVER_IRQ_VBL2,
 	.load = i915_driver_load,
 	.unload = i915_driver_unload,
+	.save = i915_save,
+	.restore = i915_restore,
 	.lastclose = i915_driver_lastclose,
 	.preclose = i915_driver_preclose,
-	.suspend = i915_suspend,
-	.resume = i915_resume,
 	.device_is_agp = i915_driver_device_is_agp,
 	.vblank_wait = i915_driver_vblank_wait,
 	.vblank_wait2 = i915_driver_vblank_wait2,

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-06-18 20:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-17 22:06 [PATCH] DRM support for new pm_ops hooks Jesse Barnes
2008-06-18 20:35 ` Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®