From: Pranay Samala <pranay.samala@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: karthik.b.s@intel.com, sameer.lattannavar@intel.com,
pranay.samala@intel.com
Subject: [PATCH i-g-t 4/7] lib/igt_pm: Add power/wakeup accessors
Date: Mon, 7 Sep 2026 19:52:56 +0530 [thread overview]
Message-ID: <20260907142259.750528-5-pranay.samala@intel.com> (raw)
In-Reply-To: <20260907142259.750528-1-pranay.samala@intel.com>
Add PCI power/wakeup accessors for igt_pm:
igt_pm_has_wakeup_support()
igt_pm_set_wakeup_enabled()
igt_pm_restore_wakeup()
These helpers expose whether the device supports wakeup accounting and allow
tests to enable/restore the power/wakeup sysfs attribute. This is needed for
PME-based HPD tests, where both device wakeup support and the PM wakeup source
must be enabled.
Assisted-by: GitHub_Copilot:claude-opus-5
Signed-off-by: Pranay Samala <pranay.samala@intel.com>
---
lib/igt_pm.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/igt_pm.h | 3 ++
2 files changed, 136 insertions(+)
diff --git a/lib/igt_pm.c b/lib/igt_pm.c
index 6536405df..a3ad80580 100644
--- a/lib/igt_pm.c
+++ b/lib/igt_pm.c
@@ -1498,6 +1498,139 @@ int igt_pm_get_runtime_usage(struct pci_device *pci_dev)
return usage;
}
+#define IGT_PM_WAKEUP_ENABLED_STR "enabled\n"
+#define IGT_PM_WAKEUP_DISABLED_STR "disabled\n"
+
+static struct {
+ struct pci_device *pci_dev;
+ bool orig_enabled;
+} __igt_pm_wakeup;
+
+static void __igt_pm_wakeup_exit_handler(int sig)
+{
+ igt_pm_restore_wakeup();
+}
+
+/**
+ * igt_pm_has_wakeup_support:
+ * @pci_dev: PCI device struct
+ *
+ * The power/wakeup* sysfs attributes only exist for devices the PM core
+ * considers wakeup capable, so their presence is the check for whether wakeup
+ * source accounting is available at all for @pci_dev.
+ *
+ * Returns: true if the device exposes power/wakeup, false otherwise.
+ */
+bool igt_pm_has_wakeup_support(struct pci_device *pci_dev)
+{
+ int fd = __igt_pm_get_power_attr_fd(pci_dev, "wakeup", O_RDONLY);
+
+ if (fd < 0)
+ return false;
+
+ close(fd);
+
+ return true;
+}
+
+/*
+ * Read power/wakeup, i.e. whether the device is permitted to wake the system.
+ * Returns false if wakeup is disabled or the device is not wakeup capable.
+ *
+ * This gates two separate things. It is the device_may_wakeup() policy, which
+ * the system suspend path requires before arming PME, and which a driver may
+ * also consult from its own runtime suspend hook - xe does, so on xe this
+ * decides whether PME is armed for a runtime suspend at all, see
+ * igt_pm_pci_pme_enabled().
+ *
+ * It also gates the device's wakeup source object: writing "disabled" makes the
+ * PM core drop dev->power.wakeup, after which wakeup events are not accounted
+ * at all and the power/wakeup_* counters read back as a bare newline. Tests
+ * that sample those counters therefore need wakeup enabled, whether or not they
+ * care about system wakeup.
+ */
+static bool igt_pm_get_wakeup_enabled(struct pci_device *pci_dev)
+{
+ char buf[64];
+ int fd;
+ bool enabled;
+
+ fd = __igt_pm_get_power_attr_fd(pci_dev, "wakeup", O_RDONLY);
+ if (fd < 0)
+ return false;
+
+ enabled = igt_pm_read_power_attr(fd, buf, sizeof(buf), false) &&
+ !strcmp(buf, "enabled");
+
+ close(fd);
+
+ return enabled;
+}
+
+/**
+ * igt_pm_set_wakeup_enabled:
+ * @pci_dev: PCI device struct
+ * @enable: whether to allow the device to wake the system
+ *
+ * Writes power/wakeup. The original value is saved on the first call and
+ * restored by an exit handler, or explicitly via igt_pm_restore_wakeup().
+ *
+ * Callers must gate on igt_pm_has_wakeup_support() first.
+ */
+void igt_pm_set_wakeup_enabled(struct pci_device *pci_dev, bool enable)
+{
+ const char *val = enable ? IGT_PM_WAKEUP_ENABLED_STR :
+ IGT_PM_WAKEUP_DISABLED_STR;
+ int len = strlen(val);
+ int fd, size;
+
+ fd = __igt_pm_get_power_attr_fd(pci_dev, "wakeup", O_RDWR);
+ igt_assert_f(fd >= 0, "Device has no power/wakeup attribute\n");
+
+ if (!__igt_pm_wakeup.pci_dev) {
+ __igt_pm_wakeup.orig_enabled = igt_pm_get_wakeup_enabled(pci_dev);
+ __igt_pm_wakeup.pci_dev = pci_dev;
+ igt_install_exit_handler(__igt_pm_wakeup_exit_handler);
+ }
+
+ size = write(fd, val, len);
+ close(fd);
+
+ igt_assert_f(size == len, "Failed to %s power/wakeup\n",
+ enable ? "enable" : "disable");
+
+ igt_debug("PCI '%04x:%02x:%02x.%01x' power/wakeup = %s\n",
+ pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func,
+ enable ? "enabled" : "disabled");
+}
+
+/**
+ * igt_pm_restore_wakeup:
+ *
+ * Restores power/wakeup to the value it had before the first
+ * igt_pm_set_wakeup_enabled() call. Does nothing if it was never changed.
+ */
+void igt_pm_restore_wakeup(void)
+{
+ struct pci_device *pci_dev = __igt_pm_wakeup.pci_dev;
+ const char *val;
+ int fd;
+
+ if (!pci_dev)
+ return;
+
+ val = __igt_pm_wakeup.orig_enabled ? IGT_PM_WAKEUP_ENABLED_STR :
+ IGT_PM_WAKEUP_DISABLED_STR;
+
+ fd = __igt_pm_get_power_attr_fd(pci_dev, "wakeup", O_RDWR);
+ if (fd >= 0) {
+ igt_ignore_warn(write(fd, val, strlen(val)));
+ close(fd);
+ }
+
+ __igt_pm_wakeup.pci_dev = NULL;
+}
+
/**
* igt_pm_ignore_slpc_efficient_freq:
* @i915: open i915 drm file descriptor
diff --git a/lib/igt_pm.h b/lib/igt_pm.h
index 2784e97be..12617c2ef 100644
--- a/lib/igt_pm.h
+++ b/lib/igt_pm.h
@@ -103,6 +103,9 @@ bool i915_is_slpc_enabled(int drm_fd);
uint64_t igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev);
uint64_t igt_pm_get_runtime_active_time(struct pci_device *pci_dev);
int igt_pm_get_runtime_usage(struct pci_device *pci_dev);
+bool igt_pm_has_wakeup_support(struct pci_device *pci_dev);
+void igt_pm_set_wakeup_enabled(struct pci_device *pci_dev, bool enable);
+void igt_pm_restore_wakeup(void);
void igt_pm_ignore_slpc_efficient_freq(int i915, int gtfd, bool val);
bool igt_has_pci_pm_capability(struct pci_device *pci_dev);
bool igt_pm_pci_pme_supported(struct pci_device *pci_dev,
--
2.53.0
next prev parent reply other threads:[~2026-09-07 14:13 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 14:22 [PATCH i-g-t 0/7] Validate PM_PME signalling on display hotplug Pranay Samala
2026-09-07 14:22 ` [PATCH i-g-t 1/7] lib/igt_pci: Add PCI Power Management capability register layout Pranay Samala
2026-09-07 14:22 ` [PATCH i-g-t 2/7] lib/igt_pm: Add PCI PME capability and D state accessors Pranay Samala
2026-09-07 14:22 ` [PATCH i-g-t 3/7] lib/igt_pm: Factor out power attribute path construction Pranay Samala
2026-09-07 14:22 ` Pranay Samala [this message]
2026-09-07 14:22 ` [PATCH i-g-t 5/7] lib/igt_pm: Add power/wakeup_active_count accessor Pranay Samala
2026-09-07 14:22 ` [PATCH i-g-t 6/7] lib/igt_pm: Add drm_kms_helper.poll save/restore helpers Pranay Samala
2026-09-07 14:22 ` [PATCH i-g-t 7/7] tests/chamelium/kms_chamelium_hpd: Add HPD from runtime suspended D3hot Pranay Samala
2026-09-07 19:49 ` ✓ Xe.CI.BAT: success for Validate PM_PME signalling on display hotplug (rev2) Patchwork
2026-09-07 20:02 ` ✓ i915.CI.BAT: " Patchwork
2026-09-08 0:17 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-09-08 6:28 ` ✗ i915.CI.Full: " 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=20260907142259.750528-5-pranay.samala@intel.com \
--to=pranay.samala@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=karthik.b.s@intel.com \
--cc=sameer.lattannavar@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 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.