[PATCH] drm/radeon: s2disk: Leave hw powered between freeze()

Jerome Glisse j.glisse at gmail.com
Thu Jun 18 20:16:57 PDT 2015


On Fri, Jun 12, 2015 at 09:21:40PM +0200, Oliver Winker wrote:
> Hello,
> 
> Below a patch [2] on v4.0 that significantly improves s2disk on my system with 
> a HD7850 [1] with an HDMI screen. 
> 
> It basically avoids powering down the card hw too much on the system-snapshot 
> between freeze() and thaw(). 
> 
> Before this patch I had to deactivate dpm to get s2disk at least kind of 
> working. Since I activated dpm (for the silent fans), s2disk didn't work 
> anymore at all. 
> 
> Also the stop/start of the card was really feeling heavy on my system, with 
> the monitor going into standby due to the signal loss, to be directly squeezed 
> back on thaw() - not easy for a heavy piece of hw like a 3d gfx-card.
> 
> With the patch the card hw stays mostly up on freeze(), only dma and irqs 
> disabled, then image snapshot is made, and then the card hw is released again. 
> Much less heavy, smoother and faster (click-clack and it's done). 
> 
> I tested this during a week and on my system s2disk with dpm activated works 
> much better now!
> 
> Now the patch is basically an experimental guess -  I just post it as feedback 
> for the devs for a possible improvement of the pm with freeze()/thaw(). But 
> I'm quite satisfied this the result ;-).


Just to make sure we are on same page, it is the image creation that is
problematic for you ? Not the resume from disk part, correct ?

While i think the part about not suspending the display make sense, i am
more reluctant about the part not suspending the GPU. Mostly because the
idea of freeze is to make sure nothing move and if we do not suspend the
various GPU rings that things can change (all the wb pointer for instance)
which might lead to an incoherent snapshot (for instance rptr/wptr of a ring
would be from earlier version in the snapshot than what the ring content the
snapshot capture).

I agree that this is unlikely given that before suspend we wait for all
rings to drain and at that point the userspace is frozen and thus nothing
should happen and GPU should stay idle. But i still feel that somehow
something might go wrong with your approach.

Anyway as it is your patch would break runtime suspend.

I recently posted patch to fix the resume side of hibernation, they might
also help in the freeze()/thaw() dance. Could you please test them without
your patch :
https://patchwork.kernel.org/patch/6641371/
https://patchwork.kernel.org/patch/6641381/

If it is not enough than also try with attached patch (which i have not
tested myself but i think the logic is right).


Cheers,
Jérôme


> Cheers, Oliver
> 
> [1] 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] 
> Pitcairn PRO [Radeon HD 7850] (prog-if 00 [VGA controller])
>         Subsystem: PC Partner Limited / Sapphire Technology Radeon HD 7850 2GB 
> GDDR5 DVI-I/DVI-D/HDMI/DP
>         Flags: bus master, fast devsel, latency 0, IRQ 37
>         Memory at e0000000 (64-bit, prefetchable) [size=256M]
>         Memory at f5000000 (64-bit, non-prefetchable) [size=256K]
>         I/O ports at a000 [size=256]
>         [virtual] Expansion ROM at f4000000 [disabled] [size=128K]
>         Capabilities: [48] Vendor Specific Information: Len=08 <?>
>         Capabilities: [50] Power Management version 3
>         Capabilities: [58] Express Legacy Endpoint, MSI 00
>         Capabilities: [a0] MSI: Enable+ Count=1/1 Maskable- 64bit+
>         Capabilities: [100] Vendor Specific Information: ID=0001 Rev=1 Len=010 
> <?>
>         Capabilities: [150] Advanced Error Reporting
>         Capabilities: [270] #19
>         Capabilities: [2b0] Address Translation Service (ATS)
>         Capabilities: [2c0] #13
>         Capabilities: [2d0] #1b
>         Kernel driver in use: radeon
> 
> 
> [2]
> 
> From e2018b5ea38c0fffa5a22ac306b2b80c470bfd87 Mon Sep 17 00:00:00 2001
> From: Oliver Winker <oliver at oli1170.net>
> Date: Sun, 7 Jun 2015 11:23:14 +0200
> Subject: [PATCH] WIP: drm/radeon: s2disk: Leave hw powered between freeze()
>  and thaw()
> 
> This allows a much smoother transition of the hw from freeze() back to thaw() 
> on s2disk.
> ---
>  drivers/gpu/drm/radeon/radeon_device.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
> b/drivers/gpu/drm/radeon/radeon_device.c
> index bd7519f..21c4223 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -1547,10 +1547,12 @@ int radeon_suspend_kms(struct drm_device *dev, bool 
> suspend, bool fbcon)
>  
>  	drm_kms_helper_poll_disable(dev);
>  
> +	if (suspend) {
>  	/* turn off display hw */
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
>  		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
>  	}
> +	}
>  
>  	/* unpin the front buffers */
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> @@ -1584,12 +1586,14 @@ int radeon_suspend_kms(struct drm_device *dev, bool 
> suspend, bool fbcon)
>  
>  	radeon_save_bios_scratch_regs(rdev);
>  
> +	if (suspend) {
>  	radeon_suspend(rdev);
>  	radeon_hpd_fini(rdev);
>  	/* evict remaining vram memory */
>  	radeon_bo_evict_vram(rdev);
>  
>  	radeon_agp_suspend(rdev);
> +	}
>  
>  	pci_save_state(dev->pdev);
>  	if (suspend) {
> @@ -1636,6 +1640,8 @@ int radeon_resume_kms(struct drm_device *dev, bool 
> resume, bool fbcon)
>  			return -1;
>  		}
>  	}
> +
> +	if (resume) {
>  	/* resume AGP if in use */
>  	radeon_agp_resume(rdev);
>  	radeon_resume(rdev);
> @@ -1655,6 +1661,7 @@ int radeon_resume_kms(struct drm_device *dev, bool 
> resume, bool fbcon)
>  		/* resume old pm late */
>  		radeon_pm_resume(rdev);
>  	}
> +	}
>  
>  	radeon_restore_bios_scratch_regs(rdev);
>  
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> xorg-driver-ati mailing list
> xorg-driver-ati at lists.x.org
> http://lists.x.org/mailman/listinfo/xorg-driver-ati
-------------- next part --------------
>From 54307edfe2faa0c13fe3010c9135c0dc746375fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Glisse?= <jglisse at redhat.com>
Date: Thu, 18 Jun 2015 22:48:54 -0400
Subject: [PATCH] drm/radeon: rework device power management for radeon.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

