All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT
@ 2022-05-05 11:03 Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 1/9] test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf} Anshuman Gupta
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

This series adds support for D3Cold Tool and IGT.

v4 has added new patch to this series.

Anshuman Gupta (9):
  test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf}
  lib/igt_device: Get gfx PCI card root port
  lib/igt_pm: D3Cold runtime pm infrastructure
  tools: Add intel_pm_rpm tool
  tools/intel_pm_rpm: Add an option to configure autosuspend
  i915_pm_rpm: Add D3Cold basic subtest
  i915_pm_rpm: Extend gem_exec_stress test with D3Cold
  i915_pm_rpm: Extend gem_execbuf test with D3Cold
  i915_pm_rpm: Extend gem-mmap-type test with D3Cold

 lib/igt_device.c         |  28 ++++
 lib/igt_device.h         |   1 +
 lib/igt_pm.c             | 341 +++++++++++++++++++++++++++++++++++++++
 lib/igt_pm.h             |  24 +++
 tests/i915/i915_pm_rpm.c | 199 +++++++++++++++++++++--
 tools/intel_pm_rpm.c     | 230 ++++++++++++++++++++++++++
 tools/meson.build        |   1 +
 7 files changed, 815 insertions(+), 9 deletions(-)
 create mode 100644 tools/intel_pm_rpm.c

-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 1/9] test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf}
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 2/9] lib/igt_device: Get gfx PCI card root port Anshuman Gupta
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, Chris Wilson, badal.nilawar, rodrigo.vivi

Add memory region placement to gem-{mmap-type, execbuf} subtest.
This will be useful to extend these sub-test for D3Cold.

Cc: Chris Wilson <chris.p.wilson@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 tests/i915/i915_pm_rpm.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/tests/i915/i915_pm_rpm.c b/tests/i915/i915_pm_rpm.c
index 461730e8a..d2bce5826 100644
--- a/tests/i915/i915_pm_rpm.c
+++ b/tests/i915/i915_pm_rpm.c
@@ -1069,7 +1069,8 @@ static void debugfs_forcewake_user_subtest(void)
 	igt_assert(wait_for_suspended());
 }
 
-static void gem_mmap_args(const struct mmap_offset *t)
+static void gem_mmap_args(const struct mmap_offset *t,
+			  struct drm_i915_gem_memory_class_instance *mem_regions)
 {
 	int i;
 	uint32_t handle;
@@ -1079,7 +1080,7 @@ static void gem_mmap_args(const struct mmap_offset *t)
 	/* Create, map and set data while the device is active. */
 	enable_one_screen_and_wait(&ms_data);
 
-	handle = gem_create(drm_fd, buf_size);
+	handle = gem_create_in_memory_region_list(drm_fd, buf_size, mem_regions, 1);
 
 	gem_buf = __gem_mmap_offset(drm_fd, handle, 0, buf_size,
 				    PROT_READ | PROT_WRITE, t->type);
@@ -1290,7 +1291,7 @@ static void submit_blt_cmd(uint32_t dst_handle, int dst_size,
 }
 
 /* Make sure we can submit a batch buffer and verify its result. */
-static void gem_execbuf_subtest(void)
+static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_regions)
 {
 	int x, y;
 	uint32_t handle;
@@ -1308,7 +1309,7 @@ static void gem_execbuf_subtest(void)
 	/* Create and set data while the device is active. */
 	enable_one_screen_and_wait(&ms_data);
 
-	handle = gem_create(drm_fd, dst_size);
+	handle = gem_create_in_memory_region_list(drm_fd, dst_size, mem_regions, 1);
 
 	cpu_buf = malloc(dst_size);
 	igt_assert(cpu_buf);
@@ -2083,15 +2084,21 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 	/* GEM */
 	igt_subtest_with_dynamic("gem-mmap-type") {
 		for_each_mmap_offset_type(drm_fd, t) {
-			igt_dynamic_f("%s", t->name)
-				gem_mmap_args(t);
+			for_each_memory_region(r, drm_fd) {
+				igt_dynamic_f("%s-%s", t->name, r->name)
+				gem_mmap_args(t, &r->ci);
+			}
 		}
 	}
 
 	igt_subtest("gem-pread")
 		gem_pread_subtest();
-	igt_subtest("gem-execbuf")
-		gem_execbuf_subtest();
+	igt_subtest_with_dynamic("gem-execbuf") {
+		for_each_memory_region(r, drm_fd) {
+			igt_dynamic_f("%s", r->name)
+				gem_execbuf_subtest(&r->ci);
+		}
+	}
 	igt_subtest("gem-idle")
 		gem_idle_subtest();
 	igt_subtest("gem-evict-pwrite") {
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 2/9] lib/igt_device: Get gfx PCI card root port
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 1/9] test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf} Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure Anshuman Gupta
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Utility library function to get the Gfx Card PCI topology
root port pci device using libpaciaccess.
root port will be used to get the real ACPI D state.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 lib/igt_device.c | 28 ++++++++++++++++++++++++++++
 lib/igt_device.h |  1 +
 2 files changed, 29 insertions(+)

diff --git a/lib/igt_device.c b/lib/igt_device.c
index 9794a9928..fddfba72c 100644
--- a/lib/igt_device.c
+++ b/lib/igt_device.c
@@ -257,3 +257,31 @@ struct pci_device *igt_device_get_pci_device(int fd)
 
 	return pci_dev;
 }
+
+/**
+ * igt_device_get_pci_root_port:
+ * @fd: the device.
+ *
+ * Looks up the graphics pci device root port using libpciaccess.
+ *
+ * Returns:
+ * The root port pci_device.
+ */
+struct pci_device *
+igt_device_get_pci_root_port(int fd)
+{
+	struct pci_device *pci_dev, *prev;
+
+	pci_dev = __igt_device_get_pci_device(fd, 0);
+	igt_require(pci_dev);
+
+	while (pci_dev) {
+		prev = pci_dev;
+		pci_dev = pci_device_get_parent_bridge(pci_dev);
+	}
+
+	igt_debug("Root Port PCI device %04x:%02x:%02x.%01x\n",
+		  prev->domain, prev->bus, prev->dev, prev->func);
+
+	return prev;
+}
diff --git a/lib/igt_device.h b/lib/igt_device.h
index 1aaa840e2..800a0fcc3 100644
--- a/lib/igt_device.h
+++ b/lib/igt_device.h
@@ -34,5 +34,6 @@ void igt_device_drop_master(int fd);
 int igt_device_get_card_index(int fd);
 struct pci_device *igt_device_get_pci_device(int fd);
 struct pci_device *__igt_device_get_pci_device(int fd, unsigned int vf_id);
