Commit f6bec6ea6816ece9d229c4d37c44e3222de14044

Authored by Dave Airlie

Merge tag 'drm-intel-fixes-2015-03-05' of git://anongit.freedesktop.org/drm-intel into drm-fixes

two fixes, both cc'd stable.

* tag 'drm-intel-fixes-2015-03-05' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: gen4: work around hang during hibernation
  drm/i915: Check for driver readyness before handling an underrun interrupt

Showing 2 changed files Side-by-side Diff

drivers/gpu/drm/i915/i915_drv.c
... ... @@ -622,7 +622,7 @@
622 622 return 0;
623 623 }
624 624  
625   -static int i915_drm_suspend_late(struct drm_device *drm_dev)
  625 +static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
626 626 {
627 627 struct drm_i915_private *dev_priv = drm_dev->dev_private;
628 628 int ret;
... ... @@ -636,7 +636,17 @@
636 636 }
637 637  
638 638 pci_disable_device(drm_dev->pdev);
639   - pci_set_power_state(drm_dev->pdev, PCI_D3hot);
  639 + /*
  640 + * During hibernation on some GEN4 platforms the BIOS may try to access
  641 + * the device even though it's already in D3 and hang the machine. So
  642 + * leave the device in D0 on those platforms and hope the BIOS will
  643 + * power down the device properly. Platforms where this was seen:
  644 + * Lenovo Thinkpad X301, X61s
  645 + */
  646 + if (!(hibernation &&
  647 + drm_dev->pdev->subsystem_vendor == PCI_VENDOR_ID_LENOVO &&
  648 + INTEL_INFO(dev_priv)->gen == 4))
  649 + pci_set_power_state(drm_dev->pdev, PCI_D3hot);
640 650  
641 651 return 0;
642 652 }
... ... @@ -662,7 +672,7 @@
662 672 if (error)
663 673 return error;
664 674  
665   - return i915_drm_suspend_late(dev);
  675 + return i915_drm_suspend_late(dev, false);
666 676 }
667 677  
668 678 static int i915_drm_resume(struct drm_device *dev)
669 679  
... ... @@ -950,9 +960,19 @@
950 960 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
951 961 return 0;
952 962  
953   - return i915_drm_suspend_late(drm_dev);
  963 + return i915_drm_suspend_late(drm_dev, false);
954 964 }
955 965  
  966 +static int i915_pm_poweroff_late(struct device *dev)
  967 +{
  968 + struct drm_device *drm_dev = dev_to_i915(dev)->dev;
  969 +
  970 + if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
  971 + return 0;
  972 +
  973 + return i915_drm_suspend_late(drm_dev, true);
  974 +}
  975 +
956 976 static int i915_pm_resume_early(struct device *dev)
957 977 {
958 978 struct drm_device *drm_dev = dev_to_i915(dev)->dev;
... ... @@ -1520,7 +1540,7 @@
1520 1540 .thaw_early = i915_pm_resume_early,
1521 1541 .thaw = i915_pm_resume,
1522 1542 .poweroff = i915_pm_suspend,
1523   - .poweroff_late = i915_pm_suspend_late,
  1543 + .poweroff_late = i915_pm_poweroff_late,
1524 1544 .restore_early = i915_pm_resume_early,
1525 1545 .restore = i915_pm_resume,
1526 1546  
drivers/gpu/drm/i915/intel_fifo_underrun.c
... ... @@ -282,16 +282,6 @@
282 282 return ret;
283 283 }
284 284  
285   -static bool
286   -__cpu_fifo_underrun_reporting_enabled(struct drm_i915_private *dev_priv,
287   - enum pipe pipe)
288   -{
289   - struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
290   - struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
291   -
292   - return !intel_crtc->cpu_fifo_underrun_disabled;
293   -}
294   -
295 285 /**
296 286 * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
297 287 * @dev_priv: i915 device instance
298 288  
... ... @@ -352,9 +342,15 @@
352 342 void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
353 343 enum pipe pipe)
354 344 {
  345 + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
  346 +
  347 + /* We may be called too early in init, thanks BIOS! */
  348 + if (crtc == NULL)
  349 + return;
  350 +
355 351 /* GMCH can't disable fifo underruns, filter them. */
356 352 if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
357   - !__cpu_fifo_underrun_reporting_enabled(dev_priv, pipe))
  353 + to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
358 354 return;
359 355  
360 356 if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))