From dd9f31c7a3887950cbd0d49eb9d43f7a1518a356 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Aug 2017 17:46:07 +0300 Subject: [PATCH] drm/i915/gen9+: Set same power state before hibernation image save/restore Mime-version: 1.0 Content-type: text/plain; charset=UTF-8 Content-transfer-encoding: 8bit Git-commit: dd9f31c7a3887950cbd0d49eb9d43f7a1518a356 Patch-mainline: v4.15-rc1 References: FATE#322643 bsc#1055900 Atm, on GEN9 big core platforms before saving the hibernation image we uninitialize the display, disabling power wells manually, while before restoring the image we keep things powered (letting HW/DMC power down things as needed). The state mismatch will trigger the following error: DC state mismatch (0x0 -> 0x2) While the restore handler knows how to initialize the display from an unknown state (due to a different loader kernel or not having i915 loaded in the loader kernel) we should still use the same state for consistency before image saving and restoring. Do this by uniniting the display before restoring the image too. Bugzilla: https://bugs.freedesktop.org/attachment.cgi?id=133376 Reported-and-tested-by: Wang Wendy Reported-and-tested-by: Joonas Lahtinen Cc: Wang Wendy Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Ville Syrjala Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20170816144607.9935-1-imre.deak@intel.com Acked-by: Takashi Iwai --- drivers/gpu/drm/i915/i915_drv.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1580,7 +1580,7 @@ static int i915_drm_suspend_late(struct intel_display_set_init_power(dev_priv, false); - fw_csr = !IS_GEN9_LP(dev_priv) && + fw_csr = !IS_GEN9_LP(dev_priv) && !hibernation && suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; /* * In case of firmware assisted context save/restore don't manually @@ -2070,11 +2070,14 @@ static int i915_pm_resume(struct device /* freeze: before creating the hibernation_image */ static int i915_pm_freeze(struct device *kdev) { + struct drm_device *dev = &kdev_to_i915(kdev)->drm; int ret; - ret = i915_pm_suspend(kdev); - if (ret) - return ret; + if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) { + ret = i915_drm_suspend(dev); + if (ret) + return ret; + } ret = i915_gem_freeze(kdev_to_i915(kdev)); if (ret) @@ -2085,11 +2088,14 @@ static int i915_pm_freeze(struct device static int i915_pm_freeze_late(struct device *kdev) { + struct drm_device *dev = &kdev_to_i915(kdev)->drm; int ret; - ret = i915_pm_suspend_late(kdev); - if (ret) - return ret; + if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) { + ret = i915_drm_suspend_late(dev, true); + if (ret) + return ret; + } ret = i915_gem_freeze_late(kdev_to_i915(kdev)); if (ret)