+struct pci_device *igt_device_get_pci_root_port(int fd);
 
 #endif /* __IGT_DEVICE_H__ */
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 1/9] test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf} Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 2/9] lib/igt_device: Get gfx PCI card root port Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 16:16   ` Rodrigo Vivi
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool Anshuman Gupta
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Enable gfx card pci devices runtime pm for all pci devices
and bridge under the topology of Gfx Card root port.

Added a library function to get the PCI root port ACPI
D state and to print the pci card devices runtime pm
status.

v2:
- Save pci dev power attr to dynamically allocated array. [Rodrigo]
- Set autosuspend delay to 0 on supported devices. [Rodrigo]
- %s/else if/else in  igt_pm_get_acpi_real_d_state. [Kamil]
v3:
- Add comment for MAX_PCI_DEVICES. [Badal]
- Use static global arrary __pci_dev_pwrattr[]. [Rodrigo]
- Use pci_slot_match iter. [Badal]
- Destroy the iter. [Badal]
v4:
- Added igt_pm_enbale_pci_card_autosuspend() to avoid any
  control attr save/resore by exit handler. [Rodrigo]

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 lib/igt_pm.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/igt_pm.h |  24 ++++
 2 files changed, 365 insertions(+)

diff --git a/lib/igt_pm.c b/lib/igt_pm.c
index b409ec463..8e5aa9208 100644
--- a/lib/igt_pm.c
+++ b/lib/igt_pm.c
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <limits.h>
+#include <pciaccess.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -75,6 +76,8 @@ enum {
 #define MIN_POWER_STR		"min_power\n"
 /* Remember to fix this if adding longer strings */
 #define MAX_POLICY_STRLEN	strlen(MAX_PERFORMANCE_STR)
+/* Root Port bus can have max 32 dev and each dev can have max 8 func */
+#define MAX_PCI_DEVICES		256
 int8_t *__sata_pm_policies;
 int __scsi_host_cnt;
 
@@ -856,3 +859,341 @@ bool i915_output_is_lpsp_capable(int drm_fd, igt_output_t *output)
 
 	return strstr(buf, "LPSP: capable");
 }
+
+/**
+ * igt_pm_acpi_d3cold_supported:
+ * @pci_dev: root port pci_dev.
+ * Check ACPI D3Cold support.
+ *
+ * Returns:
+ * True if ACPI D3Cold supported otherwise false.
+ */
+bool igt_pm_acpi_d3cold_supported(struct pci_device *pci_dev)
+{
+	char name[PATH_MAX];
+	int dir, fd;
+
+	snprintf(name, PATH_MAX,
+		 "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/firmware_node",
+		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
+
+	dir = open(name, O_RDONLY);
+	igt_require(dir > 0);
+
+	/* BIOS need to enable ACPI D3Cold Support.*/
+	fd = openat(dir, "real_power_state", O_RDONLY);
+	if (fd < 0 && errno == ENOENT)
+		return false;
+
+	igt_require(fd > 0);
+
+	return true;
+}
+
+/**
+ * igt_pm_get_acpi_real_d_state:
+ * @pci_dev: root port pci_dev.
+ * Get ACPI D state for a given root port.
+ *
+ * Returns:
+ * igt_acpi_d_state state.
+ */
+enum igt_acpi_d_state
+igt_pm_get_acpi_real_d_state(struct pci_device *pci_dev)
+{
+	char name[PATH_MAX];
+	char acpi_d_state[64];
+	int fd, n_read;
+
+	snprintf(name, PATH_MAX,
+		 "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/firmware_node/real_power_state",
+		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
+
+	fd = open(name, O_RDONLY);
+	if (fd < 0)
+		return IGT_ACPI_UNKNOWN_STATE;
+
+	n_read = read(fd, acpi_d_state, sizeof(acpi_d_state) - 1);
+	igt_assert(n_read >= 0);
+	acpi_d_state[n_read] = '\0';
+	close(fd);
+
+	if (strncmp(acpi_d_state, "D0\n", n_read) == 0)
+		return IGT_ACPI_D0;
+	if  (strncmp(acpi_d_state, "D1\n", n_read) == 0)
+		return IGT_ACPI_D1;
+	if  (strncmp(acpi_d_state, "D2\n", n_read) == 0)
+		return IGT_ACPI_D2;
+	if  (strncmp(acpi_d_state, "D3hot\n", n_read) == 0)
+		return IGT_ACPI_D3Hot;
+	if  (strncmp(acpi_d_state, "D3cold\n", n_read) == 0)
+		return IGT_ACPI_D3Cold;
+
+	return IGT_ACPI_UNKNOWN_STATE;
+}
+
+static struct igt_pm_pci_dev_pwrattr  __pci_dev_pwrattr[MAX_PCI_DEVICES];
+
+static void __igt_pm_pci_card_exit_handler(int sig)
+{
+	igt_pm_restore_pci_card_runtime_pm();
+}
+
+static int igt_pm_get_power_attr_fd(struct pci_device *pci_dev, const char *attr)
+{
+	char name[PATH_MAX];
+	int fd;
+
+	snprintf(name, PATH_MAX, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/power/%s",
+		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, attr);
+
+	fd = open(name, O_RDWR);
+	igt_assert_f(fd >= 0, "Can't open %s\n", attr);
+
+	return fd;
+}
+
+static bool igt_pm_save_power_attr(int fd, char *attr, int len, bool autosuspend)
+{
+	int size;
+
+	size = read(fd, attr, len - 1);
+
+	if (autosuspend) {
+		if (size < 0)
+			return false;
+	} else {
+		igt_assert(size > 0);
+	}
+
+	attr[size] = '\0';
+	strchomp(attr);
+
+	return true;
+}
+
+static void igt_pm_setup_power_attr(int fd, const char *val)
+{
+	int size, len;
+	char buf[6];
+
+	len = strlen(val);
+
+	size = write(fd, val, len);
+	igt_assert_eq(size, len);
+	lseek(fd, 0, SEEK_SET);
+	size = read(fd, buf, ARRAY_SIZE(buf));
+	igt_assert_eq(size, len);
+	igt_assert(strncmp(buf, val, len) == 0);
+}
+
+static void
+__igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev, int index)
+{
+	int control_fd, delay_fd, control_size, delay_size;
+	char *control, *delay;
+
+	igt_assert(index <  MAX_PCI_DEVICES);
+
+	control = __pci_dev_pwrattr[index].control;
+	control_size =  sizeof(__pci_dev_pwrattr[index].control);
+	delay = __pci_dev_pwrattr[index].autosuspend_delay;
+	delay_size =  sizeof(__pci_dev_pwrattr[index].autosuspend_delay);
+	__pci_dev_pwrattr[index].pci_dev = pci_dev;
+	__pci_dev_pwrattr[index].autosuspend_supported = true;
+
+	delay_fd = igt_pm_get_power_attr_fd(pci_dev, "autosuspend_delay_ms");
+	control_fd = igt_pm_get_power_attr_fd(pci_dev, "control");
+
+	if (!igt_pm_save_power_attr(delay_fd, delay, delay_size, true)) {
+		__pci_dev_pwrattr[index].autosuspend_supported = false;
+		igt_debug("PCI '%04x:%02x:%02x.%01x' doesn't support auto_suspend\n",
+			  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
+	}
+
+	igt_pm_save_power_attr(control_fd, control, control_size, false);
+	igt_debug("PCI '%04x:%02x:%02x.%01x' Saved 'control, autosuspend_delay_ms' as '%s, %s'\n",
+		  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, control,
+		  __pci_dev_pwrattr[index].autosuspend_supported ? delay : "NA");
+
+	if (!index)
+		igt_install_exit_handler(__igt_pm_pci_card_exit_handler);
+
+	if (__pci_dev_pwrattr[index].autosuspend_supported)
+		igt_pm_setup_power_attr(delay_fd, "0\n");
+
+	igt_pm_setup_power_attr(control_fd, "auto\n");
+
+	close(delay_fd);
+	close(control_fd);
+}
+
+static struct
+pci_device_iterator *igt_pm_get_pci_dev_itr(struct pci_device *pci_dev)
+{
+	struct pci_device_iterator *iter;
+	struct pci_slot_match match;
+	int ret;
+
+	ret = pci_system_init();
+	igt_assert(!ret);
+
+	match.domain = pci_dev->domain;
+	match.bus = PCI_MATCH_ANY;
+	match.dev = PCI_MATCH_ANY;
+	match.func = PCI_MATCH_ANY;
+	iter = pci_slot_match_iterator_create(&match);
+
+	return iter;
+}
+
+/**
+ * igt_pm_enbale_pci_card_autosuspend:
+ * @pci_dev: root port pci_dev.
+ * Setup runtime PM for all PCI endpoints devices for a given root port by
+ * setting power/control attr to "auto".
+ *
+ * Returns:
+ * Zero if success else returns error.
+ */
+int igt_pm_enbale_pci_card_autosuspend(struct pci_device *pci_dev)
+{
+	int primary, secondary, subordinate, ret, control_fd;
+	struct pci_device_iterator *iter;
+	struct pci_device *dev;
+
+	ret = pci_device_get_bridge_buses(pci_dev, &primary, &secondary, &subordinate);
+	if (ret)
+		return ret;
+
+	iter = igt_pm_get_pci_dev_itr(pci_dev);
+	if (!iter)
+		return -ENODEV;
+
+	control_fd = igt_pm_get_power_attr_fd(pci_dev, "control");
+	igt_pm_setup_power_attr(control_fd, "auto\n");
+	while ((dev = pci_device_next(iter)) != NULL) {
+		if (dev->bus >= secondary && dev->bus <= subordinate) {
+			control_fd = igt_pm_get_power_attr_fd(dev, "control");
+			igt_pm_setup_power_attr(control_fd, "auto\n");
+		}
+	}
+
+	pci_iterator_destroy(iter);
+	pci_system_cleanup();
+
+	return 0;
+}
+
+/**
+ * igt_pm_setup_pci_card_runtime_pm:
+ * @pci_dev: root port pci_dev.
+ * Setup runtime PM for all PCI endpoints devices for a given root port by
+ * enabling runtime suspend and setting autosuspend_delay_ms to zero.
+ * It also saves power control attribute for all PCI endpoints
+ * devices under given root port.
+ */
+void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev)
+{
+	int primary, secondary, subordinate, ret;
+	struct pci_device_iterator *iter;
+	struct pci_device *dev;
+	int i = 0;
+
+	memset(__pci_dev_pwrattr, 0, sizeof(__pci_dev_pwrattr));
+	ret = pci_device_get_bridge_buses(pci_dev, &primary, &secondary, &subordinate);
+	igt_assert(!ret);
+
+	/* Setup runtime pm for PCI root port */
+	__igt_pm_setup_pci_card_runtime_pm(pci_dev, i++);
+
+	iter = igt_pm_get_pci_dev_itr(pci_dev);
+	igt_assert(iter);
+	while ((dev = pci_device_next(iter)) != NULL) {
+		if (dev->bus >= secondary && dev->bus <= subordinate)
+			__igt_pm_setup_pci_card_runtime_pm(dev, i++);
+	}
+
+	pci_iterator_destroy(iter);
+}
+
+static void
+igt_pm_restore_power_attr(struct pci_device *pci_dev, const char *attr, char *val, int len)
+{
+	int fd;
+
+	igt_debug("PCI '%04x:%02x:%02x.%01x' Restoring %s attr to '%s'\n",
+		  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, attr, val);
+
+	fd = igt_pm_get_power_attr_fd(pci_dev, attr);
+	igt_assert(write(fd, val, len) == len);
+
+	close(fd);
+}
+
+/**
+ * igt_pm_restore_pci_card_runtime_pm:
+ * Restore control and autosuspend_delay_ms power attribute for all
+ * PCI endpoints devices under gfx root port, which were saved earlier
+ * by igt_pm_setup_pci_card_runtime_pm().
+ */
+void igt_pm_restore_pci_card_runtime_pm(void)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_PCI_DEVICES; i++) {
+		if (!__pci_dev_pwrattr[i].pci_dev)
+			break;
+
+		igt_pm_restore_power_attr(__pci_dev_pwrattr[i].pci_dev, "control",
+					  __pci_dev_pwrattr[i].control,
+					  sizeof(__pci_dev_pwrattr[i].control));
+
+		if (!__pci_dev_pwrattr[i].autosuspend_supported)
+			continue;
+
+		igt_pm_restore_power_attr(__pci_dev_pwrattr[i].pci_dev, "autosuspend_delay_ms",
+					  __pci_dev_pwrattr[i].autosuspend_delay,
+					  sizeof(__pci_dev_pwrattr[i].autosuspend_delay));
+	}
+
+	memset(__pci_dev_pwrattr, 0, sizeof(__pci_dev_pwrattr));
+	pci_system_cleanup();
+}
+
+static void igt_pm_print_pci_dev_runtime_status(struct pci_device *pci_dev)
+{
+	char name[PATH_MAX], runtime_status[64];
+	int fd, n_read;
+
+	snprintf(name, PATH_MAX, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/power/runtime_status",
+		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
+
+	fd = open(name, O_RDONLY);
+	igt_assert_f(fd >= 0, "Can't open runtime_status\n");
+
+	n_read = read(fd, runtime_status, sizeof(runtime_status) - 1);
+	igt_assert(n_read >= 0);
+	runtime_status[n_read] = '\0';
+	igt_info("runtime suspend status for PCI '%04x:%02x:%02x.%01x' %s\n",
+		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, runtime_status);
+	close(fd);
+}
+
+/**
+ * igt_pm_print_pci_card_runtime_status:
+ * @pci_dev: root port pci_dev.
+ * Print runtime suspend status for all PCI endpoints devices for a given
+ * root port.
+ */
+void igt_pm_print_pci_card_runtime_status(void)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_PCI_DEVICES; i++) {
+		if (!__pci_dev_pwrattr[i].pci_dev)
+			break;
+
+		igt_pm_print_pci_dev_runtime_status(__pci_dev_pwrattr[i].pci_dev);
+	}
+}
diff --git a/lib/igt_pm.h b/lib/igt_pm.h
index 162d3ca3c..db187cc2e 100644
--- a/lib/igt_pm.h
+++ b/lib/igt_pm.h
@@ -46,6 +46,23 @@ enum igt_runtime_pm_status {
 	IGT_RUNTIME_PM_STATUS_UNKNOWN,
 };
 
+/* PCI ACPI firmware node real state */
+enum igt_acpi_d_state {
+	IGT_ACPI_D0,
+	IGT_ACPI_D1,
+	IGT_ACPI_D2,
+	IGT_ACPI_D3Hot,
+	IGT_ACPI_D3Cold,
+	IGT_ACPI_UNKNOWN_STATE,
+};
+
+struct	igt_pm_pci_dev_pwrattr {
+	struct pci_device *pci_dev;
+	char control[64];
+	bool autosuspend_supported;
+	char autosuspend_delay[64];
+};
+
 bool igt_setup_runtime_pm(int device);
 void igt_disable_runtime_pm(void);
 void igt_restore_runtime_pm(void);
@@ -54,5 +71,12 @@ bool igt_wait_for_pm_status(enum igt_runtime_pm_status status);
 bool igt_pm_dmc_loaded(int debugfs);
 bool igt_pm_pc8_plus_residencies_enabled(int msr_fd);
 bool i915_output_is_lpsp_capable(int drm_fd, igt_output_t *output);
+bool igt_pm_acpi_d3cold_supported(struct pci_device *pci_dev);
+enum igt_acpi_d_state
+igt_pm_get_acpi_real_d_state(struct pci_device *pci_dev);
+int igt_pm_enbale_pci_card_autosuspend(struct pci_device *pci_dev);
+void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev);
+void igt_pm_restore_pci_card_runtime_pm(void);
+void igt_pm_print_pci_card_runtime_status(void);
 
 #endif /* IGT_PM_H */
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (2 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 16:22   ` Rodrigo Vivi
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend Anshuman Gupta
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 6668 bytes --]

intel_pm_rpm tool is a debug tool. It can be use to setup
and prepare the gfx card to go to D3Cold.
It also provide the debug option to disable all display and
prepare device to enter to runtime suspend.

v2:
- Removed IS_DGFX() condition.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 tools/intel_pm_rpm.c | 206 +++++++++++++++++++++++++++++++++++++++++++
 tools/meson.build    |   1 +
 2 files changed, 207 insertions(+)
 create mode 100644 tools/intel_pm_rpm.c

