All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
@ 2018-03-22 14:36 ` Imre Deak
  0 siblings, 0 replies; 10+ messages in thread
From: Imre Deak @ 2018-03-22 14:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable, amn-bas

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>
---
 drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
 drivers/gpu/drm/i915/i915_drv.h |  2 +-
 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 a7d3275f45d2..f706cff4f01b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	bool fw_csr;
 	int ret;
 
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	intel_display_set_init_power(dev_priv, false);
 
-	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
 	 * deinit the power domains. This also means the CSR/DMC firmware will
@@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * also enable deeper system power states that would be blocked if the
 	 * firmware was inactive.
 	 */
-	if (!fw_csr)
+	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
+	    dev_priv->csr.dmc_payload == NULL) {
 		intel_power_domains_suspend(dev_priv);
+		dev_priv->power_domains_suspended = true;
+	}
 
 	ret = 0;
 	if (IS_GEN9_LP(dev_priv))
@@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 
 	if (ret) {
 		DRM_ERROR("Suspend complete failed: %d\n", ret);
-		if (!fw_csr)
+		if (dev_priv->power_domains_suspended) {
 			intel_power_domains_init_hw(dev_priv, true);
+			dev_priv->power_domains_suspended = false;
+		}
 
 		goto out;
 	}
@@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
 		pci_set_power_state(pdev, PCI_D3hot);
 
-	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
-
 out:
 	enable_rpm_wakeref_asserts(dev_priv);
 
@@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 	intel_uncore_resume_early(dev_priv);
 
 	if (IS_GEN9_LP(dev_priv)) {
-		if (!dev_priv->suspended_to_idle)
-			gen9_sanitize_dc_state(dev_priv);
+		gen9_sanitize_dc_state(dev_priv);
 		bxt_disable_dc9(dev_priv);
 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		hsw_disable_pc8(dev_priv);
@@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 
 	intel_uncore_sanitize(dev_priv);
 
-	if (IS_GEN9_LP(dev_priv) ||
-	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
+	if (dev_priv->power_domains_suspended)
 		intel_power_domains_init_hw(dev_priv, true);
 	else
 		intel_display_set_init_power(dev_priv, true);
@@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 	enable_rpm_wakeref_asserts(dev_priv);
 
 out:
-	dev_priv->suspended_to_idle = false;
+	dev_priv->power_domains_suspended = false;
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c9c3b2ba6a86..3acc4bbec6b2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1851,7 +1851,7 @@ struct drm_i915_private {
 	u32 bxt_phy_grc;
 
 	u32 suspend_count;
-	bool suspended_to_idle;
+	bool power_domains_suspended;
 	struct i915_suspend_saved_registers regfile;
 	struct vlv_s0ix_state vlv_s0ix_state;
 
-- 
2.13.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
@ 2018-03-22 14:36 ` Imre Deak
  0 siblings, 0 replies; 10+ messages in thread
From: Imre Deak @ 2018-03-22 14:36 UTC (permalink / raw)
  To: intel-gfx; +Cc: amn-bas, Ville Syrjälä, stable

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>
---
 drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
 drivers/gpu/drm/i915/i915_drv.h |  2 +-
 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 a7d3275f45d2..f706cff4f01b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	bool fw_csr;
 	int ret;
 
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	intel_display_set_init_power(dev_priv, false);
 
-	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
 	 * deinit the power domains. This also means the CSR/DMC firmware will
@@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * also enable deeper system power states that would be blocked if the
 	 * firmware was inactive.
 	 */
-	if (!fw_csr)
+	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
+	    dev_priv->csr.dmc_payload == NULL) {
 		intel_power_domains_suspend(dev_priv);
+		dev_priv->power_domains_suspended = true;
+	}
 
 	ret = 0;
 	if (IS_GEN9_LP(dev_priv))
@@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 
 	if (ret) {
 		DRM_ERROR("Suspend complete failed: %d\n", ret);
-		if (!fw_csr)
+		if (dev_priv->power_domains_suspended) {
 			intel_power_domains_init_hw(dev_priv, true);
+			dev_priv->power_domains_suspended = false;
+		}
 
 		goto out;
 	}
@@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
 		pci_set_power_state(pdev, PCI_D3hot);
 
-	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
-
 out:
 	enable_rpm_wakeref_asserts(dev_priv);
 
