diff mbox

[i-g-t,v2] igt/psr: Test vblank continuity with PSR enabled

Message ID 20171212020657.2181-1-dhinakaran.pandiyan@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dhinakaran Pandiyan Dec. 12, 2017, 2:06 a.m. UTC
PSR allows DMC to put the system to low power states when active, but
this can reset the frame counter on some platforms. The frame counter reset
leads to a negative diff applied to vblank count. This subtest checks
for that.

v2: Some optimizations and data type changes.
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
---
 tests/kms_psr_sink_crc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

Comments

Ville Syrjälä Dec. 12, 2017, 7:10 a.m. UTC | #1
On Mon, Dec 11, 2017 at 06:06:57PM -0800, Dhinakaran Pandiyan wrote:
> PSR allows DMC to put the system to low power states when active, but
> this can reset the frame counter on some platforms. The frame counter reset
> leads to a negative diff applied to vblank count. This subtest checks
> for that.

I don't think the frame counter issues are limited to DMC. I expect that
the frame counter would stop (at least when we shut off the main link)
even on HSW. So I think the test should actually sleep for some
suitable long period and make sure the vblank counter has progressed
appropriately during that time.

Checking the DC and PSR counters around the wait does seem like a
good idea.

> 
> v2: Some optimizations and data type changes.
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  tests/kms_psr_sink_crc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c
> index 83a69f0b..831368b2 100644
> --- a/tests/kms_psr_sink_crc.c
> +++ b/tests/kms_psr_sink_crc.c
> @@ -69,6 +69,7 @@ typedef struct {
>  	enum operations op;
>  	uint32_t devid;
>  	uint32_t crtc_id;
> +	enum pipe pipe;
>  	igt_display_t display;
>  	drm_intel_bufmgr *bufmgr;
>  	struct igt_fb fb_green, fb_white;
> @@ -107,6 +108,7 @@ static void setup_output(data_t *data)
>  		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
>  			continue;
>  
> +		data->pipe = pipe;
>  		igt_output_set_pipe(output, pipe);
>  		data->crtc_id = output->config.crtc->crtc_id;
>  		data->output = output;
> @@ -285,6 +287,63 @@ static void assert_or_manual(bool condition, const char *expected)
>  	igt_assert(igt_interactive_debug || condition);
>  }
>  
> +static unsigned int get_vblank(int fd, unsigned int pipe)
> +{
> +	union drm_wait_vblank vbl;
> +
> +	memset(&vbl, 0, sizeof(vbl));
> +	vbl.request.type = DRM_VBLANK_RELATIVE | kmstest_get_vbl_flag(pipe);
> +	igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
> +
> +	return vbl.reply.sequence;
> +}
> +
> +static void dmc_read_counts(unsigned int fd, unsigned int *count)
> +{
> +	char buf[512];
> +
> +	igt_debugfs_read(fd, "i915_dmc_info", buf);
> +	igt_assert_eq(sscanf(strstr(buf, "DC3 -> DC5"), "DC3 -> DC5 count: %u", &count[0]),
> +		      1);
> +	igt_assert_eq(sscanf(strstr(buf, "DC5 -> DC6"), "DC5 -> DC6 count: %u", &count[1]),
> +		      1);
> +	igt_debug("DC3->DC5 count=%u, DC5->DC6 count=%u\n", count[0], count[1]);
> +}
> +
> +static void check_vblanks(data_t *data)
> +{
> +	unsigned int first_vbl, second_vbl;
> +	int wait = 30; /* Takes about 2.5 seconds for DC_OFF disable */
> +	char buf[512];
> +	bool has_dmc;
> +
> +	first_vbl = get_vblank(data->drm_fd, data->pipe);
> +
> +	igt_debugfs_read(data->drm_fd, "i915_dmc_info", buf);
> +	has_dmc = strstr(buf, "fw loaded: yes");
> +
> +	if (has_dmc) {
> +		unsigned int new_dc[2], old_dc[2];
> +
> +		dmc_read_counts(data->drm_fd, new_dc);
> +		do {
> +			memcpy(old_dc, new_dc, sizeof(new_dc));
> +			usleep(100 * 1000);
> +			dmc_read_counts(data->drm_fd, new_dc);
> +		} while (!memcmp(old_dc, new_dc, sizeof(new_dc)) && --wait);
> +
> +		igt_assert_f(wait, "Timed out waiting for DC state transition 3s.\n");
> +	} else {
> +		sleep(3);
> +	}
> +
> +	second_vbl = get_vblank(data->drm_fd, data->pipe);
> +	igt_debug("vblank count went from %u to %u in %d ms.\n",
> +		  first_vbl, second_vbl, has_dmc ? (30 - wait) * 100 : 3000);
> +
> +	igt_assert_lt(first_vbl, second_vbl);
> +}
> +
>  static bool drrs_disabled(data_t *data)
>  {
>  	char buf[512];
> @@ -572,6 +631,13 @@ int main(int argc, char *argv[])
>  		}
>  	}
>  
> +	igt_subtest("vblank") {
> +		setup_test_plane(&data);
> +		igt_assert(wait_psr_entry(&data));
> +		check_vblanks(&data);
> +		test_cleanup(&data);
> +	}
> +
>  	igt_subtest_f("dpms_off_psr_active") {
>  		data.test_plane = DRM_PLANE_TYPE_PRIMARY;
>  		data.op = RENDER;
> -- 
> 2.11.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Dhinakaran Pandiyan Dec. 12, 2017, 6:46 p.m. UTC | #2
On Tue, 2017-12-12 at 09:10 +0200, Ville Syrjälä wrote:
> On Mon, Dec 11, 2017 at 06:06:57PM -0800, Dhinakaran Pandiyan wrote:

> > PSR allows DMC to put the system to low power states when active, but

> > this can reset the frame counter on some platforms. The frame counter reset

> > leads to a negative diff applied to vblank count. This subtest checks

> > for that.

> 

> I don't think the frame counter issues are limited to DMC. I expect that

> the frame counter would stop (at least when we shut off the main link)

> even on HSW. So I think the test should actually sleep for some

> suitable long period and make sure the vblank counter has progressed

> appropriately during that time.


Yeah, I'd guess the frame counter would be stuck on HSW as opposed to
being reset, like on DMC platforms. This patch already tests the vblank
count after a delay of 3 seconds on non-DMC platforms. But, I'm not
entirely sure if that's enough for the link to turn off, will see if I
can find a HSW here.

-DK

> 

> Checking the DC and PSR counters around the wait does seem like a

> good idea.

> 

> > 

> > v2: Some optimizations and data type changes.

> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>

> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>

> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>

> > ---

> >  tests/kms_psr_sink_crc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++

> >  1 file changed, 66 insertions(+)

> > 

> > diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c

> > index 83a69f0b..831368b2 100644

> > --- a/tests/kms_psr_sink_crc.c

> > +++ b/tests/kms_psr_sink_crc.c

> > @@ -69,6 +69,7 @@ typedef struct {

> >  	enum operations op;

> >  	uint32_t devid;

> >  	uint32_t crtc_id;

> > +	enum pipe pipe;

> >  	igt_display_t display;

> >  	drm_intel_bufmgr *bufmgr;

> >  	struct igt_fb fb_green, fb_white;

> > @@ -107,6 +108,7 @@ static void setup_output(data_t *data)

> >  		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)

> >  			continue;

> >  

> > +		data->pipe = pipe;

> >  		igt_output_set_pipe(output, pipe);

> >  		data->crtc_id = output->config.crtc->crtc_id;

> >  		data->output = output;

> > @@ -285,6 +287,63 @@ static void assert_or_manual(bool condition, const char *expected)

> >  	igt_assert(igt_interactive_debug || condition);

> >  }