For hibernation between freeze() and thaw() do not suspend the GPU,
just wait for GPU to drains all its work queue. For regular resume/
suspend (or power on/off) turn screen off, suspend console, stop GPU
and save PCI state. Finaly for runtime power management turn screen
off and stop GPU.

Signed-off-by: Oliver Winker <oliver at oli1170.net>
Signed-off-by: Jérôme Glisse <jglisse at redhat.com>
---
 drivers/gpu/drm/radeon/radeon.h        |   4 +-
 drivers/gpu/drm/radeon/radeon_device.c | 175 ++++++++++++++++++---------------
 drivers/gpu/drm/radeon/radeon_drv.c    |  25 +++--
 drivers/gpu/drm/radeon/radeon_family.h |  16 +++
 4 files changed, 129 insertions(+), 91 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 46eb0fa..de0609f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -2988,8 +2988,8 @@ extern bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm);
 extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm);
 extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
 extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
-extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
-extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
+extern int radeon_resume_kms(struct drm_device *dev, enum radeon_pm_state state);
+extern int radeon_suspend_kms(struct drm_device *dev, enum radeon_pm_state state);
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 extern void radeon_program_register_sequence(struct radeon_device *rdev,
 					     const u32 *registers,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index a7fdfa4..5117874 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1214,7 +1214,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
 		if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
 			dev->pdev->d3_delay = 20;
 
-		radeon_resume_kms(dev, true, true);
+		radeon_resume_kms(dev, RADEON_PM_RESUME);
 
 		dev->pdev->d3_delay = d3_delay;
 
@@ -1224,7 +1224,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
 		printk(KERN_INFO "radeon: switched off\n");
 		drm_kms_helper_poll_disable(dev);
 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
-		radeon_suspend_kms(dev, true, true);
+		radeon_suspend_kms(dev, RADEON_PM_SUSPEND);
 		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
 	}
 }