diff --git a/tools/intel_pm_rpm.c b/tools/intel_pm_rpm.c
new file mode 100644
index 000000000..bf8212b3c
--- /dev/null
+++ b/tools/intel_pm_rpm.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2022 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "igt.h"
+#include "igt_device.h"
+#include "igt_device_scan.h"
+#include "igt_pm.h"
+
+typedef struct {
+	int drm_fd;
+	int debugfs_fd;
+	uint32_t devid;
+	drmModeResPtr res;
+	igt_display_t display;
+} data_t;
+
+const char *help_str =
+	"  --disable-display\t\tDisable all screen and try to go into runtime pm.\n"
+	"  --setup-d3cold\t\tPrepare dgfx gfx card to enter runtime D3Cold.\n"
+	"  --help\t\tProvide help. Provide card name with IGT_DEVICE=drm:/dev/dri/card*.";
+static struct option long_options[] = {
+	{"disable-display", 0, 0, 'd'},
+	{"setup-d3cold", 0, 0, 's'},
+	{"help", 0, 0, 'h'},
+	{ 0, 0, 0, 0 }
+};
+
+const char *optstr = "dsh";
+
+static void usage(const char *name)
+{
+	igt_info("Usage: %s [options]\n", name);
+	igt_info("%s\n", help_str);
+}
+
+static void disable_all_displays(data_t *data)
+{
+	igt_output_t *output;
+
+	for (int i = 0; i < data->display.n_outputs; i++) {
+		output = &data->display.outputs[i];
+		igt_output_set_pipe(output, PIPE_NONE);
+		igt_display_commit(&data->display);
+	}
+}
+
+static void setup_gfx_card_d3cold(data_t *data)
+{
+	struct pci_device *root;
+	int d_state;
+
+	root = igt_device_get_pci_root_port(data->drm_fd);
+
+	if (!igt_pm_acpi_d3cold_supported(root)) {
+		igt_info("D3Cold isn't supported on Root port %04x:%02x:%02x.%01x\n",
+			 root->domain, root->bus, root->dev, root->func);
+		return;
+	}
+
+	disable_all_displays(data);
+	igt_pm_setup_pci_card_runtime_pm(root);
+	sleep(1);
+	d_state = igt_pm_get_acpi_real_d_state(root);
+
+	if (d_state == IGT_ACPI_D3Cold) {
+		igt_info("D3Cold achieved for root port %04x:%02x:%02x.%01x\n",
+			 root->domain, root->bus, root->dev, root->func);
+	} else {
+		igt_pm_print_pci_card_runtime_status();
+		igt_info("D3Cold not achieved yet. Please monitor %04x:%02x:%02x.%01x real_power_state\n",
+			 root->domain, root->bus, root->dev, root->func);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	bool disable_display = false, setup_d3cold = false;
+	struct igt_device_card card;
+	char *env_device = NULL;
+	int c, option_index = 0;
+	data_t data = {};
+	int ret = 0;
+
+	if (argc <= 1) {
+		usage(argv[0]);
+		return EXIT_SUCCESS;
+	}
+
+	env_device = getenv("IGT_DEVICE");
+	igt_devices_scan(false);
+
+	if (env_device) {
+		if (!igt_device_card_match(env_device, &card)) {
+			igt_warn("No device found for the env_device\n");
+			ret = EXIT_FAILURE;
+			goto exit;
+		}
+	} else {
+		if (!igt_device_find_first_i915_discrete_card(&card)) {
+			igt_warn("No discrete gpu found\n");
+			ret = EXIT_FAILURE;
+			goto exit;
+		}
+	}
+
+	while ((c = getopt_long(argc, argv, optstr,
+				long_options, &option_index)) != -1) {
+		switch (c) {
+		case 'd':
+			disable_display = true;
+			break;
+		case 's':
+			setup_d3cold = true;
+			break;
+		default:
+		case 'h':
+			usage(argv[0]);
+			ret = EXIT_SUCCESS;
+			goto exit;
+		}
+	}
+
+	data.drm_fd = igt_open_card(&card);
+	if (data.drm_fd  >= 0) {
+		igt_info("Device %s successfully opened\n", card.card);
+	} else {
+		igt_warn("Cannot open card %s device\n", card.card);
+		ret = EXIT_FAILURE;
+		goto exit;
+	}
+
+	data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
+	data.devid = intel_get_drm_devid(data.drm_fd);
+	igt_setup_runtime_pm(data.drm_fd);
+
+	data.res = drmModeGetResources(data.drm_fd);
+	if (data.res) {
+		kmstest_set_vt_graphics_mode();
+		igt_display_require(&data.display, data.drm_fd);
+
+		/* i915 disables RPM in case DMC is not loaded on kms supported cards */
+		if (!igt_pm_dmc_loaded(data.debugfs_fd)) {
+			igt_warn("dmc fw is not loaded, no runtime pm\n");
+			ret = EXIT_FAILURE;
+			goto exit;
+		}
+	}
+
+	if (disable_display) {
+		disable_all_displays(&data);
+		if (!igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED)) {
+			__igt_debugfs_dump(data.drm_fd, "i915_runtime_pm_status", IGT_LOG_INFO);
+			ret = EXIT_FAILURE;
+			goto exit;
+		}
+
+		igt_info("Device runtime suspended, Useful for debugging.\n"
+			 "Hit CTRL-C to exit\n");
+		/* Don't return useful for debugging */
+		while (1)
+			sleep(600);
+	}
+
+	if (setup_d3cold)
+		setup_gfx_card_d3cold(&data);
+
+exit:
+	igt_restore_runtime_pm();
+
+	if (data.res)
+		igt_display_fini(&data.display);
+
+	close(data.debugfs_fd);
+	close(data.drm_fd);
+	igt_devices_free();
+
+	return ret;
+}
diff --git a/tools/meson.build b/tools/meson.build
index 771d0b9e3..24d0ea714 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -28,6 +28,7 @@ tools_progs = [
 	'intel_lid',
 	'intel_opregion_decode',
 	'intel_panel_fitter',
+	'intel_pm_rpm',
 	'intel_reg_checker',
 	'intel_residency',
 	'intel_stepping',
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (3 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 16:29   ` Rodrigo Vivi
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 6/9] i915_pm_rpm: Add D3Cold basic subtest Anshuman Gupta
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Few PCI devices under DGFX card tree don't have any kernel driver.
These devices will block D3cold state of gfx root port.
Adding support to configure autosuspend for all PCI devices
under the gfx root port. This will not save/restore pci devices
power attributes. This will be useful to tune D3Cold after boot.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 tools/intel_pm_rpm.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/tools/intel_pm_rpm.c b/tools/intel_pm_rpm.c
index bf8212b3c..92ce4f00b 100644
--- a/tools/intel_pm_rpm.c
+++ b/tools/intel_pm_rpm.c
@@ -45,10 +45,12 @@ typedef struct {
 const char *help_str =
 	"  --disable-display\t\tDisable all screen and try to go into runtime pm.\n"
 	"  --setup-d3cold\t\tPrepare dgfx gfx card to enter runtime D3Cold.\n"
+	"  --configure-autosuspend\t\tConfigure dgfx gfx card pci tree autosuspend.\n"
 	"  --help\t\tProvide help. Provide card name with IGT_DEVICE=drm:/dev/dri/card*.";
 static struct option long_options[] = {
 	{"disable-display", 0, 0, 'd'},
 	{"setup-d3cold", 0, 0, 's'},
+	{"configure-autosuspend", 0, 0, 'c'},
 	{"help", 0, 0, 'h'},
 	{ 0, 0, 0, 0 }
 };
@@ -72,6 +74,22 @@ static void disable_all_displays(data_t *data)
 	}
 }
 
+static void
+configure_gfx_card_autosuspend(data_t *data)
+{
+	struct pci_device *root;
+
+	root = igt_device_get_pci_root_port(data->drm_fd);
+
+	igt_info("Configuring pci devs autosuspend under Root port %04x:%02x:%02x.%01x\n",
+		  root->domain, root->bus, root->dev, root->func);
+
+	if  (igt_pm_enbale_pci_card_autosuspend(root) < 0) {
+		igt_warn("Unable to configure pci devs autosuspend under Root port"
+			 "%04x:%02x:%02x.%01x\n", root->domain, root->bus, root->dev, root->func);
+	}
+}
+
 static void setup_gfx_card_d3cold(data_t *data)
 {
 	struct pci_device *root;
@@ -102,7 +120,7 @@ static void setup_gfx_card_d3cold(data_t *data)
 
 int main(int argc, char *argv[])
 {
-	bool disable_display = false, setup_d3cold = false;
+	bool disable_display = false, setup_d3cold = false, configure_autosuspend = false;
 	struct igt_device_card card;
 	char *env_device = NULL;
 	int c, option_index = 0;
@@ -140,6 +158,9 @@ int main(int argc, char *argv[])
 		case 's':
 			setup_d3cold = true;
 			break;
+		case 'c':
+			configure_autosuspend = true;
+			break;
 		default:
 		case 'h':
 			usage(argv[0]);
@@ -192,6 +213,9 @@ int main(int argc, char *argv[])
 	if (setup_d3cold)
 		setup_gfx_card_d3cold(&data);
 
+	if (configure_autosuspend)
+		configure_gfx_card_autosuspend(&data);
+
 exit:
 	igt_restore_runtime_pm();
 
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 6/9] i915_pm_rpm: Add D3Cold basic subtest
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (4 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 7/9] i915_pm_rpm: Extend gem_exec_stress test with D3Cold Anshuman Gupta
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Add support for D3Cold basic subtest.
It setup and prepares the gfx PCI card for D3Cold
and checks the ACPI D3Cold state.

v2:
- Removed IS_DGFX() condition.
- Added igt_describe(). [Kamil]

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
 tests/i915/i915_pm_rpm.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/tests/i915/i915_pm_rpm.c b/tests/i915/i915_pm_rpm.c
index d2bce5826..31f9712a8 100644
--- a/tests/i915/i915_pm_rpm.c
+++ b/tests/i915/i915_pm_rpm.c
@@ -1534,6 +1534,28 @@ __noreturn static void stay_subtest(void)
 		sleep(600);
 }
 
+static void d3cold_basic_subtest(void)
+{
+	struct pci_device *root;
+	bool result;
+
+	root = igt_device_get_pci_root_port(drm_fd);
+	igt_require(igt_pm_acpi_d3cold_supported(root));
+	igt_pm_setup_pci_card_runtime_pm(root);
+	disable_all_screens_and_wait(&ms_data);
+
+	result = igt_wait(igt_pm_get_acpi_real_d_state(root) == IGT_ACPI_D3Cold, 10000, 500);
+
+	if (!result) {
+		igt_info("D3Cold not achieved for root port %04x:%02x:%02x.%01x\n",
+			 root->domain, root->bus, root->dev, root->func);
+		igt_pm_print_pci_card_runtime_status();
+	}
+
+	igt_assert(result);
+	igt_pm_restore_pci_card_runtime_pm();
+}
+
 static void system_suspend_subtest(int state, int debug)
 {
 	disable_all_screens_and_wait(&ms_data);
@@ -2065,6 +2087,10 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 		igt_subtest("stay")
 			stay_subtest();
 
+	igt_describe("Validate gfx root port d3cold state");
+	igt_subtest("d3cold-basic")
+		d3cold_basic_subtest();
+
 	/* Essential things */
 	igt_subtest("drm-resources-equal")
 		drm_resources_equal_subtest();
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 7/9] i915_pm_rpm: Extend gem_exec_stress test with D3Cold
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (5 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 6/9] i915_pm_rpm: Add D3Cold basic subtest Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 8/9] i915_pm_rpm: Extend gem_execbuf " Anshuman Gupta
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Added d3cold dynamic subtest to gem_exec_stress with device class
memory region. It test both D3Cold-{VRAM_SR, Off} by using
d3cold_sr_lmem_threshold i915_params debugfs.

v2:
- Two different subtest d3cold-off and d3cold-vrsr. [Rodrigo]
- commit header modification.
v3:
- Move {get, set}_d3cold_sr_lmem_threshold in igt_fixture. [Rodrigo]
- Skip the d3cold-vram-sr test when lmem_threshold is not available.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 tests/i915/i915_pm_rpm.c | 111 +++++++++++++++++++++++++++++++++------
 1 file changed, 96 insertions(+), 15 deletions(-)

diff --git a/tests/i915/i915_pm_rpm.c b/tests/i915/i915_pm_rpm.c
index 31f9712a8..b16d61643 100644
--- a/tests/i915/i915_pm_rpm.c
+++ b/tests/i915/i915_pm_rpm.c
@@ -85,6 +85,7 @@ enum plane_type {
 #define WAIT_PC8_RES	2
 #define WAIT_EXTRA	4
 #define USE_DPMS	8
+#define WAIT_D3COLD	16
 
 int drm_fd, msr_fd, pc8_status_fd;
 int debugfs;
@@ -215,6 +216,21 @@ static bool wait_for_suspended(void)
 	}
 }
 
+static bool wait_for_d3cold(struct pci_device *root)
+{
+	bool d3colded;
+
+	d3colded = igt_wait(igt_pm_get_acpi_real_d_state(root) == IGT_ACPI_D3Cold, 10000, 500);
+
+	if (!d3colded) {
+		igt_info("D3Cold not achieved for root port %04x:%02x:%02x.%01x\n",
+			 root->domain, root->bus, root->dev, root->func);
+		igt_pm_print_pci_card_runtime_status();
+	}
+
+	return d3colded;
+}
+
 static bool wait_for_active(void)
 {
 	if (has_pc8 && !has_runtime_pm)
@@ -744,6 +760,38 @@ static void test_i2c(struct mode_set_data *data)
 			"There is an EDID mismatch between i2c and DRM!\n");
 }
 
+static int get_d3cold_sr_lmem_threshold(int dir)
+{
+	int i915_params, lmem_threshold, ret;
+
+	i915_params = openat(dir, "i915_params", O_RDONLY);
+	igt_assert(i915_params > 0);
+	ret = igt_sysfs_scanf(i915_params, "d3cold_sr_lmem_threshold", "%d", &lmem_threshold);
+	if (ret < 0) {
+		close(i915_params);
+		return ret;
+	}
+
+	close(i915_params);
+	return lmem_threshold;
+}
+
+static int set_d3cold_sr_lmem_threshold(int dir, int val)
+{
+	int i915_params, ret;
+
+	i915_params = openat(dir, "i915_params", O_RDONLY);
+	igt_assert(i915_params > 0);
+	ret = igt_sysfs_printf(i915_params, "d3cold_sr_lmem_threshold", "%d", val);
+	if (ret < 0) {
+		close(i915_params);
+		return ret;
+	}
+
+	close(i915_params);
+	return ret;
+}
+
 static void setup_pc8(void)
 {
 	has_pc8 = false;
@@ -1069,6 +1117,17 @@ static void debugfs_forcewake_user_subtest(void)
 	igt_assert(wait_for_suspended());
 }
 
+static struct pci_device *setup_d3cold_and_get_root_port(void)
+{
+	struct pci_device *root;
+
+	root = igt_device_get_pci_root_port(drm_fd);
+	igt_require(igt_pm_acpi_d3cold_supported(root));
+	igt_pm_setup_pci_card_runtime_pm(root);
+
+	return root;
+}
+
 static void gem_mmap_args(const struct mmap_offset *t,
 			  struct drm_i915_gem_memory_class_instance *mem_regions)
 {
@@ -1392,6 +1451,7 @@ gem_execbuf_stress_subtest(int rounds, int wait_flags,
 	int i;
 	int batch_size = 4 * sizeof(uint32_t);
 	uint32_t batch_buf[batch_size];
+	struct pci_device *root;
 	uint32_t handle;
 	struct drm_i915_gem_execbuffer2 execbuf = {};
 	struct drm_i915_gem_exec_object2 objs[1] = {{}};
@@ -1408,6 +1468,9 @@ gem_execbuf_stress_subtest(int rounds, int wait_flags,
 	batch_buf[i++] = MI_NOOP;
 	igt_assert(i * sizeof(uint32_t) == batch_size);
 
+	if (wait_flags & WAIT_D3COLD)
+		root = setup_d3cold_and_get_root_port();
+
 	disable_all_screens_and_wait(&ms_data);
 
 	/* PC8 test is only applicable to igfx  */
@@ -1433,6 +1496,9 @@ gem_execbuf_stress_subtest(int rounds, int wait_flags,
 			/* clean up idle work */
 			igt_drop_caches_set(drm_fd, DROP_IDLE);
 			igt_assert(wait_for_suspended());
+			if (wait_flags & WAIT_D3COLD)
+				igt_assert(wait_for_d3cold(root));
+
 		}
 		if (wait_flags & WAIT_PC8_RES)
 			igt_assert(pc8_plus_residency_changed(30));
@@ -1440,6 +1506,9 @@ gem_execbuf_stress_subtest(int rounds, int wait_flags,
 			sleep(5);
 	}
 
+	if (wait_flags & WAIT_D3COLD)
+		igt_pm_restore_pci_card_runtime_pm();
+
 	gem_close(drm_fd, handle);
 }
 
@@ -1537,22 +1606,10 @@ __noreturn static void stay_subtest(void)
 static void d3cold_basic_subtest(void)
 {
 	struct pci_device *root;
-	bool result;
 
-	root = igt_device_get_pci_root_port(drm_fd);
-	igt_require(igt_pm_acpi_d3cold_supported(root));
-	igt_pm_setup_pci_card_runtime_pm(root);
+	root = setup_d3cold_and_get_root_port();
 	disable_all_screens_and_wait(&ms_data);
-
-	result = igt_wait(igt_pm_get_acpi_real_d_state(root) == IGT_ACPI_D3Cold, 10000, 500);
-
-	if (!result) {
-		igt_info("D3Cold not achieved for root port %04x:%02x:%02x.%01x\n",
-			 root->domain, root->bus, root->dev, root->func);
-		igt_pm_print_pci_card_runtime_status();
-	}
-
-	igt_assert(result);
+	igt_assert(wait_for_d3cold(root));
 	igt_pm_restore_pci_card_runtime_pm();
 }
 
@@ -2071,6 +2128,8 @@ static struct option long_options[] = {
 
 igt_main_args("", long_options, help_str, opt_handler, NULL)
 {
+	int lmem_threshold;
+
 	igt_subtest("basic-rte") {
 		igt_assert(setup_environment(false));
 		basic_subtest();
@@ -2081,6 +2140,7 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 	 * not properly configured. */
 	igt_fixture {
 		igt_require(setup_environment(false));
+		lmem_threshold = get_d3cold_sr_lmem_threshold(debugfs);
 	}
 
 	if (stay)
@@ -2211,6 +2271,24 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 				gem_execbuf_stress_subtest(rounds, WAIT_STATUS, &r->ci);
 			igt_dynamic_f("%s-%s", "extra-wait", r->name)
 				gem_execbuf_stress_subtest(rounds, WAIT_STATUS | WAIT_EXTRA, &r->ci);
+
+			if (r->ci.memory_class == I915_MEMORY_CLASS_SYSTEM)
+				continue;
+
+			igt_dynamic_f("%s-%s", "d3cold-off", r->name) {
+				if (lmem_threshold >= 0)
+					set_d3cold_sr_lmem_threshold(debugfs, 300);
+
+				gem_execbuf_stress_subtest(rounds, WAIT_STATUS | WAIT_D3COLD,
+							   &r->ci);
+			}
+
+			igt_dynamic_f("%s-%s", "d3cold-vrsr", r->name) {
+				igt_require(lmem_threshold >= 0);
+				set_d3cold_sr_lmem_threshold(debugfs, 0);
+				gem_execbuf_stress_subtest(rounds, WAIT_STATUS | WAIT_D3COLD,
+							   &r->ci);
+			}
 		}
 	}
 
@@ -2227,8 +2305,11 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 		pm_test_caching();
 	}
 
-	igt_fixture
+	igt_fixture {
+		if (lmem_threshold >= 0)
+			set_d3cold_sr_lmem_threshold(debugfs, lmem_threshold);
 		teardown_environment(false);
+	}
 
 	igt_subtest("module-reload") {
 		igt_debug("Reload w/o display\n");
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 8/9] i915_pm_rpm: Extend gem_execbuf test with D3Cold
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (6 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 7/9] i915_pm_rpm: Extend gem_exec_stress test with D3Cold Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 9/9] i915_pm_rpm: Extend gem-mmap-type " Anshuman Gupta
  2022-05-05 12:15 ` [igt-dev] ✗ Fi.CI.BAT: failure for D3Cold Tool & IGT (rev4) Patchwork
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Added d3cold dynamic subtest to gem_execbuf with device class
memory region. It test both D3Cold-{VRAM_SR, Off} by using
d3cold_sr_lmem_threshold i915_params debugfs.

v2:
- Two different subtest d3cold-off and d3cold-vrsr. [Rodrigo]
v3:
- Skip the d3cold-vram-sr test when lmem_threshold is not available.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 tests/i915/i915_pm_rpm.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/tests/i915/i915_pm_rpm.c b/tests/i915/i915_pm_rpm.c
index b16d61643..a062fde88 100644
--- a/tests/i915/i915_pm_rpm.c
+++ b/tests/i915/i915_pm_rpm.c
@@ -1350,10 +1350,11 @@ static void submit_blt_cmd(uint32_t dst_handle, int dst_size,
 }
 
 /* Make sure we can submit a batch buffer and verify its result. */
-static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_regions)
+static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_regions, bool d3cold)
 {
 	int x, y;
 	uint32_t handle;
+	struct pci_device *root;
 	int bpp = 4;
 	int pitch = 128 * bpp;
 	int dst_size = 128 * 128 * bpp; /* 128x128 square */
@@ -1375,6 +1376,9 @@ static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_r
 	memset(cpu_buf, 0, dst_size);
 	gem_write(drm_fd, handle, 0, cpu_buf, dst_size);
 
+	if (d3cold)
+		root = setup_d3cold_and_get_root_port();
+
 	/* Now suspend and try it. */
 	disable_all_screens_and_wait(&ms_data);
 
@@ -1383,8 +1387,15 @@ static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_r
 		       &presumed_offset);
 	igt_assert(wait_for_suspended());
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	gem_read(drm_fd, handle, 0, cpu_buf, dst_size);
 	igt_assert(wait_for_suspended());