@@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 	intel_uncore_resume_early(dev_priv);
 
 	if (IS_GEN9_LP(dev_priv)) {
-		if (!dev_priv->suspended_to_idle)
-			gen9_sanitize_dc_state(dev_priv);
+		gen9_sanitize_dc_state(dev_priv);
 		bxt_disable_dc9(dev_priv);
 	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		hsw_disable_pc8(dev_priv);
@@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 
 	intel_uncore_sanitize(dev_priv);
 
-	if (IS_GEN9_LP(dev_priv) ||
-	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
+	if (dev_priv->power_domains_suspended)
 		intel_power_domains_init_hw(dev_priv, true);
 	else
 		intel_display_set_init_power(dev_priv, true);
@@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
 	enable_rpm_wakeref_asserts(dev_priv);
 
 out:
-	dev_priv->suspended_to_idle = false;
+	dev_priv->power_domains_suspended = false;
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c9c3b2ba6a86..3acc4bbec6b2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1851,7 +1851,7 @@ struct drm_i915_private {
 	u32 bxt_phy_grc;
 
 	u32 suspend_count;
-	bool suspended_to_idle;
+	bool power_domains_suspended;
 	struct i915_suspend_saved_registers regfile;
 	struct vlv_s0ix_state vlv_s0ix_state;
 
-- 
2.13.2

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-22 14:36 ` Imre Deak
  (?)
@ 2018-03-22 15:31 ` Patchwork
  -1 siblings, 0 replies; 10+ messages in thread
From: Patchwork @ 2018-03-22 15:31 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix hibernation with ACPI S0 target state
URL   : https://patchwork.freedesktop.org/series/40466/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
3f4a1545711f drm/i915: Fix hibernation with ACPI S0 target state
-:11: ERROR:GIT_COMMIT_ID: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit dd9f31c7a388 ("drm/i915/gen9+: Set same power state before hibernation image save/restore")'
#11: 
commit dd9f31c7a3887950cbd0d49eb9d43f7a1518a356

-:75: CHECK:COMPARISON_TO_NULL: Comparison to NULL could be written "!dev_priv->csr.dmc_payload"
#75: FILE: drivers/gpu/drm/i915/i915_drv.c:1629:
+	    dev_priv->csr.dmc_payload == NULL) {

total: 1 errors, 0 warnings, 1 checks, 80 lines checked

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* ✓ Fi.CI.BAT: success for drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-22 14:36 ` Imre Deak
  (?)
  (?)
@ 2018-03-22 15:46 ` Patchwork
  -1 siblings, 0 replies; 10+ messages in thread
From: Patchwork @ 2018-03-22 15:46 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix hibernation with ACPI S0 target state
URL   : https://patchwork.freedesktop.org/series/40466/
State : success

== Summary ==

Series 40466v1 drm/i915: Fix hibernation with ACPI S0 target state
https://patchwork.freedesktop.org/api/1.0/series/40466/revisions/1/mbox/

---- Known issues:

Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-b:
                incomplete -> PASS       (fi-snb-2520m) fdo#103713

fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713

fi-bdw-5557u     total:285  pass:264  dwarn:0   dfail:0   fail:0   skip:21  time:428s
fi-bdw-gvtdvm    total:285  pass:261  dwarn:0   dfail:0   fail:0   skip:24  time:443s
fi-blb-e6850     total:285  pass:220  dwarn:1   dfail:0   fail:0   skip:64  time:379s
fi-bsw-n3050     total:285  pass:239  dwarn:0   dfail:0   fail:0   skip:46  time:536s
fi-bwr-2160      total:285  pass:180  dwarn:0   dfail:0   fail:0   skip:105 time:298s
fi-bxt-dsi       total:285  pass:255  dwarn:0   dfail:0   fail:0   skip:30  time:516s
fi-bxt-j4205     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:507s
fi-byt-j1900     total:285  pass:250  dwarn:0   dfail:0   fail:0   skip:35  time:516s
fi-byt-n2820     total:285  pass:246  dwarn:0   dfail:0   fail:0   skip:39  time:505s
fi-cfl-8700k     total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:412s
fi-cfl-u         total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:511s
fi-cnl-drrs      total:285  pass:254  dwarn:3   dfail:0   fail:0   skip:28  time:527s
fi-cnl-y3        total:285  pass:259  dwarn:0   dfail:0   fail:0   skip:26  time:583s
fi-elk-e7500     total:285  pass:225  dwarn:1   dfail:0   fail:0   skip:59  time:424s
fi-gdg-551       total:285  pass:176  dwarn:0   dfail:0   fail:1   skip:108 time:318s
fi-glk-1         total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:535s
fi-hsw-4770      total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:410s
fi-ilk-650       total:285  pass:225  dwarn:0   dfail:0   fail:0   skip:60  time:418s
fi-ivb-3520m     total:285  pass:256  dwarn:0   dfail:0   fail:0   skip:29  time:464s
fi-ivb-3770      total:285  pass:252  dwarn:0   dfail:0   fail:0   skip:33  time:430s
fi-kbl-7500u     total:285  pass:260  dwarn:1   dfail:0   fail:0   skip:24  time:476s
fi-kbl-7567u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:467s
fi-kbl-r         total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:515s
fi-pnv-d510      total:285  pass:219  dwarn:1   dfail:0   fail:0   skip:65  time:651s
fi-skl-6260u     total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:440s
fi-skl-6600u     total:285  pass:258  dwarn:0   dfail:0   fail:0   skip:27  time:534s
fi-skl-6700k2    total:285  pass:261  dwarn:0   dfail:0   fail:0   skip:24  time:506s
fi-skl-6770hq    total:285  pass:265  dwarn:0   dfail:0   fail:0   skip:20  time:504s
fi-skl-guc       total:285  pass:257  dwarn:0   dfail:0   fail:0   skip:28  time:430s
fi-skl-gvtdvm    total:285  pass:262  dwarn:0   dfail:0   fail:0   skip:23  time:442s
fi-snb-2520m     total:285  pass:245  dwarn:0   dfail:0   fail:0   skip:40  time:599s
fi-snb-2600      total:285  pass:245  dwarn:0   dfail:0   fail:0   skip:40  time:398s
fi-cfl-s3 failed to connect after reboot

7ae13170ff7a3e55b3f10149db1b34571d5bbd7b drm-tip: 2018y-03m-22d-14h-02m-32s UTC integration manifest
3f4a1545711f drm/i915: Fix hibernation with ACPI S0 target state

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8451/issues.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* ✓ Fi.CI.IGT: success for drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-22 14:36 ` Imre Deak
                   ` (2 preceding siblings ...)
  (?)
@ 2018-03-22 16:49 ` Patchwork
  2018-03-23 18:03   ` Imre Deak
  -1 siblings, 1 reply; 10+ messages in thread
From: Patchwork @ 2018-03-22 16:49 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix hibernation with ACPI S0 target state
URL   : https://patchwork.freedesktop.org/series/40466/
State : success

== Summary ==

---- Known issues:

Test kms_cursor_crc:
        Subgroup cursor-256x256-suspend:
                pass       -> INCOMPLETE (shard-hsw) fdo#103375
Test kms_flip:
        Subgroup dpms-vs-vblank-race:
                fail       -> PASS       (shard-hsw) fdo#103060 +1
        Subgroup plain-flip-fb-recreate-interruptible:
                pass       -> FAIL       (shard-hsw) fdo#100368 +2
Test kms_rotation_crc:
        Subgroup sprite-rotation-180:
                fail       -> PASS       (shard-apl) fdo#103925
Test kms_setmode:
        Subgroup basic:
                fail       -> PASS       (shard-apl) fdo#99912

fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375
fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103925 https://bugs.freedesktop.org/show_bug.cgi?id=103925
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912

shard-apl        total:3484 pass:1821 dwarn:1   dfail:0   fail:6   skip:1655 time:13132s
shard-hsw        total:3477 pass:1770 dwarn:1   dfail:0   fail:2   skip:1702 time:11273s
shard-snb        total:3484 pass:1363 dwarn:1   dfail:0   fail:3   skip:2117 time:7243s
Blacklisted hosts:
shard-kbl        total:3484 pass:1943 dwarn:1   dfail:0   fail:9   skip:1531 time:10063s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8451/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-22 14:36 ` Imre Deak
@ 2018-03-23 13:22   ` Ville Syrjälä
  -1 siblings, 0 replies; 10+ messages in thread
From: Ville Syrjälä @ 2018-03-23 13:22 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, amn-bas, stable

On Thu, Mar 22, 2018 at 04:36:42PM +0200, Imre Deak wrote:
> 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>

Make sense to me.
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

On thing I can't quite tell is what happens with switcheroo. Maybe it's
not even relevant for platforms with DC6 in which case I suppose it
should work correctly.

> ---
>  drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
>  drivers/gpu/drm/i915/i915_drv.h |  2 +-
>  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 a7d3275f45d2..f706cff4f01b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	bool fw_csr;
>  	int ret;
>  
>  	disable_rpm_wakeref_asserts(dev_priv);
>  
>  	intel_display_set_init_power(dev_priv, false);
>  
> -	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
>  	 * deinit the power domains. This also means the CSR/DMC firmware will
> @@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  	 * also enable deeper system power states that would be blocked if the
>  	 * firmware was inactive.
>  	 */
> -	if (!fw_csr)
> +	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
> +	    dev_priv->csr.dmc_payload == NULL) {
>  		intel_power_domains_suspend(dev_priv);
> +		dev_priv->power_domains_suspended = true;
> +	}
>  
>  	ret = 0;
>  	if (IS_GEN9_LP(dev_priv))
> @@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  
>  	if (ret) {
>  		DRM_ERROR("Suspend complete failed: %d\n", ret);
> -		if (!fw_csr)
> +		if (dev_priv->power_domains_suspended) {
>  			intel_power_domains_init_hw(dev_priv, true);
> +			dev_priv->power_domains_suspended = false;
> +		}
>  
>  		goto out;
>  	}
> @@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
>  		pci_set_power_state(pdev, PCI_D3hot);
>  
> -	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
> -
>  out:
>  	enable_rpm_wakeref_asserts(dev_priv);
>  
> @@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  	intel_uncore_resume_early(dev_priv);
>  
>  	if (IS_GEN9_LP(dev_priv)) {
> -		if (!dev_priv->suspended_to_idle)
> -			gen9_sanitize_dc_state(dev_priv);
> +		gen9_sanitize_dc_state(dev_priv);
>  		bxt_disable_dc9(dev_priv);
>  	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
>  		hsw_disable_pc8(dev_priv);
> @@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  
>  	intel_uncore_sanitize(dev_priv);
>  
> -	if (IS_GEN9_LP(dev_priv) ||
> -	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
> +	if (dev_priv->power_domains_suspended)
>  		intel_power_domains_init_hw(dev_priv, true);
>  	else
>  		intel_display_set_init_power(dev_priv, true);
> @@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  	enable_rpm_wakeref_asserts(dev_priv);
>  
>  out:
> -	dev_priv->suspended_to_idle = false;
> +	dev_priv->power_domains_suspended = false;
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index c9c3b2ba6a86..3acc4bbec6b2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1851,7 +1851,7 @@ struct drm_i915_private {
>  	u32 bxt_phy_grc;
>  
>  	u32 suspend_count;
> -	bool suspended_to_idle;
> +	bool power_domains_suspended;
>  	struct i915_suspend_saved_registers regfile;
>  	struct vlv_s0ix_state vlv_s0ix_state;
>  
> -- 
> 2.13.2

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
@ 2018-03-23 13:22   ` Ville Syrjälä
  0 siblings, 0 replies; 10+ messages in thread
From: Ville Syrjälä @ 2018-03-23 13:22 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, amn-bas, stable

On Thu, Mar 22, 2018 at 04:36:42PM +0200, Imre Deak wrote:
> 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>

Make sense to me.
Reviewed-by: Ville Syrj�l� <ville.syrjala@linux.intel.com>

On thing I can't quite tell is what happens with switcheroo. Maybe it's
not even relevant for platforms with DC6 in which case I suppose it
should work correctly.

> ---
>  drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
>  drivers/gpu/drm/i915/i915_drv.h |  2 +-
>  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 a7d3275f45d2..f706cff4f01b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct pci_dev *pdev = dev_priv->drm.pdev;
> -	bool fw_csr;
>  	int ret;
>  
>  	disable_rpm_wakeref_asserts(dev_priv);
>  
>  	intel_display_set_init_power(dev_priv, false);
>  
> -	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
>  	 * deinit the power domains. This also means the CSR/DMC firmware will
> @@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  	 * also enable deeper system power states that would be blocked if the
>  	 * firmware was inactive.
>  	 */
> -	if (!fw_csr)
> +	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
> +	    dev_priv->csr.dmc_payload == NULL) {
>  		intel_power_domains_suspend(dev_priv);
> +		dev_priv->power_domains_suspended = true;
> +	}
>  
>  	ret = 0;
>  	if (IS_GEN9_LP(dev_priv))
> @@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  
>  	if (ret) {
>  		DRM_ERROR("Suspend complete failed: %d\n", ret);
> -		if (!fw_csr)
> +		if (dev_priv->power_domains_suspended) {
>  			intel_power_domains_init_hw(dev_priv, true);
> +			dev_priv->power_domains_suspended = false;
> +		}
>  
>  		goto out;
>  	}
> @@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
>  	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
>  		pci_set_power_state(pdev, PCI_D3hot);
>  
> -	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
> -
>  out:
>  	enable_rpm_wakeref_asserts(dev_priv);
>  
> @@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  	intel_uncore_resume_early(dev_priv);
>  
>  	if (IS_GEN9_LP(dev_priv)) {
> -		if (!dev_priv->suspended_to_idle)
> -			gen9_sanitize_dc_state(dev_priv);
> +		gen9_sanitize_dc_state(dev_priv);
>  		bxt_disable_dc9(dev_priv);
>  	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
>  		hsw_disable_pc8(dev_priv);
> @@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  
>  	intel_uncore_sanitize(dev_priv);
>  
> -	if (IS_GEN9_LP(dev_priv) ||
> -	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
> +	if (dev_priv->power_domains_suspended)
>  		intel_power_domains_init_hw(dev_priv, true);
>  	else
>  		intel_display_set_init_power(dev_priv, true);
> @@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  	enable_rpm_wakeref_asserts(dev_priv);
>  
>  out:
> -	dev_priv->suspended_to_idle = false;
> +	dev_priv->power_domains_suspended = false;
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index c9c3b2ba6a86..3acc4bbec6b2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1851,7 +1851,7 @@ struct drm_i915_private {
>  	u32 bxt_phy_grc;
>  
>  	u32 suspend_count;
> -	bool suspended_to_idle;
> +	bool power_domains_suspended;
>  	struct i915_suspend_saved_registers regfile;
>  	struct vlv_s0ix_state vlv_s0ix_state;
>  
> -- 
> 2.13.2

-- 
Ville Syrj�l�
Intel OTC

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-23 13:22   ` Ville Syrjälä
@ 2018-03-23 17:33     ` Imre Deak
  -1 siblings, 0 replies; 10+ messages in thread
From: Imre Deak @ 2018-03-23 17:33 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, amn-bas, stable

On Fri, Mar 23, 2018 at 03:22:35PM +0200, Ville Syrjälä wrote:
> On Thu, Mar 22, 2018 at 04:36:42PM +0200, Imre Deak wrote:
> > 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>
> 
> Make sense to me.
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> On thing I can't quite tell is what happens with switcheroo. Maybe it's
> not even relevant for platforms with DC6 in which case I suppose it
> should work correctly.

Yep I haven't noticed that issue. On GEN9+ big core machines hibernating from a
switcheroo off state looks broken for a similar reason: Switcheroo-off on those
machines corresponds to suspending to idle and so DC6, but after resuming from
hibernation power domains and so DC states will be disabled.

The following is one way to fix that preventing s2idle for switcheroo. Since
it's a separate existing issue I could send a proper patch as a follow-up.

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f706cff4f01b..a1c188c9ef05 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1608,7 +1608,7 @@ static int i915_drm_suspend(struct drm_device *dev)
 	return error;
 }
 
-static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
+static int i915_drm_suspend_late(struct drm_device *dev, bool allow_s2idle)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
@@ -1625,7 +1625,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * also enable deeper system power states that would be blocked if the
 	 * firmware was inactive.
 	 */
-	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
+	if (IS_GEN9_LP(dev_priv) || !allow_s2idle || !suspend_to_idle(dev_priv) ||
 	    dev_priv->csr.dmc_payload == NULL) {
 		intel_power_domains_suspend(dev_priv);
 		dev_priv->power_domains_suspended = true;
@@ -1662,7 +1662,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * Fujitsu FSC S7110
 	 * Acer Aspire 1830T
 	 */
-	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
+	if (allow_s2idle || INTEL_GEN(dev_priv) >= 6)
 		pci_set_power_state(pdev, PCI_D3hot);
 
 out:
@@ -2100,7 +2100,7 @@ static int i915_pm_suspend_late(struct device *kdev)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	return i915_drm_suspend_late(dev, false);
+	return i915_drm_suspend_late(dev, true);
 }
 
 static int i915_pm_poweroff_late(struct device *kdev)
@@ -2110,7 +2110,7 @@ static int i915_pm_poweroff_late(struct device *kdev)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	return i915_drm_suspend_late(dev, true);
+	return i915_drm_suspend_late(dev, false);
 }
 
 static int i915_pm_resume_early(struct device *kdev)
@@ -2158,7 +2158,7 @@ static int i915_pm_freeze_late(struct device *kdev)
 	int ret;
 
 	if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) {
-		ret = i915_drm_suspend_late(dev, true);
+		ret = i915_drm_suspend_late(dev, false);
 		if (ret)
 			return ret;
 	}

> 
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
> >  drivers/gpu/drm/i915/i915_drv.h |  2 +-
> >  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 a7d3275f45d2..f706cff4f01b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> > -	bool fw_csr;
> >  	int ret;
> >  
> >  	disable_rpm_wakeref_asserts(dev_priv);
> >  
> >  	intel_display_set_init_power(dev_priv, false);
> >  
> > -	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
> >  	 * deinit the power domains. This also means the CSR/DMC firmware will
> > @@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  	 * also enable deeper system power states that would be blocked if the
> >  	 * firmware was inactive.
> >  	 */
> > -	if (!fw_csr)
> > +	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
> > +	    dev_priv->csr.dmc_payload == NULL) {
> >  		intel_power_domains_suspend(dev_priv);
> > +		dev_priv->power_domains_suspended = true;
> > +	}
> >  
> >  	ret = 0;
> >  	if (IS_GEN9_LP(dev_priv))
> > @@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  
> >  	if (ret) {
> >  		DRM_ERROR("Suspend complete failed: %d\n", ret);
> > -		if (!fw_csr)
> > +		if (dev_priv->power_domains_suspended) {
> >  			intel_power_domains_init_hw(dev_priv, true);
> > +			dev_priv->power_domains_suspended = false;
> > +		}
> >  
> >  		goto out;
> >  	}
> > @@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
> >  		pci_set_power_state(pdev, PCI_D3hot);
> >  
> > -	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
> > -
> >  out:
> >  	enable_rpm_wakeref_asserts(dev_priv);
> >  
> > @@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  	intel_uncore_resume_early(dev_priv);
> >  
> >  	if (IS_GEN9_LP(dev_priv)) {
> > -		if (!dev_priv->suspended_to_idle)
> > -			gen9_sanitize_dc_state(dev_priv);
> > +		gen9_sanitize_dc_state(dev_priv);
> >  		bxt_disable_dc9(dev_priv);
> >  	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> >  		hsw_disable_pc8(dev_priv);
> > @@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  
> >  	intel_uncore_sanitize(dev_priv);
> >  
> > -	if (IS_GEN9_LP(dev_priv) ||
> > -	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
> > +	if (dev_priv->power_domains_suspended)
> >  		intel_power_domains_init_hw(dev_priv, true);
> >  	else
> >  		intel_display_set_init_power(dev_priv, true);
> > @@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  	enable_rpm_wakeref_asserts(dev_priv);
> >  
> >  out:
> > -	dev_priv->suspended_to_idle = false;
> > +	dev_priv->power_domains_suspended = false;
> >  
> >  	return ret;
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index c9c3b2ba6a86..3acc4bbec6b2 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1851,7 +1851,7 @@ struct drm_i915_private {
> >  	u32 bxt_phy_grc;
> >  
> >  	u32 suspend_count;
> > -	bool suspended_to_idle;
> > +	bool power_domains_suspended;
> >  	struct i915_suspend_saved_registers regfile;
> >  	struct vlv_s0ix_state vlv_s0ix_state;
> >  
> > -- 
> > 2.13.2
> 
> -- 
> Ville Syrjälä
> Intel OTC

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH] drm/i915: Fix hibernation with ACPI S0 target state
@ 2018-03-23 17:33     ` Imre Deak
  0 siblings, 0 replies; 10+ messages in thread
From: Imre Deak @ 2018-03-23 17:33 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, amn-bas, stable

On Fri, Mar 23, 2018 at 03:22:35PM +0200, Ville Syrj�l� wrote:
> On Thu, Mar 22, 2018 at 04:36:42PM +0200, Imre Deak wrote:
> > 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>
> 
> Make sense to me.
> Reviewed-by: Ville Syrj�l� <ville.syrjala@linux.intel.com>
> 
> On thing I can't quite tell is what happens with switcheroo. Maybe it's
> not even relevant for platforms with DC6 in which case I suppose it
> should work correctly.

Yep I haven't noticed that issue. On GEN9+ big core machines hibernating from a
switcheroo off state looks broken for a similar reason: Switcheroo-off on those
machines corresponds to suspending to idle and so DC6, but after resuming from
hibernation power domains and so DC states will be disabled.

The following is one way to fix that preventing s2idle for switcheroo. Since
it's a separate existing issue I could send a proper patch as a follow-up.

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f706cff4f01b..a1c188c9ef05 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1608,7 +1608,7 @@ static int i915_drm_suspend(struct drm_device *dev)
 	return error;
 }
 
-static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
+static int i915_drm_suspend_late(struct drm_device *dev, bool allow_s2idle)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
@@ -1625,7 +1625,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * also enable deeper system power states that would be blocked if the
 	 * firmware was inactive.
 	 */
-	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
+	if (IS_GEN9_LP(dev_priv) || !allow_s2idle || !suspend_to_idle(dev_priv) ||
 	    dev_priv->csr.dmc_payload == NULL) {
 		intel_power_domains_suspend(dev_priv);
 		dev_priv->power_domains_suspended = true;
@@ -1662,7 +1662,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 	 * Fujitsu FSC S7110
 	 * Acer Aspire 1830T
 	 */
-	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
+	if (allow_s2idle || INTEL_GEN(dev_priv) >= 6)
 		pci_set_power_state(pdev, PCI_D3hot);
 
 out:
@@ -2100,7 +2100,7 @@ static int i915_pm_suspend_late(struct device *kdev)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	return i915_drm_suspend_late(dev, false);
+	return i915_drm_suspend_late(dev, true);
 }
 
 static int i915_pm_poweroff_late(struct device *kdev)
@@ -2110,7 +2110,7 @@ static int i915_pm_poweroff_late(struct device *kdev)
 	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
 
-	return i915_drm_suspend_late(dev, true);
+	return i915_drm_suspend_late(dev, false);
 }
 
 static int i915_pm_resume_early(struct device *kdev)
@@ -2158,7 +2158,7 @@ static int i915_pm_freeze_late(struct device *kdev)
 	int ret;
 
 	if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) {
-		ret = i915_drm_suspend_late(dev, true);
+		ret = i915_drm_suspend_late(dev, false);
 		if (ret)
 			return ret;
 	}

> 
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c | 22 ++++++++++------------
> >  drivers/gpu/drm/i915/i915_drv.h |  2 +-
> >  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 a7d3275f45d2..f706cff4f01b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1612,15 +1612,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct pci_dev *pdev = dev_priv->drm.pdev;
> > -	bool fw_csr;
> >  	int ret;
> >  
> >  	disable_rpm_wakeref_asserts(dev_priv);
> >  
> >  	intel_display_set_init_power(dev_priv, false);
> >  
> > -	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
> >  	 * deinit the power domains. This also means the CSR/DMC firmware will
> > @@ -1628,8 +1625,11 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  	 * also enable deeper system power states that would be blocked if the
> >  	 * firmware was inactive.
> >  	 */
> > -	if (!fw_csr)
> > +	if (IS_GEN9_LP(dev_priv) || hibernation || !suspend_to_idle(dev_priv) ||
> > +	    dev_priv->csr.dmc_payload == NULL) {
> >  		intel_power_domains_suspend(dev_priv);
> > +		dev_priv->power_domains_suspended = true;
> > +	}
> >  
> >  	ret = 0;
> >  	if (IS_GEN9_LP(dev_priv))
> > @@ -1641,8 +1641,10 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  
> >  	if (ret) {
> >  		DRM_ERROR("Suspend complete failed: %d\n", ret);
> > -		if (!fw_csr)
> > +		if (dev_priv->power_domains_suspended) {
> >  			intel_power_domains_init_hw(dev_priv, true);
> > +			dev_priv->power_domains_suspended = false;
> > +		}
> >  
> >  		goto out;
> >  	}
> > @@ -1663,8 +1665,6 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
> >  	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
> >  		pci_set_power_state(pdev, PCI_D3hot);
> >  
> > -	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
> > -
> >  out:
> >  	enable_rpm_wakeref_asserts(dev_priv);
> >  
> > @@ -1831,8 +1831,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  	intel_uncore_resume_early(dev_priv);
> >  
> >  	if (IS_GEN9_LP(dev_priv)) {
> > -		if (!dev_priv->suspended_to_idle)
> > -			gen9_sanitize_dc_state(dev_priv);
> > +		gen9_sanitize_dc_state(dev_priv);
> >  		bxt_disable_dc9(dev_priv);
> >  	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> >  		hsw_disable_pc8(dev_priv);
> > @@ -1840,8 +1839,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  
> >  	intel_uncore_sanitize(dev_priv);
> >  
> > -	if (IS_GEN9_LP(dev_priv) ||
> > -	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
> > +	if (dev_priv->power_domains_suspended)
> >  		intel_power_domains_init_hw(dev_priv, true);
> >  	else
> >  		intel_display_set_init_power(dev_priv, true);
> > @@ -1851,7 +1849,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
> >  	enable_rpm_wakeref_asserts(dev_priv);
> >  
> >  out:
> > -	dev_priv->suspended_to_idle = false;
> > +	dev_priv->power_domains_suspended = false;
> >  
> >  	return ret;
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index c9c3b2ba6a86..3acc4bbec6b2 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1851,7 +1851,7 @@ struct drm_i915_private {
> >  	u32 bxt_phy_grc;
> >  
> >  	u32 suspend_count;
> > -	bool suspended_to_idle;
> > +	bool power_domains_suspended;
> >  	struct i915_suspend_saved_registers regfile;
> >  	struct vlv_s0ix_state vlv_s0ix_state;
> >  
> > -- 
> > 2.13.2
> 
> -- 
> Ville Syrj�l�
> Intel OTC

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: ✓ Fi.CI.IGT: success for drm/i915: Fix hibernation with ACPI S0 target state
  2018-03-22 16:49 ` ✓ Fi.CI.IGT: " Patchwork
@ 2018-03-23 18:03   ` Imre Deak
  0 siblings, 0 replies; 10+ messages in thread
From: Imre Deak @ 2018-03-23 18:03 UTC (permalink / raw)
  To: intel-gfx, Ville Syrjälä

On Thu, Mar 22, 2018 at 04:49:22PM +0000, Patchwork wrote:
> == Series Details ==
> 
> Series: drm/i915: Fix hibernation with ACPI S0 target state
> URL   : https://patchwork.freedesktop.org/series/40466/
> State : success
> 
> == Summary ==

Thanks for the review, I pushed the patch to -dinq.

> 
> ---- Known issues:
> 
> Test kms_cursor_crc:
>         Subgroup cursor-256x256-suspend:
>                 pass       -> INCOMPLETE (shard-hsw) fdo#103375
> Test kms_flip:
>         Subgroup dpms-vs-vblank-race:
>                 fail       -> PASS       (shard-hsw) fdo#103060 +1
>         Subgroup plain-flip-fb-recreate-interruptible:
>                 pass       -> FAIL       (shard-hsw) fdo#100368 +2
> Test kms_rotation_crc:
>         Subgroup sprite-rotation-180:
>                 fail       -> PASS       (shard-apl) fdo#103925
> Test kms_setmode:
>         Subgroup basic:
>                 fail       -> PASS       (shard-apl) fdo#99912
> 
> fdo#103375 https://bugs.freedesktop.org/show_bug.cgi?id=103375
> fdo#103060 https://bugs.freedesktop.org/show_bug.cgi?id=103060
> fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
> fdo#103925 https://bugs.freedesktop.org/show_bug.cgi?id=103925
> fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
> 
> shard-apl        total:3484 pass:1821 dwarn:1   dfail:0   fail:6   skip:1655 time:13132s
> shard-hsw        total:3477 pass:1770 dwarn:1   dfail:0   fail:2   skip:1702 time:11273s
> shard-snb        total:3484 pass:1363 dwarn:1   dfail:0   fail:3   skip:2117 time:7243s
> Blacklisted hosts:
> shard-kbl        total:3484 pass:1943 dwarn:1   dfail:0   fail:9   skip:1531 time:10063s
> 
> == Logs ==
> 
> For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_8451/shards.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-03-23 18:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-22 14:36 [PATCH] drm/i915: Fix hibernation with ACPI S0 target state Imre Deak
2018-03-22 14:36 ` Imre Deak
2018-03-22 15:31 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-03-22 15:46 ` ✓ Fi.CI.BAT: success " Patchwork
2018-03-22 16:49 ` ✓ Fi.CI.IGT: " Patchwork
2018-03-23 18:03   ` Imre Deak
2018-03-23 13:22 ` [PATCH] " Ville Syrjälä
2018-03-23 13:22   ` Ville Syrjälä
2018-03-23 17:33   ` Imre Deak
2018-03-23 17:33     ` Imre Deak

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.