> >  

> > +static unsigned int get_vblank(int fd, unsigned int pipe)

> > +{

> > +	union drm_wait_vblank vbl;

> > +

> > +	memset(&vbl, 0, sizeof(vbl));

> > +	vbl.request.type = DRM_VBLANK_RELATIVE | kmstest_get_vbl_flag(pipe);

> > +	igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);

> > +

> > +	return vbl.reply.sequence;

> > +}

> > +

> > +static void dmc_read_counts(unsigned int fd, unsigned int *count)

> > +{

> > +	char buf[512];

> > +

> > +	igt_debugfs_read(fd, "i915_dmc_info", buf);

> > +	igt_assert_eq(sscanf(strstr(buf, "DC3 -> DC5"), "DC3 -> DC5 count: %u", &count[0]),

> > +		      1);

> > +	igt_assert_eq(sscanf(strstr(buf, "DC5 -> DC6"), "DC5 -> DC6 count: %u", &count[1]),

> > +		      1);

> > +	igt_debug("DC3->DC5 count=%u, DC5->DC6 count=%u\n", count[0], count[1]);

> > +}

> > +

> > +static void check_vblanks(data_t *data)

> > +{

> > +	unsigned int first_vbl, second_vbl;

> > +	int wait = 30; /* Takes about 2.5 seconds for DC_OFF disable */

> > +	char buf[512];

> > +	bool has_dmc;

> > +

> > +	first_vbl = get_vblank(data->drm_fd, data->pipe);

> > +

> > +	igt_debugfs_read(data->drm_fd, "i915_dmc_info", buf);

> > +	has_dmc = strstr(buf, "fw loaded: yes");

> > +

> > +	if (has_dmc) {

> > +		unsigned int new_dc[2], old_dc[2];

> > +

> > +		dmc_read_counts(data->drm_fd, new_dc);

> > +		do {

> > +			memcpy(old_dc, new_dc, sizeof(new_dc));

> > +			usleep(100 * 1000);

> > +			dmc_read_counts(data->drm_fd, new_dc);

> > +		} while (!memcmp(old_dc, new_dc, sizeof(new_dc)) && --wait);

> > +

> > +		igt_assert_f(wait, "Timed out waiting for DC state transition 3s.\n");

> > +	} else {

> > +		sleep(3);

> > +	}

> > +

> > +	second_vbl = get_vblank(data->drm_fd, data->pipe);

> > +	igt_debug("vblank count went from %u to %u in %d ms.\n",

> > +		  first_vbl, second_vbl, has_dmc ? (30 - wait) * 100 : 3000);

> > +

> > +	igt_assert_lt(first_vbl, second_vbl);

> > +}