+
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	for (y = 0; y < 128; y++) {
 		for (x = 0; x < 128; x++) {
 			uint32_t px = cpu_buf[y * 128 + x];
@@ -1423,6 +1434,9 @@ static void gem_execbuf_subtest(struct drm_i915_gem_memory_class_instance *mem_r
 
 	disable_all_screens_and_wait(&ms_data);
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	memset(cpu_buf, 0, dst_size);
 	gem_read(drm_fd, handle, 0, cpu_buf, dst_size);
 	for (y = 0; y < 128; y++) {
@@ -2182,7 +2196,23 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 	igt_subtest_with_dynamic("gem-execbuf") {
 		for_each_memory_region(r, drm_fd) {
 			igt_dynamic_f("%s", r->name)
-				gem_execbuf_subtest(&r->ci);
+				gem_execbuf_subtest(&r->ci, false);
+
+			if (r->ci.memory_class == I915_MEMORY_CLASS_SYSTEM)
+				continue;
+
+			igt_dynamic_f("%s-%s", "d3cold-off", r->name) {
+				if (lmem_threshold >= 0)
+					set_d3cold_sr_lmem_threshold(debugfs, 300);
+
+				gem_execbuf_subtest(&r->ci, true);
+			}
+
+			igt_dynamic_f("%s-%s", "d3cold-vrsr", r->name) {
+				igt_require(lmem_threshold >= 0);
+				set_d3cold_sr_lmem_threshold(debugfs, 0);
+				gem_execbuf_subtest(&r->ci, true);
+			}
 		}
 	}
 	igt_subtest("gem-idle")
-- 
2.26.2

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

* [igt-dev] [PATCH i-g-t v4 9/9] i915_pm_rpm: Extend gem-mmap-type test with D3Cold
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (7 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 8/9] i915_pm_rpm: Extend gem_execbuf " Anshuman Gupta
@ 2022-05-05 11:03 ` Anshuman Gupta
  2022-05-05 12:15 ` [igt-dev] ✗ Fi.CI.BAT: failure for D3Cold Tool & IGT (rev4) Patchwork
  9 siblings, 0 replies; 14+ messages in thread
From: Anshuman Gupta @ 2022-05-05 11:03 UTC (permalink / raw)
  To: igt-dev; +Cc: petri.latvala, badal.nilawar, rodrigo.vivi

Added d3cold dynamic subtest to gem-mmap-type with device class
memory region. It test both D3Cold-{VRAM_SR, Off} by using
d3cold_sr_lmem_threshold i915_params debugfs.

v2:
- Two different subtest d3cold-off and d3cold-vrsr. [Rodrigo]
v3:
- Skip the d3cold-vram-sr test when lmem_threshold is not available.

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
---
 tests/i915/i915_pm_rpm.c | 41 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/tests/i915/i915_pm_rpm.c b/tests/i915/i915_pm_rpm.c
index a062fde88..3a4e2901b 100644
--- a/tests/i915/i915_pm_rpm.c
+++ b/tests/i915/i915_pm_rpm.c
@@ -1129,11 +1129,12 @@ static struct pci_device *setup_d3cold_and_get_root_port(void)
 }
 
 static void gem_mmap_args(const struct mmap_offset *t,
-			  struct drm_i915_gem_memory_class_instance *mem_regions)
+			  struct drm_i915_gem_memory_class_instance *mem_regions, bool d3cold)
 {
 	int i;
 	uint32_t handle;
 	int buf_size = 8192;
+	struct pci_device *root;
 	uint8_t *gem_buf;
 
 	/* Create, map and set data while the device is active. */
@@ -1151,17 +1152,29 @@ static void gem_mmap_args(const struct mmap_offset *t,
 	for (i = 0; i < buf_size; i++)
 		igt_assert(gem_buf[i] == (i & 0xFF));
 
+	if (d3cold)
+		root = setup_d3cold_and_get_root_port();
+
 	/* Now suspend, read and modify. */
 	disable_all_screens_and_wait(&ms_data);
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	for (i = 0; i < buf_size; i++)
 		igt_assert(gem_buf[i] == (i & 0xFF));
 	igt_assert(wait_for_suspended());
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	for (i = 0; i < buf_size; i++)
 		gem_buf[i] = (~i & 0xFF);
 	igt_assert(wait_for_suspended());
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	/* Now resume and see if it's still there. */
 	enable_one_screen_and_wait(&ms_data);
 	for (i = 0; i < buf_size; i++)
@@ -1173,12 +1186,18 @@ static void gem_mmap_args(const struct mmap_offset *t,
 	 * suspended. */
 	disable_all_screens_and_wait(&ms_data);
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	gem_buf = __gem_mmap_offset(drm_fd, handle, 0, buf_size,
 				    PROT_READ | PROT_WRITE, t->type);
 	igt_require(gem_buf);
 
 	igt_assert(wait_for_suspended());
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	for (i = 0; i < buf_size; i++)
 		gem_buf[i] = i & 0xFF;
 
@@ -1187,6 +1206,9 @@ static void gem_mmap_args(const struct mmap_offset *t,
 
 	igt_assert(wait_for_suspended());
 
+	if (d3cold)
+		igt_assert(wait_for_d3cold(root));
+
 	/* Resume and check if it's still there. */
 	enable_one_screen_and_wait(&ms_data);
 	for (i = 0; i < buf_size; i++)
@@ -2186,7 +2208,22 @@ igt_main_args("", long_options, help_str, opt_handler, NULL)
 		for_each_mmap_offset_type(drm_fd, t) {
 			for_each_memory_region(r, drm_fd) {
 				igt_dynamic_f("%s-%s", t->name, r->name)
-				gem_mmap_args(t, &r->ci);
+				gem_mmap_args(t, &r->ci, false);
+
+				if (r->ci.memory_class == I915_MEMORY_CLASS_SYSTEM)
+					continue;
+
+				igt_dynamic_f("%s-%s-%s", t->name, "d3cold-off", r->name) {
+					if (lmem_threshold >= 0)
+						set_d3cold_sr_lmem_threshold(debugfs, 300);
+					gem_mmap_args(t, &r->ci, true);
+				}
+
+				igt_dynamic_f("%s-%s-%s", t->name, "d3cold-vrsr", r->name) {
+					igt_require(lmem_threshold >= 0);
+					set_d3cold_sr_lmem_threshold(debugfs, 0);
+					gem_mmap_args(t, &r->ci, true);
+				}
 			}
 		}
 	}
-- 
2.26.2

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

* [igt-dev] ✗ Fi.CI.BAT: failure for D3Cold Tool & IGT (rev4)
  2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
                   ` (8 preceding siblings ...)
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 9/9] i915_pm_rpm: Extend gem-mmap-type " Anshuman Gupta
@ 2022-05-05 12:15 ` Patchwork
  9 siblings, 0 replies; 14+ messages in thread
From: Patchwork @ 2022-05-05 12:15 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 11890 bytes --]

== Series Details ==

Series: D3Cold Tool & IGT (rev4)
URL   : https://patchwork.freedesktop.org/series/102780/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11610 -> IGTPW_7043
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_7043 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_7043, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/index.html

Participating hosts (43 -> 41)
------------------------------

  Additional (3): bat-adlm-1 bat-dg2-9 bat-dg1-5 
  Missing    (5): bat-dg2-8 fi-bsw-cyan fi-icl-u2 bat-rpls-1 bat-rpls-2 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_7043:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live@gt_lrc:
    - bat-adlp-4:         NOTRUN -> [DMESG-FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-adlp-4/igt@i915_selftest@live@gt_lrc.html

  
Known issues
------------

  Here are the changes found in IGTPW_7043 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@fbdev@write:
    - bat-dg1-5:          NOTRUN -> [SKIP][2] ([i915#2582]) +4 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@fbdev@write.html

  * igt@gem_mmap@basic:
    - bat-dg1-5:          NOTRUN -> [SKIP][3] ([i915#4083])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@gem_mmap@basic.html

  * igt@gem_tiled_fence_blits@basic:
    - bat-dg1-5:          NOTRUN -> [SKIP][4] ([i915#4077]) +2 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@gem_tiled_fence_blits@basic.html

  * igt@gem_tiled_pread_basic:
    - bat-dg1-5:          NOTRUN -> [SKIP][5] ([i915#4079]) +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@gem_tiled_pread_basic.html

  * igt@i915_pm_backlight@basic-brightness:
    - bat-dg1-5:          NOTRUN -> [SKIP][6] ([i915#1155])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@i915_pm_backlight@basic-brightness.html

  * igt@i915_selftest@live@gt_engines:
    - bat-dg1-5:          NOTRUN -> [INCOMPLETE][7] ([i915#4418])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@i915_selftest@live@gt_engines.html

  * igt@i915_selftest@live@hangcheck:
    - fi-bdw-5557u:       NOTRUN -> [INCOMPLETE][8] ([i915#3921])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/fi-bdw-5557u/igt@i915_selftest@live@hangcheck.html

  * igt@kms_addfb_basic@basic-y-tiled-legacy:
    - bat-dg1-5:          NOTRUN -> [SKIP][9] ([i915#4215])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_addfb_basic@basic-y-tiled-legacy.html

  * igt@kms_addfb_basic@tile-pitch-mismatch:
    - bat-dg1-5:          NOTRUN -> [SKIP][10] ([i915#4212]) +7 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_addfb_basic@tile-pitch-mismatch.html

  * igt@kms_busy@basic:
    - bat-dg1-5:          NOTRUN -> [SKIP][11] ([i915#4303])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_busy@basic.html

  * igt@kms_busy@basic@flip:
    - bat-adlp-4:         [PASS][12] -> [DMESG-WARN][13] ([i915#3576])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/bat-adlp-4/igt@kms_busy@basic@flip.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-adlp-4/igt@kms_busy@basic@flip.html

  * igt@kms_chamelium@common-hpd-after-suspend:
    - fi-ivb-3770:        NOTRUN -> [SKIP][14] ([fdo#109271] / [fdo#111827])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/fi-ivb-3770/igt@kms_chamelium@common-hpd-after-suspend.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - bat-dg1-5:          NOTRUN -> [SKIP][15] ([fdo#111827]) +7 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_chamelium@hdmi-hpd-fast.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - bat-dg1-5:          NOTRUN -> [SKIP][16] ([i915#4103] / [i915#4213]) +1 similar issue
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-dpms:
    - bat-dg1-5:          NOTRUN -> [SKIP][17] ([i915#4078]) +23 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_flip@basic-flip-vs-dpms.html

  * igt@kms_force_connector_basic@force-load-detect:
    - bat-dg1-5:          NOTRUN -> [SKIP][18] ([fdo#109285])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_force_connector_basic@force-load-detect.html

  * igt@kms_psr@primary_page_flip:
    - bat-dg1-5:          NOTRUN -> [SKIP][19] ([i915#1072] / [i915#4078]) +3 similar issues
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_psr@primary_page_flip.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - bat-dg1-5:          NOTRUN -> [SKIP][20] ([i915#3555])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@kms_setmode@basic-clone-single-crtc.html

  * igt@prime_vgem@basic-fence-mmap:
    - bat-dg1-5:          NOTRUN -> [SKIP][21] ([i915#3708] / [i915#4077]) +1 similar issue
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@prime_vgem@basic-fence-mmap.html

  * igt@prime_vgem@basic-userptr:
    - bat-dg1-5:          NOTRUN -> [SKIP][22] ([i915#3708] / [i915#4873])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@prime_vgem@basic-userptr.html

  * igt@prime_vgem@basic-write:
    - bat-dg1-5:          NOTRUN -> [SKIP][23] ([i915#3708]) +3 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@prime_vgem@basic-write.html

  * igt@runner@aborted:
    - bat-dg1-5:          NOTRUN -> [FAIL][24] ([i915#4312] / [i915#5257])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-dg1-5/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@gem_exec_suspend@basic-s0@smem:
    - {fi-ehl-2}:         [DMESG-WARN][25] ([i915#5122]) -> [PASS][26]
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/fi-ehl-2/igt@gem_exec_suspend@basic-s0@smem.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/fi-ehl-2/igt@gem_exec_suspend@basic-s0@smem.html

  * igt@i915_pm_rpm@module-reload:
    - bat-adlp-4:         [INCOMPLETE][27] -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/bat-adlp-4/igt@i915_pm_rpm@module-reload.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-adlp-4/igt@i915_pm_rpm@module-reload.html

  * igt@i915_selftest@live@gem_migrate:
    - fi-bdw-5557u:       [INCOMPLETE][29] ([i915#5716]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/fi-bdw-5557u/igt@i915_selftest@live@gem_migrate.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/fi-bdw-5557u/igt@i915_selftest@live@gem_migrate.html

  * igt@i915_selftest@live@hangcheck:
    - fi-ivb-3770:        [INCOMPLETE][31] ([i915#3303] / [i915#5370]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/fi-ivb-3770/igt@i915_selftest@live@hangcheck.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/fi-ivb-3770/igt@i915_selftest@live@hangcheck.html

  * igt@kms_flip@basic-flip-vs-modeset@b-edp1:
    - {bat-adlp-6}:       [DMESG-WARN][33] ([i915#3576]) -> [PASS][34] +1 similar issue
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/bat-adlp-6/igt@kms_flip@basic-flip-vs-modeset@b-edp1.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-adlp-6/igt@kms_flip@basic-flip-vs-modeset@b-edp1.html
    - bat-adlp-4:         [DMESG-WARN][35] ([i915#3576]) -> [PASS][36]
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11610/bat-adlp-4/igt@kms_flip@basic-flip-vs-modeset@b-edp1.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/bat-adlp-4/igt@kms_flip@basic-flip-vs-modeset@b-edp1.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109284]: https://bugs.freedesktop.org/show_bug.cgi?id=109284
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1155]: https://gitlab.freedesktop.org/drm/intel/issues/1155
  [i915#1759]: https://gitlab.freedesktop.org/drm/intel/issues/1759
  [i915#2373]: https://gitlab.freedesktop.org/drm/intel/issues/2373
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3303]: https://gitlab.freedesktop.org/drm/intel/issues/3303
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4078]: https://gitlab.freedesktop.org/drm/intel/issues/4078
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/intel/issues/4215
  [i915#4303]: https://gitlab.freedesktop.org/drm/intel/issues/4303
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4418]: https://gitlab.freedesktop.org/drm/intel/issues/4418
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4873]: https://gitlab.freedesktop.org/drm/intel/issues/4873
  [i915#5122]: https://gitlab.freedesktop.org/drm/intel/issues/5122
  [i915#5171]: https://gitlab.freedesktop.org/drm/intel/issues/5171
  [i915#5174]: https://gitlab.freedesktop.org/drm/intel/issues/5174
  [i915#5181]: https://gitlab.freedesktop.org/drm/intel/issues/5181
  [i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5370]: https://gitlab.freedesktop.org/drm/intel/issues/5370
  [i915#5606]: https://gitlab.freedesktop.org/drm/intel/issues/5606
  [i915#5703]: https://gitlab.freedesktop.org/drm/intel/issues/5703
  [i915#5716]: https://gitlab.freedesktop.org/drm/intel/issues/5716
  [i915#5775]: https://gitlab.freedesktop.org/drm/intel/issues/5775
  [i915#5801]: https://gitlab.freedesktop.org/drm/intel/issues/5801


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_6465 -> IGTPW_7043

  CI-20190529: 20190529
  CI_DRM_11610: c0acb508f6f2581929400eeef6c0a94e925ae264 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_7043: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/index.html
  IGT_6465: f6bb4399881a806fbff75ce3df89b60286d55917 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git


Testlist changes
----------------

+igt@i915_pm_rpm@d3cold-basic

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_7043/index.html

[-- Attachment #2: Type: text/html, Size: 12751 bytes --]

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

* Re: [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure Anshuman Gupta
@ 2022-05-05 16:16   ` Rodrigo Vivi
  0 siblings, 0 replies; 14+ messages in thread
From: Rodrigo Vivi @ 2022-05-05 16:16 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: petri.latvala, igt-dev, badal.nilawar

On Thu, May 05, 2022 at 04:33:48PM +0530, Anshuman Gupta wrote:
> Enable gfx card pci devices runtime pm for all pci devices
> and bridge under the topology of Gfx Card root port.
> 
> Added a library function to get the PCI root port ACPI
> D state and to print the pci card devices runtime pm
> status.
> 
> v2:
> - Save pci dev power attr to dynamically allocated array. [Rodrigo]
> - Set autosuspend delay to 0 on supported devices. [Rodrigo]
> - %s/else if/else in  igt_pm_get_acpi_real_d_state. [Kamil]
> v3:
> - Add comment for MAX_PCI_DEVICES. [Badal]
> - Use static global arrary __pci_dev_pwrattr[]. [Rodrigo]
> - Use pci_slot_match iter. [Badal]
> - Destroy the iter. [Badal]
> v4:
> - Added igt_pm_enbale_pci_card_autosuspend() to avoid any
>   control attr save/resore by exit handler. [Rodrigo]
> 
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  lib/igt_pm.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/igt_pm.h |  24 ++++
>  2 files changed, 365 insertions(+)
> 
> diff --git a/lib/igt_pm.c b/lib/igt_pm.c
> index b409ec463..8e5aa9208 100644
> --- a/lib/igt_pm.c
> +++ b/lib/igt_pm.c
> @@ -28,6 +28,7 @@
>  #include <fcntl.h>
>  #include <stdio.h>
>  #include <limits.h>
> +#include <pciaccess.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
> @@ -75,6 +76,8 @@ enum {
>  #define MIN_POWER_STR		"min_power\n"
>  /* Remember to fix this if adding longer strings */
>  #define MAX_POLICY_STRLEN	strlen(MAX_PERFORMANCE_STR)
> +/* Root Port bus can have max 32 dev and each dev can have max 8 func */
> +#define MAX_PCI_DEVICES		256
>  int8_t *__sata_pm_policies;
>  int __scsi_host_cnt;
>  
> @@ -856,3 +859,341 @@ bool i915_output_is_lpsp_capable(int drm_fd, igt_output_t *output)
>  
>  	return strstr(buf, "LPSP: capable");
>  }
> +
> +/**
> + * igt_pm_acpi_d3cold_supported:
> + * @pci_dev: root port pci_dev.
> + * Check ACPI D3Cold support.
> + *
> + * Returns:
> + * True if ACPI D3Cold supported otherwise false.
> + */
> +bool igt_pm_acpi_d3cold_supported(struct pci_device *pci_dev)
> +{
> +	char name[PATH_MAX];
> +	int dir, fd;
> +
> +	snprintf(name, PATH_MAX,
> +		 "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/firmware_node",
> +		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
> +
> +	dir = open(name, O_RDONLY);
> +	igt_require(dir > 0);
> +
> +	/* BIOS need to enable ACPI D3Cold Support.*/
> +	fd = openat(dir, "real_power_state", O_RDONLY);
> +	if (fd < 0 && errno == ENOENT)
> +		return false;
> +
> +	igt_require(fd > 0);
> +
> +	return true;
> +}
> +
> +/**
> + * igt_pm_get_acpi_real_d_state:
> + * @pci_dev: root port pci_dev.
> + * Get ACPI D state for a given root port.
> + *
> + * Returns:
> + * igt_acpi_d_state state.
> + */
> +enum igt_acpi_d_state
> +igt_pm_get_acpi_real_d_state(struct pci_device *pci_dev)
> +{
> +	char name[PATH_MAX];
> +	char acpi_d_state[64];
> +	int fd, n_read;
> +
> +	snprintf(name, PATH_MAX,
> +		 "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/firmware_node/real_power_state",
> +		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
> +
> +	fd = open(name, O_RDONLY);
> +	if (fd < 0)
> +		return IGT_ACPI_UNKNOWN_STATE;
> +
> +	n_read = read(fd, acpi_d_state, sizeof(acpi_d_state) - 1);
> +	igt_assert(n_read >= 0);
> +	acpi_d_state[n_read] = '\0';
> +	close(fd);
> +
> +	if (strncmp(acpi_d_state, "D0\n", n_read) == 0)
> +		return IGT_ACPI_D0;
> +	if  (strncmp(acpi_d_state, "D1\n", n_read) == 0)
> +		return IGT_ACPI_D1;
> +	if  (strncmp(acpi_d_state, "D2\n", n_read) == 0)
> +		return IGT_ACPI_D2;
> +	if  (strncmp(acpi_d_state, "D3hot\n", n_read) == 0)
> +		return IGT_ACPI_D3Hot;
> +	if  (strncmp(acpi_d_state, "D3cold\n", n_read) == 0)
> +		return IGT_ACPI_D3Cold;
> +
> +	return IGT_ACPI_UNKNOWN_STATE;
> +}
> +
> +static struct igt_pm_pci_dev_pwrattr  __pci_dev_pwrattr[MAX_PCI_DEVICES];
> +
> +static void __igt_pm_pci_card_exit_handler(int sig)
> +{
> +	igt_pm_restore_pci_card_runtime_pm();
> +}
> +
> +static int igt_pm_get_power_attr_fd(struct pci_device *pci_dev, const char *attr)
> +{
> +	char name[PATH_MAX];
> +	int fd;
> +
> +	snprintf(name, PATH_MAX, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/power/%s",
> +		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, attr);
> +
> +	fd = open(name, O_RDWR);
> +	igt_assert_f(fd >= 0, "Can't open %s\n", attr);
> +
> +	return fd;
> +}
> +
> +static bool igt_pm_save_power_attr(int fd, char *attr, int len, bool autosuspend)
> +{
> +	int size;
> +
> +	size = read(fd, attr, len - 1);
> +
> +	if (autosuspend) {
> +		if (size < 0)
> +			return false;
> +	} else {
> +		igt_assert(size > 0);
> +	}
> +
> +	attr[size] = '\0';
> +	strchomp(attr);
> +
> +	return true;
> +}
> +
> +static void igt_pm_setup_power_attr(int fd, const char *val)
> +{
> +	int size, len;
> +	char buf[6];
> +
> +	len = strlen(val);
> +
> +	size = write(fd, val, len);
> +	igt_assert_eq(size, len);
> +	lseek(fd, 0, SEEK_SET);
> +	size = read(fd, buf, ARRAY_SIZE(buf));
> +	igt_assert_eq(size, len);
> +	igt_assert(strncmp(buf, val, len) == 0);
> +}
> +
> +static void
> +__igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev, int index)
> +{
> +	int control_fd, delay_fd, control_size, delay_size;
> +	char *control, *delay;
> +
> +	igt_assert(index <  MAX_PCI_DEVICES);
> +
> +	control = __pci_dev_pwrattr[index].control;
> +	control_size =  sizeof(__pci_dev_pwrattr[index].control);
> +	delay = __pci_dev_pwrattr[index].autosuspend_delay;
> +	delay_size =  sizeof(__pci_dev_pwrattr[index].autosuspend_delay);
> +	__pci_dev_pwrattr[index].pci_dev = pci_dev;
> +	__pci_dev_pwrattr[index].autosuspend_supported = true;
> +
> +	delay_fd = igt_pm_get_power_attr_fd(pci_dev, "autosuspend_delay_ms");
> +	control_fd = igt_pm_get_power_attr_fd(pci_dev, "control");
> +
> +	if (!igt_pm_save_power_attr(delay_fd, delay, delay_size, true)) {
> +		__pci_dev_pwrattr[index].autosuspend_supported = false;
> +		igt_debug("PCI '%04x:%02x:%02x.%01x' doesn't support auto_suspend\n",
> +			  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
> +	}
> +
> +	igt_pm_save_power_attr(control_fd, control, control_size, false);
> +	igt_debug("PCI '%04x:%02x:%02x.%01x' Saved 'control, autosuspend_delay_ms' as '%s, %s'\n",
> +		  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, control,
> +		  __pci_dev_pwrattr[index].autosuspend_supported ? delay : "NA");
> +
> +	if (!index)
> +		igt_install_exit_handler(__igt_pm_pci_card_exit_handler);
> +
> +	if (__pci_dev_pwrattr[index].autosuspend_supported)
> +		igt_pm_setup_power_attr(delay_fd, "0\n");
> +
> +	igt_pm_setup_power_attr(control_fd, "auto\n");
> +
> +	close(delay_fd);
> +	close(control_fd);
> +}
> +
> +static struct
> +pci_device_iterator *igt_pm_get_pci_dev_itr(struct pci_device *pci_dev)
> +{
> +	struct pci_device_iterator *iter;
> +	struct pci_slot_match match;
> +	int ret;
> +
> +	ret = pci_system_init();
> +	igt_assert(!ret);
> +
> +	match.domain = pci_dev->domain;
> +	match.bus = PCI_MATCH_ANY;
> +	match.dev = PCI_MATCH_ANY;
> +	match.func = PCI_MATCH_ANY;
> +	iter = pci_slot_match_iterator_create(&match);
> +
> +	return iter;
> +}
> +
> +/**
> + * igt_pm_enbale_pci_card_autosuspend:
> + * @pci_dev: root port pci_dev.
> + * Setup runtime PM for all PCI endpoints devices for a given root port by
> + * setting power/control attr to "auto".
> + *
> + * Returns:
> + * Zero if success else returns error.
> + */
> +int igt_pm_enbale_pci_card_autosuspend(struct pci_device *pci_dev)
> +{
> +	int primary, secondary, subordinate, ret, control_fd;
> +	struct pci_device_iterator *iter;
> +	struct pci_device *dev;
> +
> +	ret = pci_device_get_bridge_buses(pci_dev, &primary, &secondary, &subordinate);
> +	if (ret)
> +		return ret;
> +
> +	iter = igt_pm_get_pci_dev_itr(pci_dev);
> +	if (!iter)
> +		return -ENODEV;
> +
> +	control_fd = igt_pm_get_power_attr_fd(pci_dev, "control");
> +	igt_pm_setup_power_attr(control_fd, "auto\n");
> +	while ((dev = pci_device_next(iter)) != NULL) {
> +		if (dev->bus >= secondary && dev->bus <= subordinate) {
> +			control_fd = igt_pm_get_power_attr_fd(dev, "control");
> +			igt_pm_setup_power_attr(control_fd, "auto\n");
> +		}
> +	}

could we do in a way that we avoid duplication?
it looks like the other setup function is handling more cases with debug msgs.

> +
> +	pci_iterator_destroy(iter);
> +	pci_system_cleanup();
> +
> +	return 0;
> +}
> +
> +/**
> + * igt_pm_setup_pci_card_runtime_pm:
> + * @pci_dev: root port pci_dev.
> + * Setup runtime PM for all PCI endpoints devices for a given root port by
> + * enabling runtime suspend and setting autosuspend_delay_ms to zero.
> + * It also saves power control attribute for all PCI endpoints
> + * devices under given root port.
> + */
> +void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev)
> +{
> +	int primary, secondary, subordinate, ret;
> +	struct pci_device_iterator *iter;
> +	struct pci_device *dev;
> +	int i = 0;
> +
> +	memset(__pci_dev_pwrattr, 0, sizeof(__pci_dev_pwrattr));
> +	ret = pci_device_get_bridge_buses(pci_dev, &primary, &secondary, &subordinate);
> +	igt_assert(!ret);
> +
> +	/* Setup runtime pm for PCI root port */
> +	__igt_pm_setup_pci_card_runtime_pm(pci_dev, i++);
> +
> +	iter = igt_pm_get_pci_dev_itr(pci_dev);
> +	igt_assert(iter);
> +	while ((dev = pci_device_next(iter)) != NULL) {
> +		if (dev->bus >= secondary && dev->bus <= subordinate)
> +			__igt_pm_setup_pci_card_runtime_pm(dev, i++);
> +	}
> +
> +	pci_iterator_destroy(iter);
> +}
> +
> +static void
> +igt_pm_restore_power_attr(struct pci_device *pci_dev, const char *attr, char *val, int len)
> +{
> +	int fd;
> +
> +	igt_debug("PCI '%04x:%02x:%02x.%01x' Restoring %s attr to '%s'\n",
> +		  pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, attr, val);
> +
> +	fd = igt_pm_get_power_attr_fd(pci_dev, attr);
> +	igt_assert(write(fd, val, len) == len);
> +
> +	close(fd);
> +}
> +
> +/**
> + * igt_pm_restore_pci_card_runtime_pm:
> + * Restore control and autosuspend_delay_ms power attribute for all
> + * PCI endpoints devices under gfx root port, which were saved earlier
> + * by igt_pm_setup_pci_card_runtime_pm().
> + */
> +void igt_pm_restore_pci_card_runtime_pm(void)
> +{
> +	int i = 0;
> +
> +	for (i = 0; i < MAX_PCI_DEVICES; i++) {
> +		if (!__pci_dev_pwrattr[i].pci_dev)
> +			break;
> +
> +		igt_pm_restore_power_attr(__pci_dev_pwrattr[i].pci_dev, "control",
> +					  __pci_dev_pwrattr[i].control,
> +					  sizeof(__pci_dev_pwrattr[i].control));
> +
> +		if (!__pci_dev_pwrattr[i].autosuspend_supported)
> +			continue;
> +
> +		igt_pm_restore_power_attr(__pci_dev_pwrattr[i].pci_dev, "autosuspend_delay_ms",
> +					  __pci_dev_pwrattr[i].autosuspend_delay,
> +					  sizeof(__pci_dev_pwrattr[i].autosuspend_delay));
> +	}
> +
> +	memset(__pci_dev_pwrattr, 0, sizeof(__pci_dev_pwrattr));
> +	pci_system_cleanup();
> +}
> +
> +static void igt_pm_print_pci_dev_runtime_status(struct pci_device *pci_dev)
> +{
> +	char name[PATH_MAX], runtime_status[64];
> +	int fd, n_read;
> +
> +	snprintf(name, PATH_MAX, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/power/runtime_status",
> +		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func);
> +
> +	fd = open(name, O_RDONLY);
> +	igt_assert_f(fd >= 0, "Can't open runtime_status\n");
> +
> +	n_read = read(fd, runtime_status, sizeof(runtime_status) - 1);
> +	igt_assert(n_read >= 0);
> +	runtime_status[n_read] = '\0';
> +	igt_info("runtime suspend status for PCI '%04x:%02x:%02x.%01x' %s\n",
> +		 pci_dev->domain, pci_dev->bus, pci_dev->dev, pci_dev->func, runtime_status);
> +	close(fd);
> +}
> +
> +/**
> + * igt_pm_print_pci_card_runtime_status:
> + * @pci_dev: root port pci_dev.
> + * Print runtime suspend status for all PCI endpoints devices for a given
> + * root port.
> + */
> +void igt_pm_print_pci_card_runtime_status(void)
> +{
> +	int i = 0;
> +
> +	for (i = 0; i < MAX_PCI_DEVICES; i++) {
> +		if (!__pci_dev_pwrattr[i].pci_dev)
> +			break;
> +
> +		igt_pm_print_pci_dev_runtime_status(__pci_dev_pwrattr[i].pci_dev);
> +	}
> +}
> diff --git a/lib/igt_pm.h b/lib/igt_pm.h
> index 162d3ca3c..db187cc2e 100644
> --- a/lib/igt_pm.h
> +++ b/lib/igt_pm.h
> @@ -46,6 +46,23 @@ enum igt_runtime_pm_status {
>  	IGT_RUNTIME_PM_STATUS_UNKNOWN,
>  };
>  
> +/* PCI ACPI firmware node real state */
> +enum igt_acpi_d_state {
> +	IGT_ACPI_D0,
> +	IGT_ACPI_D1,
> +	IGT_ACPI_D2,
> +	IGT_ACPI_D3Hot,
> +	IGT_ACPI_D3Cold,
> +	IGT_ACPI_UNKNOWN_STATE,
> +};
> +
> +struct	igt_pm_pci_dev_pwrattr {
> +	struct pci_device *pci_dev;
> +	char control[64];
> +	bool autosuspend_supported;
> +	char autosuspend_delay[64];
> +};
> +
>  bool igt_setup_runtime_pm(int device);
>  void igt_disable_runtime_pm(void);
>  void igt_restore_runtime_pm(void);
> @@ -54,5 +71,12 @@ bool igt_wait_for_pm_status(enum igt_runtime_pm_status status);
>  bool igt_pm_dmc_loaded(int debugfs);
>  bool igt_pm_pc8_plus_residencies_enabled(int msr_fd);
>  bool i915_output_is_lpsp_capable(int drm_fd, igt_output_t *output);
> +bool igt_pm_acpi_d3cold_supported(struct pci_device *pci_dev);
> +enum igt_acpi_d_state
> +igt_pm_get_acpi_real_d_state(struct pci_device *pci_dev);
> +int igt_pm_enbale_pci_card_autosuspend(struct pci_device *pci_dev);
> +void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev);
> +void igt_pm_restore_pci_card_runtime_pm(void);
> +void igt_pm_print_pci_card_runtime_status(void);
>  
>  #endif /* IGT_PM_H */
> -- 
> 2.26.2
> 

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

* Re: [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool Anshuman Gupta
@ 2022-05-05 16:22   ` Rodrigo Vivi
  0 siblings, 0 replies; 14+ messages in thread
From: Rodrigo Vivi @ 2022-05-05 16:22 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: petri.latvala, igt-dev, badal.nilawar

On Thu, May 05, 2022 at 04:33:49PM +0530, Anshuman Gupta wrote:
> intel_pm_rpm tool is a debug tool. It can be use to setup
> and prepare the gfx card to go to D3Cold.
> It also provide the debug option to disable all display and
> prepare device to enter to runtime suspend.
> 
> v2:
> - Removed IS_DGFX() condition.
> 
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
> ---
>  tools/intel_pm_rpm.c | 206 +++++++++++++++++++++++++++++++++++++++++++
>  tools/meson.build    |   1 +
>  2 files changed, 207 insertions(+)
>  create mode 100644 tools/intel_pm_rpm.c
> 
> diff --git a/tools/intel_pm_rpm.c b/tools/intel_pm_rpm.c
> new file mode 100644
> index 000000000..bf8212b3c
> --- /dev/null
> +++ b/tools/intel_pm_rpm.c
> @@ -0,0 +1,206 @@
> +/*
> + * Copyright © 2022 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include <errno.h>
> +#include <getopt.h>
> +#include <glib.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include "igt.h"
> +#include "igt_device.h"
> +#include "igt_device_scan.h"
> +#include "igt_pm.h"
> +
> +typedef struct {
> +	int drm_fd;
> +	int debugfs_fd;
> +	uint32_t devid;
> +	drmModeResPtr res;
> +	igt_display_t display;
> +} data_t;
> +
> +const char *help_str =
> +	"  --disable-display\t\tDisable all screen and try to go into runtime pm.\n"
> +	"  --setup-d3cold\t\tPrepare dgfx gfx card to enter runtime D3Cold.\n"
> +	"  --help\t\tProvide help. Provide card name with IGT_DEVICE=drm:/dev/dri/card*.";
> +static struct option long_options[] = {
> +	{"disable-display", 0, 0, 'd'},
> +	{"setup-d3cold", 0, 0, 's'},
> +	{"help", 0, 0, 'h'},
> +	{ 0, 0, 0, 0 }
> +};
> +
> +const char *optstr = "dsh";
> +
> +static void usage(const char *name)
> +{
> +	igt_info("Usage: %s [options]\n", name);
> +	igt_info("%s\n", help_str);
> +}
> +
> +static void disable_all_displays(data_t *data)
> +{
> +	igt_output_t *output;
> +
> +	for (int i = 0; i < data->display.n_outputs; i++) {
> +		output = &data->display.outputs[i];
> +		igt_output_set_pipe(output, PIPE_NONE);
> +		igt_display_commit(&data->display);
> +	}
> +}
> +
> +static void setup_gfx_card_d3cold(data_t *data)
> +{
> +	struct pci_device *root;
> +	int d_state;
> +
> +	root = igt_device_get_pci_root_port(data->drm_fd);
> +
> +	if (!igt_pm_acpi_d3cold_supported(root)) {
> +		igt_info("D3Cold isn't supported on Root port %04x:%02x:%02x.%01x\n",
> +			 root->domain, root->bus, root->dev, root->func);
> +		return;
> +	}
> +
> +	disable_all_displays(data);
> +	igt_pm_setup_pci_card_runtime_pm(root);
> +	sleep(1);
> +	d_state = igt_pm_get_acpi_real_d_state(root);
> +
> +	if (d_state == IGT_ACPI_D3Cold) {
> +		igt_info("D3Cold achieved for root port %04x:%02x:%02x.%01x\n",
> +			 root->domain, root->bus, root->dev, root->func);
> +	} else {
> +		igt_pm_print_pci_card_runtime_status();
> +		igt_info("D3Cold not achieved yet. Please monitor %04x:%02x:%02x.%01x real_power_state\n",
> +			 root->domain, root->bus, root->dev, root->func);
> +	}

wait... I'm confused now...
I just realized that here we don't have the while(1) with the ctrl+c for exit like we have on the disable-display.

With that right after this line aren't we restoring all the runtime_pm control states?

Shouldn't we keep in loop here as well?

> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	bool disable_display = false, setup_d3cold = false;
> +	struct igt_device_card card;
> +	char *env_device = NULL;
> +	int c, option_index = 0;
> +	data_t data = {};
> +	int ret = 0;
> +
> +	if (argc <= 1) {
> +		usage(argv[0]);
> +		return EXIT_SUCCESS;
> +	}
> +
> +	env_device = getenv("IGT_DEVICE");
> +	igt_devices_scan(false);
> +
> +	if (env_device) {
> +		if (!igt_device_card_match(env_device, &card)) {
> +			igt_warn("No device found for the env_device\n");
> +			ret = EXIT_FAILURE;
> +			goto exit;
> +		}
> +	} else {
> +		if (!igt_device_find_first_i915_discrete_card(&card)) {
> +			igt_warn("No discrete gpu found\n");
> +			ret = EXIT_FAILURE;
> +			goto exit;
> +		}
> +	}
> +
> +	while ((c = getopt_long(argc, argv, optstr,
> +				long_options, &option_index)) != -1) {
> +		switch (c) {
> +		case 'd':
> +			disable_display = true;
> +			break;
> +		case 's':
> +			setup_d3cold = true;
> +			break;
> +		default:
> +		case 'h':
> +			usage(argv[0]);
> +			ret = EXIT_SUCCESS;
> +			goto exit;
> +		}
> +	}
> +
> +	data.drm_fd = igt_open_card(&card);
> +	if (data.drm_fd  >= 0) {
> +		igt_info("Device %s successfully opened\n", card.card);
> +	} else {
> +		igt_warn("Cannot open card %s device\n", card.card);
> +		ret = EXIT_FAILURE;
> +		goto exit;
> +	}
> +
> +	data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
> +	data.devid = intel_get_drm_devid(data.drm_fd);
> +	igt_setup_runtime_pm(data.drm_fd);
> +
> +	data.res = drmModeGetResources(data.drm_fd);
> +	if (data.res) {
> +		kmstest_set_vt_graphics_mode();
> +		igt_display_require(&data.display, data.drm_fd);
> +
> +		/* i915 disables RPM in case DMC is not loaded on kms supported cards */
> +		if (!igt_pm_dmc_loaded(data.debugfs_fd)) {
> +			igt_warn("dmc fw is not loaded, no runtime pm\n");
> +			ret = EXIT_FAILURE;
> +			goto exit;
> +		}
> +	}
> +
> +	if (disable_display) {
> +		disable_all_displays(&data);
> +		if (!igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED)) {
> +			__igt_debugfs_dump(data.drm_fd, "i915_runtime_pm_status", IGT_LOG_INFO);
> +			ret = EXIT_FAILURE;
> +			goto exit;
> +		}
> +
> +		igt_info("Device runtime suspended, Useful for debugging.\n"
> +			 "Hit CTRL-C to exit\n");
> +		/* Don't return useful for debugging */
> +		while (1)
> +			sleep(600);
> +	}
> +
> +	if (setup_d3cold)
> +		setup_gfx_card_d3cold(&data);
> +
> +exit:
> +	igt_restore_runtime_pm();
> +
> +	if (data.res)
> +		igt_display_fini(&data.display);
> +
> +	close(data.debugfs_fd);
> +	close(data.drm_fd);
> +	igt_devices_free();
> +
> +	return ret;
> +}
> diff --git a/tools/meson.build b/tools/meson.build
> index 771d0b9e3..24d0ea714 100644
> --- a/tools/meson.build
> +++ b/tools/meson.build
> @@ -28,6 +28,7 @@ tools_progs = [
>  	'intel_lid',
>  	'intel_opregion_decode',
>  	'intel_panel_fitter',
> +	'intel_pm_rpm',
>  	'intel_reg_checker',
>  	'intel_residency',
>  	'intel_stepping',
> -- 
> 2.26.2
> 

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

* Re: [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend
  2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend Anshuman Gupta
@ 2022-05-05 16:29   ` Rodrigo Vivi
  0 siblings, 0 replies; 14+ messages in thread
From: Rodrigo Vivi @ 2022-05-05 16:29 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: petri.latvala, igt-dev, badal.nilawar

On Thu, May 05, 2022 at 04:33:50PM +0530, Anshuman Gupta wrote:
> Few PCI devices under DGFX card tree don't have any kernel driver.
> These devices will block D3cold state of gfx root port.
> Adding support to configure autosuspend for all PCI devices
> under the gfx root port. This will not save/restore pci devices
> power attributes. This will be useful to tune D3Cold after boot.
> 
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  tools/intel_pm_rpm.c | 26 +++++++++++++++++++++++++-
>  1 file changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/intel_pm_rpm.c b/tools/intel_pm_rpm.c
> index bf8212b3c..92ce4f00b 100644
> --- a/tools/intel_pm_rpm.c
> +++ b/tools/intel_pm_rpm.c
> @@ -45,10 +45,12 @@ typedef struct {
>  const char *help_str =
>  	"  --disable-display\t\tDisable all screen and try to go into runtime pm.\n"
>  	"  --setup-d3cold\t\tPrepare dgfx gfx card to enter runtime D3Cold.\n"
> +	"  --configure-autosuspend\t\tConfigure dgfx gfx card pci tree autosuspend.\n"
>  	"  --help\t\tProvide help. Provide card name with IGT_DEVICE=drm:/dev/dri/card*.";
>  static struct option long_options[] = {
>  	{"disable-display", 0, 0, 'd'},
>  	{"setup-d3cold", 0, 0, 's'},
> +	{"configure-autosuspend", 0, 0, 'c'},

I know, my fault! but I believe these names are confusing...


* disable-display is okay... but it is disabling display and waiting in the loop and restoring display at ctrl+c

* setup-d3cold would be an okay name, if we are exiting and never restoring any state and leaving it auto in all cases.

* configure-autosuspend: that is exactly what my brain things about the setup-d3cold. After all, anyone willing to use
this use case here is looking after setting up a d3cold possible environment....


so, we either:

1. ensure setup-d3cold never restore the runtime_pm controls. and we use only that case.

2. we ensure we have 2 options setup-d3cold that never restores the runtime_pm and a new
force-d3cold-wait that loops until the ctrl+c and restore everything at exit.
then it would probably be good to rename the display one to disable-display-wait

>  	{"help", 0, 0, 'h'},
>  	{ 0, 0, 0, 0 }
>  };
> @@ -72,6 +74,22 @@ static void disable_all_displays(data_t *data)
>  	}
>  }
>  
> +static void
> +configure_gfx_card_autosuspend(data_t *data)
> +{
> +	struct pci_device *root;
> +
> +	root = igt_device_get_pci_root_port(data->drm_fd);
> +
> +	igt_info("Configuring pci devs autosuspend under Root port %04x:%02x:%02x.%01x\n",
> +		  root->domain, root->bus, root->dev, root->func);
> +
> +	if  (igt_pm_enbale_pci_card_autosuspend(root) < 0) {
> +		igt_warn("Unable to configure pci devs autosuspend under Root port"
> +			 "%04x:%02x:%02x.%01x\n", root->domain, root->bus, root->dev, root->func);
> +	}
> +}
> +
>  static void setup_gfx_card_d3cold(data_t *data)
>  {
>  	struct pci_device *root;
> @@ -102,7 +120,7 @@ static void setup_gfx_card_d3cold(data_t *data)
>  
>  int main(int argc, char *argv[])
>  {
> -	bool disable_display = false, setup_d3cold = false;
> +	bool disable_display = false, setup_d3cold = false, configure_autosuspend = false;
>  	struct igt_device_card card;
>  	char *env_device = NULL;
>  	int c, option_index = 0;
> @@ -140,6 +158,9 @@ int main(int argc, char *argv[])
>  		case 's':
>  			setup_d3cold = true;
>  			break;
> +		case 'c':
> +			configure_autosuspend = true;
> +			break;
>  		default:
>  		case 'h':
>  			usage(argv[0]);
> @@ -192,6 +213,9 @@ int main(int argc, char *argv[])
>  	if (setup_d3cold)
>  		setup_gfx_card_d3cold(&data);
>  
> +	if (configure_autosuspend)
> +		configure_gfx_card_autosuspend(&data);
> +
>  exit:
>  	igt_restore_runtime_pm();
>  
> -- 
> 2.26.2
> 

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

end of thread, other threads:[~2022-05-05 16:29 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-05 11:03 [igt-dev] [PATCH i-g-t v4 0/9] D3Cold Tool & IGT Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 1/9] test/i915_pm_rpm: Add placement to gem-{mmap-type, execbuf} Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 2/9] lib/igt_device: Get gfx PCI card root port Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 3/9] lib/igt_pm: D3Cold runtime pm infrastructure Anshuman Gupta
2022-05-05 16:16   ` Rodrigo Vivi
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 4/9] tools: Add intel_pm_rpm tool Anshuman Gupta
2022-05-05 16:22   ` Rodrigo Vivi
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 5/9] tools/intel_pm_rpm: Add an option to configure autosuspend Anshuman Gupta
2022-05-05 16:29   ` Rodrigo Vivi
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 6/9] i915_pm_rpm: Add D3Cold basic subtest Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 7/9] i915_pm_rpm: Extend gem_exec_stress test with D3Cold Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 8/9] i915_pm_rpm: Extend gem_execbuf " Anshuman Gupta
2022-05-05 11:03 ` [igt-dev] [PATCH i-g-t v4 9/9] i915_pm_rpm: Extend gem-mmap-type " Anshuman Gupta
2022-05-05 12:15 ` [igt-dev] ✗ Fi.CI.BAT: failure for D3Cold Tool & IGT (rev4) Patchwork

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.