From: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: Vinay Belgaumkar <vinay.belgaumkar@intel.com>,
Badal Nilawar <badal.nilawar@intel.com>,
Rodrigo Vivi <rodrigo.vivi@intel.com>
Subject: [PATCH v3 2/2] drm/xe: Poll GT for C6 before D3
Date: Thu, 10 Sep 2026 14:57:56 -0700 [thread overview]
Message-ID: <20260910215756.2393137-2-vinay.belgaumkar@intel.com> (raw)
In-Reply-To: <20260910215756.2393137-1-vinay.belgaumkar@intel.com>
Check if GTs are in C6 before transitioning to D3. PM subsystem can
retry if this is not the case. This ensures some component is not
accessing the GT when D3 state is forced. This check can be added
to the runtime idle check since it helps to check for pending
forcewakes as well before we poll for GT C6.
v2: Force resume when we cancel suspend due to C6 check (Sashiko)
v3: Abort the suspend properly when idle check fails (Sashiko)
Cc: Badal Nilawar <badal.nilawar@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
---
drivers/gpu/drm/xe/xe_gt_idle.c | 37 +++++++++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_gt_idle.h | 1 +
drivers/gpu/drm/xe/xe_pci.c | 13 +++++++++++-
drivers/gpu/drm/xe/xe_pm.c | 4 ++++
4 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c
index c208d7563e36..e077f9a13473 100644
--- a/drivers/gpu/drm/xe/xe_gt_idle.c
+++ b/drivers/gpu/drm/xe/xe_gt_idle.c
@@ -8,10 +8,12 @@
#include <drm/drm_managed.h>
#include <generated/xe_wa_oob.h>
+#include <linux/iopoll.h>
#include "xe_force_wake.h"
#include "xe_device.h"
#include "xe_gt.h"
#include "xe_gt_idle.h"
+#include "xe_gt_printk.h"
#include "xe_gt_sysfs.h"
#include "xe_guc_pc.h"
#include "regs/xe_gt_regs.h"
@@ -451,3 +453,38 @@ int xe_gt_idle_disable_c6(struct xe_gt *gt)
return 0;
}
+
+static int wait_for_gt_c6_state(struct xe_gt *gt,
+ u16 timeout_ms)
+{
+ struct xe_guc_pc *pc = >->uc.guc.pc;
+ enum xe_gt_idle_state state;
+
+ return poll_timeout_us(state = gt->gtidle.idle_status(pc),
+ state == GT_IDLE_C6,
+ 20,
+ timeout_ms * USEC_PER_MSEC,
+ false);
+}
+
+/**
+ * xe_gt_idle_wait_for_c6 - Poll for GT C6
+ * @gt: GT object
+ * @timeout_ms: wait time in ms
+ *
+ * This function polls for GT C6 state
+ *
+ * Return: 0 on success, -EAGAIN otherwise
+ */
+int xe_gt_idle_wait_for_c6(struct xe_gt *gt, u16 timeout_ms)
+{
+ if (IS_SRIOV_VF(gt_to_xe(gt)))
+ return 0;
+
+ if (wait_for_gt_c6_state(gt, timeout_ms)) {
+ xe_gt_dbg(gt, "GT is not in C6\n");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/xe/xe_gt_idle.h b/drivers/gpu/drm/xe/xe_gt_idle.h
index 9c34a155e102..74d6bd167fab 100644
--- a/drivers/gpu/drm/xe/xe_gt_idle.h
+++ b/drivers/gpu/drm/xe/xe_gt_idle.h
@@ -18,5 +18,6 @@ void xe_gt_idle_enable_pg(struct xe_gt *gt);
void xe_gt_idle_disable_pg(struct xe_gt *gt);
int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p);
u64 xe_gt_idle_residency_msec(struct xe_gt_idle *gtidle);
+int xe_gt_idle_wait_for_c6(struct xe_gt *gt, u16 timeout_ms);
#endif /* _XE_GT_IDLE_H_ */
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index a79d928ad75a..b0e0bd363e65 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -1327,7 +1327,7 @@ static int xe_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
- int err;
+ int err, ret;
if (xe_survivability_mode_is_boot_enabled(xe))
return -EBUSY;
@@ -1343,6 +1343,17 @@ static int xe_pci_suspend(struct device *dev)
*/
d3cold_toggle(pdev, D3COLD_ENABLE);
+ ret = xe_pm_check_runtime_idle(xe);
+ if (ret) {
+ err = xe_pm_runtime_resume(xe);
+ if (err) {
+ drm_err(&xe->drm, "Resume failed after suspend was canceled");
+ return err;
+ }
+
+ return ret;
+ }
+
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3cold);
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index e8d4cdbaef88..04529a242998 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -1046,6 +1046,10 @@ int xe_pm_check_runtime_idle(struct xe_device *xe)
if (xe_force_wake_any_bit_set(gt_to_fw(gt), XE_FW_DOMAIN_ID_GT))
return -EBUSY;
+ for_each_gt(gt, xe, id)
+ if (xe_gt_idle_wait_for_c6(gt, 200))
+ return -EAGAIN;
+
return 0;
}
--
2.38.1
next prev parent reply other threads:[~2026-09-10 22:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 21:57 [PATCH v3 1/2] drm/xe: Inspect all forcewake bits for runtime idleness Vinay Belgaumkar
2026-09-10 21:57 ` Vinay Belgaumkar [this message]
2026-09-10 22:11 ` [PATCH v3 2/2] drm/xe: Poll GT for C6 before D3 sashiko-bot
2026-09-10 22:14 ` [PATCH v3 1/2] drm/xe: Inspect all forcewake bits for runtime idleness sashiko-bot
2026-09-10 22:18 ` ✗ CI.checkpatch: warning for series starting with [v3,1/2] " Patchwork
2026-09-10 22:20 ` ✓ CI.KUnit: success " Patchwork
2026-09-10 23:13 ` ✓ Xe.CI.BAT: " Patchwork
2026-09-11 7:46 ` ✗ Xe.CI.FULL: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260910215756.2393137-2-vinay.belgaumkar@intel.com \
--to=vinay.belgaumkar@intel.com \
--cc=badal.nilawar@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox