Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Rafael J. Wysocki and committed by
Linus Torvalds
61caf87c 4386b583

+9 -21
+9 -21
drivers/gpu/drm/i915/i915_drv.c
··· 176 176 177 177 static int i915_drm_freeze(struct drm_device *dev) 178 178 { 179 + struct drm_i915_private *dev_priv = dev->dev_private; 180 + 179 181 pci_save_state(dev->pdev); 180 182 181 183 /* If KMS is active, we do the leavevt stuff here */ ··· 193 191 194 192 i915_save_state(dev); 195 193 196 - return 0; 197 - } 198 - 199 - static void i915_drm_suspend(struct drm_device *dev) 200 - { 201 - struct drm_i915_private *dev_priv = dev->dev_private; 202 - 203 194 intel_opregion_free(dev, 1); 204 195 205 196 /* Modeset on resume, not lid events */ 206 197 dev_priv->modeset_on_lid = 0; 198 + 199 + return 0; 207 200 } 208 201 209 202 static int i915_suspend(struct drm_device *dev, pm_message_t state) ··· 218 221 if (error) 219 222 return error; 220 223 221 - i915_drm_suspend(dev); 222 - 223 224 if (state.event == PM_EVENT_SUSPEND) { 224 225 /* Shut down the device */ 225 226 pci_disable_device(dev->pdev); ··· 231 236 { 232 237 struct drm_i915_private *dev_priv = dev->dev_private; 233 238 int error = 0; 239 + 240 + i915_restore_state(dev); 241 + 242 + intel_opregion_init(dev, 1); 234 243 235 244 /* KMS EnterVT equivalent */ 236 245 if (drm_core_check_feature(dev, DRIVER_MODESET)) { ··· 261 262 return -EIO; 262 263 263 264 pci_set_master(dev->pdev); 264 - 265 - i915_restore_state(dev); 266 - 267 - intel_opregion_init(dev, 1); 268 265 269 266 return i915_drm_thaw(dev); 270 267 } ··· 418 423 if (error) 419 424 return error; 420 425 421 - i915_drm_suspend(drm_dev); 422 - 423 426 pci_disable_device(pdev); 424 427 pci_set_power_state(pdev, PCI_D3hot); 425 428 ··· 457 464 { 458 465 struct pci_dev *pdev = to_pci_dev(dev); 459 466 struct drm_device *drm_dev = pci_get_drvdata(pdev); 460 - int error; 461 467 462 - error = i915_drm_freeze(drm_dev); 463 - if (!error) 464 - i915_drm_suspend(drm_dev); 465 - 466 - return error; 468 + return i915_drm_freeze(drm_dev); 467 469 } 468 470 469 471 const struct dev_pm_ops i915_pm_ops = {