> > +

> >  static bool drrs_disabled(data_t *data)

> >  {

> >  	char buf[512];

> > @@ -572,6 +631,13 @@ int main(int argc, char *argv[])

> >  		}

> >  	}

> >  

> > +	igt_subtest("vblank") {

> > +		setup_test_plane(&data);

> > +		igt_assert(wait_psr_entry(&data));

> > +		check_vblanks(&data);

> > +		test_cleanup(&data);

> > +	}

> > +

> >  	igt_subtest_f("dpms_off_psr_active") {

> >  		data.test_plane = DRM_PLANE_TYPE_PRIMARY;

> >  		data.op = RENDER;

> > -- 

> > 2.11.0

> > 

> > _______________________________________________

> > Intel-gfx mailing list

> > Intel-gfx@lists.freedesktop.org

> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx

>
diff mbox

Patch

diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c
index 83a69f0b..831368b2 100644
--- a/tests/kms_psr_sink_crc.c
+++ b/tests/kms_psr_sink_crc.c
@@ -69,6 +69,7 @@  typedef struct {
 	enum operations op;
 	uint32_t devid;
 	uint32_t crtc_id;
+	enum pipe pipe;
 	igt_display_t display;
 	drm_intel_bufmgr *bufmgr;
 	struct igt_fb fb_green, fb_white;
@@ -107,6 +108,7 @@  static void setup_output(data_t *data)
 		if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
 			continue;
 
+		data->pipe = pipe;
 		igt_output_set_pipe(output, pipe);
 		data->crtc_id = output->config.crtc->crtc_id;
 		data->output = output;
@@ -285,6 +287,63 @@  static void assert_or_manual(bool condition, const char *expected)
 	igt_assert(igt_interactive_debug || condition);
 }
 
+static unsigned int get_vblank(int fd, unsigned int pipe)
+{
+	union drm_wait_vblank vbl;
+
+	memset(&vbl, 0, sizeof(vbl));
+	vbl.request.type = DRM_VBLANK_RELATIVE | kmstest_get_vbl_flag(pipe);
+	igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
+
+	return vbl.reply.sequence;
+}
+
+static void dmc_read_counts(unsigned int fd, unsigned int *count)
+{
+	char buf[512];
+
+	igt_debugfs_read(fd, "i915_dmc_info", buf);
+	igt_assert_eq(sscanf(strstr(buf, "DC3 -> DC5"), "DC3 -> DC5 count: %u", &count[0]),
+		      1);
+	igt_assert_eq(sscanf(strstr(buf, "DC5 -> DC6"), "DC5 -> DC6 count: %u", &count[1]),
+		      1);
+	igt_debug("DC3->DC5 count=%u, DC5->DC6 count=%u\n", count[0], count[1]);
+}
+
+static void check_vblanks(data_t *data)
+{
+	unsigned int first_vbl, second_vbl;
+	int wait = 30; /* Takes about 2.5 seconds for DC_OFF disable */
+	char buf[512];
+	bool has_dmc;
+
+	first_vbl = get_vblank(data->drm_fd, data->pipe);
+
+	igt_debugfs_read(data->drm_fd, "i915_dmc_info", buf);
+	has_dmc = strstr(buf, "fw loaded: yes");
+
+	if (has_dmc) {
+		unsigned int new_dc[2], old_dc[2];
+
+		dmc_read_counts(data->drm_fd, new_dc);
+		do {
+			memcpy(old_dc, new_dc, sizeof(new_dc));
+			usleep(100 * 1000);
+			dmc_read_counts(data->drm_fd, new_dc);
+		} while (!memcmp(old_dc, new_dc, sizeof(new_dc)) && --wait);
+
+		igt_assert_f(wait, "Timed out waiting for DC state transition 3s.\n");
+	} else {
+		sleep(3);
+	}
+
+	second_vbl = get_vblank(data->drm_fd, data->pipe);
+	igt_debug("vblank count went from %u to %u in %d ms.\n",
+		  first_vbl, second_vbl, has_dmc ? (30 - wait) * 100 : 3000);
+
+	igt_assert_lt(first_vbl, second_vbl);
+}
+
 static bool drrs_disabled(data_t *data)
 {
 	char buf[512];
@@ -572,6 +631,13 @@  int main(int argc, char *argv[])
 		}
 	}
 
+	igt_subtest("vblank") {
+		setup_test_plane(&data);
+		igt_assert(wait_psr_entry(&data));
+		check_vblanks(&data);
+		test_cleanup(&data);
+	}
+
 	igt_subtest_f("dpms_off_psr_active") {
 		data.test_plane = DRM_PLANE_TYPE_PRIMARY;
 		data.op = RENDER;