@@ -1543,13 +1543,13 @@ void radeon_device_fini(struct radeon_device *rdev)
  * radeon_suspend_kms - initiate device suspend
  *
  * @pdev: drm dev pointer
- * @state: suspend state
+ * @state: suspend to state
  *
  * Puts the hw in the suspend state (all asics).
  * Returns 0 for success or an error on failure.
  * Called at driver suspend.
  */
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
+int radeon_suspend_kms(struct drm_device *dev, enum radeon_pm_state state)
 {
 	struct radeon_device *rdev;
 	struct drm_crtc *crtc;
@@ -1565,33 +1565,39 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
+	/*
+	 * This is not symetrical for freeze() and thaw() but its fine
+	 * as during thaw() we do not care for screen hotplug really.
+	 */
 	drm_kms_helper_poll_disable(dev);
 
-	/* turn off display hw */
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-	}
+	if (state != RADEON_PM_FREEZE) {
+		/* turn off display hw */
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		}
 
-	/* unpin the front buffers */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb);
-		struct radeon_bo *robj;
+		/* unpin the front buffers */
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb);
+			struct radeon_bo *robj;
 
-		if (rfb == NULL || rfb->obj == NULL) {
-			continue;
-		}
-		robj = gem_to_radeon_bo(rfb->obj);
-		/* don't unpin kernel fb objects */
-		if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
-			r = radeon_bo_reserve(robj, false);
-			if (r == 0) {
-				radeon_bo_unpin(robj);
-				radeon_bo_unreserve(robj);
+			if (rfb == NULL || rfb->obj == NULL) {
+				continue;
+			}
+			robj = gem_to_radeon_bo(rfb->obj);
+			/* don't unpin kernel fb objects */
+			if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
+				r = radeon_bo_reserve(robj, false);
+				if (r == 0) {
+					radeon_bo_unpin(robj);
+					radeon_bo_unreserve(robj);
+				}
 			}
 		}
+		/* evict vram memory */
+		radeon_bo_evict_vram(rdev);
 	}
-	/* evict vram memory */
-	radeon_bo_evict_vram(rdev);
 
 	/* wait for gpu to finish processing current batch */
 	for (i = 0; i < RADEON_NUM_RINGS; i++) {
@@ -1602,23 +1608,23 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 		}
 	}
 
-	radeon_save_bios_scratch_regs(rdev);
+	if (state != RADEON_PM_FREEZE) {
+		radeon_save_bios_scratch_regs(rdev);
 
-	radeon_suspend(rdev);
-	radeon_hpd_fini(rdev);
-	/* evict remaining vram memory */
-	radeon_bo_evict_vram(rdev);
+		radeon_suspend(rdev);
+		radeon_hpd_fini(rdev);
+		/* evict remaining vram memory */
+		radeon_bo_evict_vram(rdev);
 
-	radeon_agp_suspend(rdev);
+		radeon_agp_suspend(rdev);
+	}
 
