diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-02-18 17:06:27 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-22 11:47:14 -0500 |
| commit | 61caf87cb5c2a198966018343a6ce4c5ab6cf8df (patch) | |
| tree | 4fa1ab6a366627a8d3113b4be62f9c251307a00a | |
| parent | 4386b58349366511df1c4fe1f7917c198f71529a (diff) | |
i915 / PM: Fix hibernate regression caused by suspend/resume splitting
Commit 84b79f8d2882b0a84330c04839ed4d3cefd2ff77 (drm/i915: Fix crash
while aborting hibernation) attempted to fix a regression introduced
by commit cbda12d77ea590082edb6d30bd342a67ebc459e0 (drm/i915:
implement new pm ops for i915), but it went too far trying to split
the freeze/suspend and resume/thaw parts of the code. As a result,
it introduced another regression, which only is visible on some systems.
Fix the problem by merging i915_drm_suspend() with
i915_drm_freeze() and moving some code from i915_resume()
into i915_drm_thaw(), so that intel_opregion_free() and
intel_opregion_init() are also executed in the freeze and thaw code
paths, respectively.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reported-and-tested-by: Pedro Ribeiro <pedrib@gmail.com>
Tested-by: Tino Keitel <tino.keitel@tikei.de>
Acked-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 30 |
1 files changed, 9 insertions, 21 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 79beffcf5936..cf4cb3e9a0c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -176,6 +176,8 @@ MODULE_DEVICE_TABLE(pci, pciidlist); | |||
| 176 | 176 | ||
| 177 | static int i915_drm_freeze(struct drm_device *dev) | 177 | static int i915_drm_freeze(struct drm_device *dev) |
| 178 | { | 178 | { |
| 179 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 180 | |||
| 179 | pci_save_state(dev->pdev); | 181 | pci_save_state(dev->pdev); |
| 180 | 182 | ||
| 181 | /* If KMS is active, we do the leavevt stuff here */ | 183 | /* If KMS is active, we do the leavevt stuff here */ |
| @@ -191,17 +193,12 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
| 191 | 193 | ||
| 192 | i915_save_state(dev); | 194 | i915_save_state(dev); |
| 193 | 195 | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static void i915_drm_suspend(struct drm_device *dev) | ||
| 198 | { | ||
| 199 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 200 | |||
| 201 | intel_opregion_free(dev, 1); | 196 | intel_opregion_free(dev, 1); |
| 202 | 197 | ||
| 203 | /* Modeset on resume, not lid events */ | 198 | /* Modeset on resume, not lid events */ |
| 204 | dev_priv->modeset_on_lid = 0; | 199 | dev_priv->modeset_on_lid = 0; |
| 200 | |||
| 201 | return 0; | ||
| 205 | } | 202 | } |
| 206 | 203 | ||
| 207 | static int i915_suspend(struct drm_device *dev, pm_message_t state) | 204 | static int i915_suspend(struct drm_device *dev, pm_message_t state) |
| @@ -221,8 +218,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 221 | if (error) | 218 | if (error) |
| 222 | return error; | 219 | return error; |
| 223 | 220 | ||
| 224 | i915_drm_suspend(dev); | ||
| 225 | |||
| 226 | if (state.event == PM_EVENT_SUSPEND) { | 221 | if (state.event == PM_EVENT_SUSPEND) { |
| 227 | /* Shut down the device */ | 222 | /* Shut down the device */ |
| 228 | pci_disable_device(dev->pdev); | 223 | pci_disable_device(dev->pdev); |
| @@ -237,6 +232,10 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
| 237 | struct drm_i915_private *dev_priv = dev->dev_private; | 232 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 238 | int error = 0; | 233 | int error = 0; |
| 239 | 234 | ||
| 235 | i915_restore_state(dev); | ||
| 236 | |||
| 237 | intel_opregion_init(dev, 1); | ||
| 238 | |||
| 240 | /* KMS EnterVT equivalent */ | 239 | /* KMS EnterVT equivalent */ |
| 241 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 240 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 242 | mutex_lock(&dev->struct_mutex); | 241 | mutex_lock(&dev->struct_mutex); |
| @@ -263,10 +262,6 @@ static int i915_resume(struct drm_device *dev) | |||
| 263 | 262 | ||
| 264 | pci_set_master(dev->pdev); | 263 | pci_set_master(dev->pdev); |
| 265 | 264 | ||
| 266 | i915_restore_state(dev); | ||
| 267 | |||
| 268 | intel_opregion_init(dev, 1); | ||
| 269 | |||
| 270 | return i915_drm_thaw(dev); | 265 | return i915_drm_thaw(dev); |
| 271 | } | 266 | } |
| 272 | 267 | ||
| @@ -423,8 +418,6 @@ static int i915_pm_suspend(struct device *dev) | |||
| 423 | if (error) | 418 | if (error) |
| 424 | return error; | 419 | return error; |
| 425 | 420 | ||
| 426 | i915_drm_suspend(drm_dev); | ||
| 427 | |||
| 428 | pci_disable_device(pdev); | 421 | pci_disable_device(pdev); |
| 429 | pci_set_power_state(pdev, PCI_D3hot); | 422 | pci_set_power_state(pdev, PCI_D3hot); |
| 430 | 423 | ||
| @@ -464,13 +457,8 @@ static int i915_pm_poweroff(struct device *dev) | |||
| 464 | { | 457 | { |
| 465 | struct pci_dev *pdev = to_pci_dev(dev); | 458 | struct pci_dev *pdev = to_pci_dev(dev); |
| 466 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | 459 | struct drm_device *drm_dev = pci_get_drvdata(pdev); |
| 467 | int error; | ||
| 468 | |||
| 469 | error = i915_drm_freeze(drm_dev); | ||
| 470 | if (!error) | ||
| 471 | i915_drm_suspend(drm_dev); | ||
| 472 | 460 | ||
| 473 | return error; | 461 | return i915_drm_freeze(drm_dev); |
| 474 | } | 462 | } |
| 475 | 463 | ||
| 476 | const struct dev_pm_ops i915_pm_ops = { | 464 | const struct dev_pm_ops i915_pm_ops = { |
