Skip to content

Commit 0f90603

Browse files
committed
drm/i915: Fix hibernation with ACPI S0 target state
After commit dd9f31c 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: dd9f31c ("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
1 parent 46b3617 commit 0f90603

File tree

2 files changed

+11
-13
lines changed

2 files changed

+11
-13
lines changed

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,24 +1607,24 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
16071607
{
16081608
struct drm_i915_private *dev_priv = to_i915(dev);
16091609
struct pci_dev *pdev = dev_priv->drm.pdev;
1610-
bool fw_csr;
16111610
int ret;
16121611

16131612
disable_rpm_wakeref_asserts(dev_priv);
16141613

16151614
intel_display_set_init_power(dev_priv, false);
16161615

1617-
fw_csr = !IS_GEN9_LP(dev_priv) && !hibernation &&
1618-
suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
16191616
/*
16201617
* In case of firmware assisted context save/restore don't manually
16211618
* deinit the power domains. This also means the CSR/DMC firmware will
16221619
* stay active, it will power down any HW resources as required and
16231620
* also enable deeper system power states that would be blocked if the
16241621
* firmware was inactive.
16251622
*/
1626-
if (!fw_csr)
1623+
if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
1624+
dev_priv->csr.dmc_payload == NULL) {
16271625
intel_power_domains_suspend(dev_priv);
1626+
dev_priv->power_domains_suspended = true;
1627+
}
16281628

16291629
ret = 0;
16301630
if (IS_GEN9_LP(dev_priv))
@@ -1636,8 +1636,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
16361636

16371637
if (ret) {
16381638
DRM_ERROR("Suspend complete failed: %d\n", ret);
1639-
if (!fw_csr)
1639+
if (dev_priv->power_domains_suspended) {
16401640
intel_power_domains_init_hw(dev_priv, true);
1641+
dev_priv->power_domains_suspended = false;
1642+
}
16411643

16421644
goto out;
16431645
}
@@ -1658,8 +1660,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
16581660
if (!(hibernation && INTEL_GEN(dev_priv) < 6))
16591661
pci_set_power_state(pdev, PCI_D3hot);
16601662

1661-
dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
1662-
16631663
out:
16641664
enable_rpm_wakeref_asserts(dev_priv);
16651665

@@ -1826,17 +1826,15 @@ static int i915_drm_resume_early(struct drm_device *dev)
18261826
intel_uncore_resume_early(dev_priv);
18271827

18281828
if (IS_GEN9_LP(dev_priv)) {
1829-
if (!dev_priv->suspended_to_idle)
1830-
gen9_sanitize_dc_state(dev_priv);
1829+
gen9_sanitize_dc_state(dev_priv);
18311830
bxt_disable_dc9(dev_priv);
18321831
} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
18331832
hsw_disable_pc8(dev_priv);
18341833
}
18351834

18361835
intel_uncore_sanitize(dev_priv);
18371836

1838-
if (IS_GEN9_LP(dev_priv) ||
1839-
!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
1837+
if (dev_priv->power_domains_suspended)
18401838
intel_power_domains_init_hw(dev_priv, true);
18411839
else
18421840
intel_display_set_init_power(dev_priv, true);
@@ -1846,7 +1844,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
18461844
enable_rpm_wakeref_asserts(dev_priv);
18471845

18481846
out:
1849-
dev_priv->suspended_to_idle = false;
1847+
dev_priv->power_domains_suspended = false;
18501848

18511849
return ret;
18521850
}

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ struct drm_i915_private {
18511851
u32 bxt_phy_grc;
18521852

18531853
u32 suspend_count;
1854-
bool suspended_to_idle;
1854+
bool power_domains_suspended;
18551855
struct i915_suspend_saved_registers regfile;
18561856
struct vlv_s0ix_state vlv_s0ix_state;
18571857

0 commit comments

Comments
 (0)