-	pci_save_state(dev->pdev);
-	if (suspend) {
+	if (state == RADEON_PM_SUSPEND) {
+		pci_save_state(dev->pdev);
 		/* Shut down the device */
 		pci_disable_device(dev->pdev);
 		pci_set_power_state(dev->pdev, PCI_D3hot);
-	}
 
-	if (fbcon) {
 		console_lock();
 		radeon_fbdev_set_suspend(rdev, 1);
 		console_unlock();
@@ -1630,12 +1636,13 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
  * radeon_resume_kms - initiate device resume
  *
  * @pdev: drm dev pointer
+ * @state: resume from state
  *
  * Bring the hw back to operating state (all asics).
  * Returns 0 for success or an error on failure.
  * Called at driver resume.
  */
-int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
+int radeon_resume_kms(struct drm_device *dev, enum radeon_pm_state state)
 {
 	struct drm_connector *connector;
 	struct radeon_device *rdev = dev->dev_private;
@@ -1644,70 +1651,78 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	if (fbcon) {
+	if (state == RADEON_PM_RESUME) {
 		console_lock();
-	}
-	if (resume) {
 		pci_set_power_state(dev->pdev, PCI_D0);
 		pci_restore_state(dev->pdev);
 		if (pci_enable_device(dev->pdev)) {
-			if (fbcon)
-				console_unlock();
+			console_unlock();
 			return -1;
 		}
 	}
-	/* resume AGP if in use */
-	radeon_agp_resume(rdev);
-	radeon_resume(rdev);
 
-	r = radeon_ib_ring_tests(rdev);
-	if (r)
-		DRM_ERROR("ib ring test failed (%d).\n", r);
+	if (state != RADEON_PM_THAW) {
+		/* resume AGP if in use */
+		radeon_agp_resume(rdev);
+		radeon_resume(rdev);
 
-	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
-		/* do dpm late init */
-		r = radeon_pm_late_init(rdev);
-		if (r) {
-			rdev->pm.dpm_enabled = false;
-			DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+		r = radeon_ib_ring_tests(rdev);
+		if (r)
+			DRM_ERROR("ib ring test failed (%d).\n", r);
+
+		if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
+		    rdev->pm.dpm_enabled) {
+			/* do dpm late init */
+			r = radeon_pm_late_init(rdev);
+			if (r) {
+				rdev->pm.dpm_enabled = false;
+				DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+			}
+		} else {
+			/* resume old pm late */
+			radeon_pm_resume(rdev);
 		}
-	} else {
-		/* resume old pm late */
-		radeon_pm_resume(rdev);
-	}
-
-	radeon_restore_bios_scratch_regs(rdev);
 
-	/* init dig PHYs, disp eng pll */
-	if (rdev->is_atom_bios) {
-		radeon_atom_encoder_init(rdev);
-		radeon_atom_disp_eng_pll_init(rdev);
-		/* turn on the BL */
-		if (rdev->mode_info.bl_encoder) {
-			u8 bl_level = radeon_get_backlight_level(rdev,
-								 rdev->mode_info.bl_encoder);
-			radeon_set_backlight_level(rdev, rdev->mode_info.bl_encoder,
-						   bl_level);
+		radeon_restore_bios_scratch_regs(rdev);
+
+		/* init dig PHYs, disp eng pll */
+		if (rdev->is_atom_bios) {
+			radeon_atom_encoder_init(rdev);
+			radeon_atom_disp_eng_pll_init(rdev);
+			/* turn on the BL */
+			if (rdev->mode_info.bl_encoder) {
+				u8 bl_level = radeon_get_backlight_level(rdev,
+						rdev->mode_info.bl_encoder);
+				radeon_set_backlight_level(rdev,
+						rdev->mode_info.bl_encoder,
+						bl_level);
+			}
 		}
-	}
-	/* reset hpd state */
-	radeon_hpd_init(rdev);
-	/* blat the mode back in */
-	if (fbcon) {
-		drm_helper_resume_force_mode(dev);
-		/* turn on display hw */
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+		/* reset hpd state */
+		radeon_hpd_init(rdev);
+
+		/* blat the mode back in */
+		if (state != RADEON_PM_RUNTIME_RESUME) {
+			drm_helper_resume_force_mode(dev);
+			/* turn on display hw */
+			list_for_each_entry(connector,
+				&dev->mode_config.connector_list, head) {
+				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+			}
 		}
-	}
 
-	drm_kms_helper_poll_enable(dev);
+		/*
+		 * This is not symetrical for freeze() and thaw() but its fine
+		 * as during thaw() we do not care for screen hotplug really.
+		 */
+		drm_kms_helper_poll_enable(dev);
+	}
 
 	/* set the power state here in case we are a PX system or headless */
 	if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
 		radeon_pm_compute_clocks(rdev);
 
-	if (fbcon) {
+	if (state == RADEON_PM_RESUME) {
 		radeon_fbdev_set_suspend(rdev, 0);
 		console_unlock();
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 7d620d4..673a4c0 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -102,8 +102,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
 				 struct drm_file *file_priv);
 void radeon_driver_preclose_kms(struct drm_device *dev,
 				struct drm_file *file_priv);
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
-int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
+int radeon_suspend_kms(struct drm_device *dev, enum radeon_pm_state state);
+int radeon_resume_kms(struct drm_device *dev, enum radeon_pm_state state);
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
 int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
 void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
@@ -420,28 +420,35 @@ static int radeon_pmops_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_suspend_kms(drm_dev, true, true);
+	return radeon_suspend_kms(drm_dev, RADEON_PM_SUSPEND);
 }
 
 static int radeon_pmops_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_resume_kms(drm_dev, true, true);
+	return radeon_resume_kms(drm_dev, RADEON_PM_RESUME);
 }
 
 static int radeon_pmops_freeze(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_suspend_kms(drm_dev, false, true);
+	return radeon_suspend_kms(drm_dev, RADEON_PM_FREEZE);
+}
+
+static int radeon_pmops_poweroff(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	return radeon_suspend_kms(drm_dev, RADEON_PM_POWEROFF);
 }
 
 static int radeon_pmops_thaw(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_resume_kms(drm_dev, false, true);
+	return radeon_resume_kms(drm_dev, RADEON_PM_THAW);
 }
 
 static int radeon_pmops_runtime_suspend(struct device *dev)
@@ -459,7 +466,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
 	drm_kms_helper_poll_disable(drm_dev);
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
 
-	ret = radeon_suspend_kms(drm_dev, false, false);
+	ret = radeon_suspend_kms(drm_dev, RADEON_PM_RUNTIME_SUSPEND);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	pci_ignore_hotplug(pdev);
@@ -487,7 +494,7 @@ static int radeon_pmops_runtime_resume(struct device *dev)
 		return ret;
 	pci_set_master(pdev);
 
-	ret = radeon_resume_kms(drm_dev, false, false);
+	ret = radeon_resume_kms(drm_dev, RADEON_PM_RUNTIME_RESUME);
 	drm_kms_helper_poll_enable(drm_dev);
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
@@ -541,7 +548,7 @@ static const struct dev_pm_ops radeon_pm_ops = {
 	.resume = radeon_pmops_resume,
 	.freeze = radeon_pmops_freeze,
 	.thaw = radeon_pmops_thaw,
-	.poweroff = radeon_pmops_freeze,
+	.poweroff = radeon_pmops_poweroff,
 	.restore = radeon_pmops_resume,
 	.runtime_suspend = radeon_pmops_runtime_suspend,
 	.runtime_resume = radeon_pmops_runtime_resume,
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h
index 4b7b87f..f6078f5 100644
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -119,4 +119,20 @@ enum radeon_chip_flags {
 	RADEON_IS_PX = 0x02000000UL,
 };
 
+/*
+ * Sadly there is no easy common place share btw radeon_drv.c and rest of kms
+ * code to define enum. So for lack of better place, here are the enum for the
+ * power management states.
+ */
+enum radeon_pm_state {
+	RADEON_PM_FREEZE,
+	RADEON_PM_POWEROFF,
+	RADEON_PM_SUSPEND,
+	RADEON_PM_RUNTIME_SUSPEND,
+
+	RADEON_PM_RESUME,
+	RADEON_PM_RUNTIME_RESUME,
+	RADEON_PM_THAW,
+};
+
 #endif
-- 
2.1.0



More information about the xorg-driver-ati mailing list