aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2018-03-22 10:36:42 -0400
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2018-03-27 04:20:06 -0400
commit300efa9eea451bdcf3b5a1eb292222e06e85bb2c (patch)
tree9ca5c00a28fd9929eca45c07bf210fbfaa0f0edb
parent76cb9d314a5385020c3adabf563df8efe71c6325 (diff)
drm/i915: Fix hibernation with ACPI S0 target state
After commit dd9f31c7a3887950cbd0d49eb9d43f7a1518a356 Author: Imre Deak <imre.deak@intel.com> Date: Wed Aug 16 17:46:07 2017 +0300 drm/i915/gen9+: Set same power state before hibernation image save/restore during hibernation/suspend the power domain functionality got disabled, after which resume could leave it incorrectly disabled if the ACPI target state was S0 during suspend and i915 was not loaded by the loader kernel. This was caused by not considering if we resumed from hibernation as the condition for power domains reiniting. Fix this by simply tracking if we suspended power domains during system suspend and reinit power domains accordingly during resume. This will result in reiniting power domains always when resuming from hibernation, regardless of the platform and whether or not i915 is loaded by the loader kernel. The reason we didn't catch this earlier is that the enabled/disabled state of power domains during PMSG_FREEZE/PMSG_QUIESCE is platform and kernel config dependent: on my SKL the target state is S4 during PMSG_FREEZE and (with the driver loaded in the loader kernel) S0 during PMSG_QUIESCE. On the reporter's machine it's S0 during PMSG_FREEZE but (contrary to this) power domains are not initialized during PMSG_QUIESCE since i915 is not loaded in the loader kernel, or it's loaded but without the DMC firmware being available. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105196 Reported-and-tested-by: amn-bas@hotmail.com Fixes: dd9f31c7a388 ("drm/i915/gen9+: Set same power state before hibernation image save/restore") Cc: amn-bas@hotmail.com Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: <stable@vger.kernel.org> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180322143642.26883-1-imre.deak@intel.com (cherry picked from commit 0f90603c33bdf6575cfdc81edd53f3f13ba166fb) Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c22
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
2 files changed, 11 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d7c4de45644d..07c07d55398b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1611,15 +1611,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
1611{ 1611{
1612 struct drm_i915_private *dev_priv = to_i915(dev); 1612 struct drm_i915_private *dev_priv = to_i915(dev);
1613 struct pci_dev *pdev = dev_priv->drm.pdev; 1613 struct pci_dev *pdev = dev_priv->drm.pdev;
1614 bool fw_csr;
1615 int ret; 1614 int ret;
1616 1615
1617 disable_rpm_wakeref_asserts(dev_priv); 1616 disable_rpm_wakeref_asserts(dev_priv);
1618 1617
1619 intel_display_set_init_power(dev_priv, false); 1618 intel_display_set_init_power(dev_priv, false);
1620 1619
1621 fw_csr = !IS_GEN9_LP(dev_priv) && !hibernation &&
1622 suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
1623 /* 1620 /*
1624 * In case of firmware assisted context save/restore don't manually 1621 * In case of firmware assisted context save/restore don't manually
1625 * deinit the power domains. This also means the CSR/DMC firmware will 1622 * deinit the power domains. This also means the CSR/DMC firmware will
@@ -1627,8 +1624,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
1627 * also enable deeper system power states that would be blocked if the 1624 * also enable deeper system power states that would be blocked if the
1628 * firmware was inactive. 1625 * firmware was inactive.
1629 */ 1626 */
1630 if (!fw_csr) 1627 if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
1628 dev_priv->csr.dmc_payload == NULL) {
1631 intel_power_domains_suspend(dev_priv); 1629 intel_power_domains_suspend(dev_priv);
1630 dev_priv->power_domains_suspended = true;
1631 }
1632 1632
1633 ret = 0; 1633 ret = 0;
1634 if (IS_GEN9_LP(dev_priv)) 1634 if (IS_GEN9_LP(dev_priv))
@@ -1640,8 +1640,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
1640 1640
1641 if (ret) { 1641 if (ret) {
1642 DRM_ERROR("Suspend complete failed: %d\n", ret); 1642 DRM_ERROR("Suspend complete failed: %d\n", ret);
1643 if (!fw_csr) 1643 if (dev_priv->power_domains_suspended) {
1644 intel_power_domains_init_hw(dev_priv, true); 1644 intel_power_domains_init_hw(dev_priv, true);
1645 dev_priv->power_domains_suspended = false;
1646 }
1645 1647
1646 goto out; 1648 goto out;
1647 } 1649 }
@@ -1662,8 +1664,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
1662 if (!(hibernation && INTEL_GEN(dev_priv) < 6)) 1664 if (!(hibernation && INTEL_GEN(dev_priv) < 6))
1663 pci_set_power_state(pdev, PCI_D3hot); 1665 pci_set_power_state(pdev, PCI_D3hot);
1664 1666
1665 dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
1666
1667out: 1667out:
1668 enable_rpm_wakeref_asserts(dev_priv); 1668 enable_rpm_wakeref_asserts(dev_priv);
1669 1669
@@ -1830,8 +1830,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
1830 intel_uncore_resume_early(dev_priv); 1830 intel_uncore_resume_early(dev_priv);
1831 1831
1832 if (IS_GEN9_LP(dev_priv)) { 1832 if (IS_GEN9_LP(dev_priv)) {
1833 if (!dev_priv->suspended_to_idle) 1833 gen9_sanitize_dc_state(dev_priv);
1834 gen9_sanitize_dc_state(dev_priv);
1835 bxt_disable_dc9(dev_priv); 1834 bxt_disable_dc9(dev_priv);
1836 } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { 1835 } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1837 hsw_disable_pc8(dev_priv); 1836 hsw_disable_pc8(dev_priv);
@@ -1839,8 +1838,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
1839 1838
1840 intel_uncore_sanitize(dev_priv); 1839 intel_uncore_sanitize(dev_priv);
1841 1840
1842 if (IS_GEN9_LP(dev_priv) || 1841 if (dev_priv->power_domains_suspended)
1843 !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
1844 intel_power_domains_init_hw(dev_priv, true); 1842 intel_power_domains_init_hw(dev_priv, true);
1845 else 1843 else
1846 intel_display_set_init_power(dev_priv, true); 1844 intel_display_set_init_power(dev_priv, true);
@@ -1850,7 +1848,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
1850 enable_rpm_wakeref_asserts(dev_priv); 1848 enable_rpm_wakeref_asserts(dev_priv);
1851 1849
1852out: 1850out:
1853 dev_priv->suspended_to_idle = false; 1851 dev_priv->power_domains_suspended = false;
1854 1852
1855 return ret; 1853 return ret;
1856} 1854}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6e740f6fe33f..ce18b6cf6e68 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2119,7 +2119,7 @@ struct drm_i915_private {
2119 u32 bxt_phy_grc; 2119 u32 bxt_phy_grc;
2120 2120
2121 u32 suspend_count; 2121 u32 suspend_count;
2122 bool suspended_to_idle; 2122 bool power_domains_suspended;
2123 struct i915_suspend_saved_registers regfile; 2123 struct i915_suspend_saved_registers regfile;
2124 struct vlv_s0ix_state vlv_s0ix_state; 2124 struct vlv_s0ix_state vlv_s0ix_state;
2125 2125