|
@@ -1553,12 +1553,30 @@ static bool suspend_to_idle(struct drm_i915_private *dev_priv)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static int i915_drm_prepare(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *i915 = to_i915(dev);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * NB intel_display_suspend() may issue new requests after we've
|
|
|
+ * ostensibly marked the GPU as ready-to-sleep here. We need to
|
|
|
+ * split out that work and pull it forward so that after point,
|
|
|
+ * the GPU is not woken again.
|
|
|
+ */
|
|
|
+ err = i915_gem_suspend(i915);
|
|
|
+ if (err)
|
|
|
+ dev_err(&i915->drm.pdev->dev,
|
|
|
+ "GEM idle failed, suspend/resume might fail\n");
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static int i915_drm_suspend(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
struct pci_dev *pdev = dev_priv->drm.pdev;
|
|
|
pci_power_t opregion_target_state;
|
|
|
- int error;
|
|
|
|
|
|
/* ignore lid events during suspend */
|
|
|
mutex_lock(&dev_priv->modeset_restore_lock);
|
|
@@ -1575,13 +1593,6 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|
|
|
|
|
pci_save_state(pdev);
|
|
|
|
|
|
- error = i915_gem_suspend(dev_priv);
|
|
|
- if (error) {
|
|
|
- dev_err(&pdev->dev,
|
|
|
- "GEM idle failed, resume might fail\n");
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
intel_display_suspend(dev);
|
|
|
|
|
|
intel_dp_mst_suspend(dev);
|
|
@@ -1609,10 +1620,9 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|
|
|
|
|
intel_csr_ucode_suspend(dev_priv);
|
|
|
|
|
|
-out:
|
|
|
enable_rpm_wakeref_asserts(dev_priv);
|
|
|
|
|
|
- return error;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
|
|
@@ -2081,6 +2091,22 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int i915_pm_prepare(struct device *kdev)
|
|
|
+{
|
|
|
+ struct pci_dev *pdev = to_pci_dev(kdev);
|
|
|
+ struct drm_device *dev = pci_get_drvdata(pdev);
|
|
|
+
|
|
|
+ if (!dev) {
|
|
|
+ dev_err(kdev, "DRM not initialized, aborting suspend.\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return i915_drm_prepare(dev);
|
|
|
+}
|
|
|
+
|
|
|
static int i915_pm_suspend(struct device *kdev)
|
|
|
{
|
|
|
struct pci_dev *pdev = to_pci_dev(kdev);
|
|
@@ -2731,6 +2757,7 @@ const struct dev_pm_ops i915_pm_ops = {
|
|
|
* S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
|
|
|
* PMSG_RESUME]
|
|
|
*/
|
|
|
+ .prepare = i915_pm_prepare,
|
|
|
.suspend = i915_pm_suspend,
|
|
|
.suspend_late = i915_pm_suspend_late,
|
|
|
.resume_early = i915_pm_resume_early,
|