[Intel-gfx] [PATCH] edp-DRRS test

Ramalingam C ramalingam.c at intel.com
Thu Jul 20 06:27:35 UTC 2017


On Friday 14 July 2017 02:21 AM, Paulo Zanoni wrote:
> Em Qua, 2017-06-21 às 13:40 +0530, Lohith BS escreveu:
>> Idleness DRRS:
>> 	By default the DRRS state will be at DRRS_HIGH_RR. When a
>> Display
>> 	content is Idle for more than 1Sec Idleness will be declared
>> and
>> 	DRRS_LOW_RR will be invoked, changing the refresh rate to the
>> 	lower most refresh rate supported by the panel. As soon as
>> there
>> 	is a display content change there will be a DRRS state
>> transition
>> 	as DRRS_LOW_RR--> DRRS_HIGH_RR, changing the refresh rate to
>> the
>> 	highest refresh rate supported by the panel.
>>
>> To test this, Idleness DRRS IGT will probe the DRRS state at below
>> instances and compare with the expected state.
>>
>> 	Instance					Expected State
>> 1. Immediately after rendering the still image		DRRS_HI
>> GH_RR
>> 2. After a delay of 1.2Sec				DRRS_LOW_RR
>> 3. After changing the frame buffer			DRRS_HIGH_R
>> R
>> 4. After a delay of 1.2Sec				DRRS_LOW_RR
>> 5. After changing the frame buffer			DRRS_HIGH_R
>> R
>> 6. After a delay of 1.2Sec				DRRS_LOW_RR
>>
>> The test checks the driver DRRS state from the debugfs entry. To
>> check the
>> actual refresh-rate, the number of vblanks received per sec.
>> The refresh-rate calculated is checked against the expected refresh-
>> rate
>> with a tolerance value of 2.
>>
>> This patch is a continuation of the earlier work
>> https://patchwork.freedesktop.org/patch/45472/ towards igt for
>> idleness
>>
>> DRRS. The code is tested on Broxton BXT_T platform.
>>
>> v2: Addressed the comments and suggestions from Vlad, Marius.
>> The signoff details from the earlier work are also included.
>>
>> v3: Modified vblank rate calculation by using reply-sequence,
>> provided by
>> drmWaitVBlank, as suggested by Chris Wilson.
>>
>> v4: As suggested from Chris Wilson and Daniel Vetter
>> 	1) Avoided using pthread for calculating vblank refresh rate,
>> 	   instead used drmWaitVBlank reply sequence.
>> 	2) Avoided using kernel-specific info like transitional delays,
>> 	   instead polling mechanism with timeout is used.
>> 	3) Included edp-DRRS as a subtest in
>> kms_frontbuffer_tracking.c,
>> 	   instead of having a separate test.
> I completely disagree with the way this part was implemented. The code
> added to kms_frontbuffer_tracking.c uses pretty much zero of the
> infrastructure provided by the file. This patch adds a completely
> unrelated set of functions to kms_frontbuffer_tracking.c. If we're not
> going to use the current subtests & infrastructure, please make it a
> separate test.
Agreed Paulo. As per daniel's suggestion we tried to reuse the 
infrastructure
provided by frontbuffer tracking igt. But we couldn't as the test case 
requirements
were not matching.

If we are fine with implementation of the test, we are good to separate
the test into separate igt.

Daniel, hope this is sounding good to you too.

With respect to other review comments, In this version, We have tried to 
address all chris's
review comments. please review them too.

Thanks a lot
--Ram
>
>
>> This is in continuation of last patch "https://patchwork.freedesktop.
>> org/patch/117149/"
>>
>> Signed-off-by: Lohith BS <lohith.bs at intel.com>
>> Signed-off-by: Ramalingam C <ramalingam.c at intel.com>
>> Signed-off-by: Vandana Kannan <vandana.kannan at intel.com>
>> Signed-off-by: aknautiy <ankit.k.nautiyal at intel.com>
>> ---
>>   tests/kms_frontbuffer_tracking.c | 453
>> ++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 452 insertions(+), 1 deletion(-)
>>
>> diff --git a/tests/kms_frontbuffer_tracking.c
>> b/tests/kms_frontbuffer_tracking.c
>> index c24e4a8..4d46e1e 100644
>> --- a/tests/kms_frontbuffer_tracking.c
>> +++ b/tests/kms_frontbuffer_tracking.c
>> @@ -32,9 +32,18 @@
>>   #include <poll.h>
>>   #include <pthread.h>
>>   
>> +#include "drmtest.h"
>> +#include "igt_debugfs.h"
>> +#include "igt_kms.h"
>> +#include "intel_chipset.h"
>> +#include "intel_batchbuffer.h"
>> +#include "ioctl_wrappers.h"
>> +#include <time.h>
>> +#include <stdlib.h>
>> +#include <sys/time.h>
>>   
>>   IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking
>> mechanism and "
>> -		     "its related features: FBC and PSR");
>> +		     "its related features: DRRS, FBC and PSR");
>>   
>>   /*
>>    * One of the aspects of this test is that, for every subtest, we
>> try different
>> @@ -327,6 +336,41 @@ drmModeModeInfo std_1024_mode = {
>>   	.name = "Custom 1024x768",
>>   };
>>   
>> +#define DRRS_TOLERANCE_THRESHOLD 2
>> +#define DRRS_POLL_TIMEOUT_PERIOD_MS 5000
>> +#define DRRS_STATUS_BYTES_CNT 1000
>> +#define DRRS_MAX_ITERATION 3
>> +
>> +/*
>> + * Struct to hold drrs test related data
>> + */
>> +typedef struct {
>> +	uint32_t devid;
>> +	uint32_t handle[2];
>> +	igt_display_t display;
>> +	igt_output_t *output;
>> +	enum pipe pipe;
>> +	igt_plane_t *primary;
>> +	struct igt_fb fb[2];
>> +	uint32_t fb_id[2];
>> +} drrs_data_t;
>> +
>> +/*
>> + * Structure to count vblank and note the starting time of the
>> counter
>> + */
>> +typedef struct {
>> +	unsigned int vbl_count;
>> +	struct timeval start;
>> +} vbl_info;
>> +
>> +/*
>> + * Structure for refresh rate type
>> + */
>> +typedef struct{
>> +	int rate;
>> +	const char *name;
>> +} refresh_rate_t;
>> +
>>   static drmModeModeInfoPtr
>> get_connector_smallest_mode(drmModeConnectorPtr c)
>>   {
>>   	int i;
>> @@ -3415,6 +3459,410 @@ static const char *flip_str(enum flip_type
>> flip)
>>   
>>   #define TEST_MODE_ITER_END } } } } } }
>>   
>> +static inline uint32_t pipe_select(int pipe)
>> +{
>> +	if (pipe > 1)
>> +		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
>> +	else if (pipe > 0)
>> +		return DRM_VBLANK_SECONDARY;
>> +	else
>> +		return DRM_VBLANK_ABSOLUTE;
>> +}
>> +
>> +/*
>> + * Calculates the total no. of millisec elapsed since timeval start
>> + */
>> +static double igt_millisec_elapsed(const struct timeval *start)
>> +{
>> +	struct timeval curr;
>> +
>> +	gettimeofday(&curr, NULL);
>> +	return (1e3*(curr.tv_sec - start->tv_sec) +
>> +				(curr.tv_usec - start-
>>> tv_usec)/1000.00);
>> +}
>> +
>> +/*
>> + * Func to read the DRRS status from debugfs
>> + */
>> +static bool read_drrs_status(char *str)
>> +{
>> +	FILE *fp;
>> +	int fd;
>> +	int cnt;
>> +
>> +	fd = igt_debugfs_open(drm.fd, "i915_drrs_status", O_RDONLY);
>> +	igt_assert(fd);
>> +	fp = fdopen(fd, "r");
>> +	igt_require(fp);
>> +	cnt = fread(str, DRRS_STATUS_BYTES_CNT - 1, 1, fp);
>> +
>> +	if (!cnt) {
>> +		if (!feof(fp)) {
>> +			igt_critical("Failed to read
>> i915_drrs_status:%d \n",
>> +				ferror(fp));
>> +			return false;
>> +		}
>> +		clearerr(fp);
>> +	}
>> +	fclose(fp);
>> +
>> +	return true;
>> +}
>> +
>> +/*
>> + * Func to check for DRRS support
>> + */
>> +static bool is_drrs_supported(void)
>> +{
>> +	char str[DRRS_STATUS_BYTES_CNT] = {};
>> +
>> +	if (!read_drrs_status(str))
>> +		return false;
>> +
>> +	return strstr(str, "DRRS Supported: Yes") != NULL;
>> +}
>> +
>> +/*
>> + * Func to check if DRRS is enabled by driver.
>> + */
>> +static bool is_drrs_enabled(void)
>> +{
>> +	char str[DRRS_STATUS_BYTES_CNT] = {};
>> +
>> +	if (!read_drrs_status(str))
>> +		return false;
>> +
>> +	return strstr(str, "Idleness DRRS: Disabled") == NULL;
>> +}
>> +
>> +
>> +/*
>> + * vbl_rate = vbl_count/time taken
>> + */
>> +static double vbl_rate(const union drm_wait_vblank *start,
>> +				const union drm_wait_vblank *end)
>> +{
>> +	double s, e;
>> +
>> +	s = start->reply.tval_sec + 1e-6 * start->reply.tval_usec;
>> +	e = end->reply.tval_sec + 1e-6 * end->reply.tval_usec;
>> +	return ((end->reply.sequence - start->reply.sequence) / (e -
>> s));
>> +}
>> +
>> +/*
>> + * refresh_rate = (20 vblanks) /(time for 20vblanks)
>> + */
>> +int calculate_refresh_rate(drrs_data_t *data)
>> +{
>> +	union drm_wait_vblank start, end;
>> +	struct timeval start_tv;
>> +	int refresh_rate;
>> +
>> +	memset(&start, 0, sizeof(start));
>> +	start.request.type = DRM_VBLANK_RELATIVE | pipe_select(data-
>>> pipe);
>> +
>> +	if (drmWaitVBlank(drm.fd, &start) != 0) {
>> +		igt_critical("drmWaitVBlank Failed!\n");
>> +		return -1;
>> +	}
>> +	gettimeofday(&start_tv, NULL);
>> +	memset(&end, 0, sizeof(end));
>> +	end.request.type = DRM_VBLANK_RELATIVE | pipe_select(data-
>>> pipe);
>> +
>> +	/* Configured to wait for 20 vblank events*/
>> +	end.request.sequence = 20;
>> +
>> +	if (drmWaitVBlank(drm.fd, &end) != 0) {
>> +		igt_critical("drmWaitVBlank Failed!\n");
>> +		return -1;
>> +	}
>> +	refresh_rate = vbl_rate(&start, &end);
>> +
>> +	return refresh_rate;
>> +}
>> +
>> +/*
>> + * Poll for DRRS transition from high to low with 5 seconds time
>> out.
>> + */
>> +int wait_for_drrs_switch_to_low(drrs_data_t *data)
>> +{
>> +	char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
>> +	const char *drrs_low_name = "DRRS_LOW_RR";
>> +	int status = 1;
>> +	struct timeval start_tv;
>> +
>> +	gettimeofday(&start_tv, NULL);
>> +
>> +	while (igt_millisec_elapsed(&start_tv) <
>> DRRS_POLL_TIMEOUT_PERIOD_MS) {
>> +
>> +		if (!read_drrs_status(drrs_status)) {
>> +			status = -1;
>> +			break;
>> +		}
>> +
>> +		if (strstr(drrs_status, drrs_low_name) != NULL)
>> +			break;
>> +	}
>> +
>> +	if (igt_millisec_elapsed(&start_tv) >
>> DRRS_POLL_TIMEOUT_PERIOD_MS) {
>> +
>> +		igt_critical("DRRS failed to switch refresh rate
>> from "
>> +			"higher to lower\n");
>> +
>> +		status = -1;
>> +	}
>> +
>> +	return status;
>> +}
>> +
>> +/*
>> + * Check if calulated refresh rate is same as expected refresh rate
>> + * Returns 0 in case of pass , 1 in case of failure, and -1 for
>> error.
>> + */
>> +static int check_refresh_rate(drrs_data_t *data, refresh_rate_t
>> *expected_rr)
>> +{
>> +	int refresh_rate = -1;
>> +	char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
>> +
>> +	/* Get the DRRS Status from the debugfs entry */
>> +	if (!read_drrs_status(drrs_status))
>> +		return -1;
>> +
>> +	refresh_rate = calculate_refresh_rate(data);
>> +
>> +	if (refresh_rate < 0) {
>> +		igt_critical("Refresh rate calculation FAILED\n");
>> +		return -1;
>> +	}
>> +
>> +	/* Compare with Expected Refresh Rate */
>> +	if (strstr(drrs_status, expected_rr->name) != NULL
>> +	&& abs(refresh_rate - expected_rr->rate) <=
>> DRRS_TOLERANCE_THRESHOLD) {
>> +		return 0;
>> +	}
>> +	igt_critical("Expected %s : FAILED.\n", expected_rr->name);
>> +
>> +	return 1;
>> +}
>> +
>> +/*
>> + * This function
>> + * 1. Creates framebuffers
>> + * 2. Apply framebuffers alternatively and count the vblank refresh
>> rate
>> + *    which should be equal to highest refresh rate supported.
>> + * 3. Poll for DRRS to toggle from DRRS_HIGH_RR -> DRRS_LOW_RR with
>> 5sec
>> + *    timeout using kernel debugfs entry(i915_drrs_status).
>> + * 4. Once DRRS switches to LOW we count the vblank refresh rate
>> which
>> + *    should be equal to lowest refresh rate supported.
>> + * 5. The above calculated vblank refresh rates can have a tolerance
>> of 2.
>> + */
>> +static int execute_test(drrs_data_t *data)
>> +{
>> +	igt_display_t *display = &data->display;
>> +	igt_output_t *output = data->output;
>> +	drmModeModeInfo *mode, *supported_modes;
>> +	int test_failed = 0;
>> +	int ret, i, i_mod, count_modes;
>> +	refresh_rate_t high_rr, low_rr;
>> +
>> +	high_rr.name = "DRRS_HIGH_RR";
>> +	high_rr.rate = 0;
>> +	low_rr.name = "DRRS_LOW_RR";
>> +	low_rr.rate = 0;
>> +
>> +	/* get the max and min supported refresh rates for the
>> display */
>> +	supported_modes = output->config.connector->modes;
>> +	count_modes = output->config.connector->count_modes;
>> +
>> +	/* minimum 2 modes are required for DRRS */
>> +	igt_assert_f(count_modes >= 2, "Minimum 2 modes required for
>> DRRS\n");
>> +
>> +	for (i = 0; i < count_modes; i++) {
>> +		int rr = supported_modes[i].vrefresh;
>> +
>> +		if (i == 0) {
>> +			high_rr.rate = low_rr.rate = rr;
>> +			continue;
>> +		}
>> +
>> +		if (high_rr.rate < rr)
>> +			high_rr.rate = rr;
>> +
>> +		if (low_rr.rate > rr)
>> +			low_rr.rate = rr;
>> +	}
>> +
>> +	igt_output_set_pipe(output, data->pipe);
>> +	data->primary = igt_output_get_plane(data->output,
>> +				DRM_PLANE_TYPE_OVERLAY);
>> +	mode = igt_output_get_mode(data->output);
>> +	data->fb_id[0] = igt_create_color_fb(drm.fd, mode->hdisplay,
>> +						mode->vdisplay,
>> +						DRM_FORMAT_XRGB8888,
>> +						LOCAL_DRM_FORMAT_MOD
>> _NONE,
>> +						0.0, 100.1, 0.0,
>> &data->fb[0]);
>> +
>> +	igt_assert(data->fb_id[0]);
>> +	data->fb_id[1] = igt_create_color_fb(drm.fd, mode->hdisplay,
>> +						mode->vdisplay,
>> +						DRM_FORMAT_XRGB8888,
>> +						LOCAL_DRM_FORMAT_MOD
>> _NONE,
>> +						100.1, 0.0, 0.0,
>> +						&data->fb[1]);
>> +
>> +	igt_assert(data->fb_id[1]);
>> +	data->handle[0] = data->fb[0].gem_handle;
>> +	data->handle[1] = data->fb[1].gem_handle;
>> +
>> +	for (i = 1; i <= DRRS_MAX_ITERATION; i++) {
>> +		i_mod = i % 2;
>> +		igt_plane_set_fb(data->primary, &data->fb[i_mod]);
>> +		igt_display_commit(display);
>> +
>> +		if (!is_drrs_enabled()) {
>> +			igt_critical("DRRS not enabled\n");
>> +			igt_plane_set_fb(data->primary, NULL);
>> +			igt_output_set_pipe(output, PIPE_ANY);
>> +			igt_display_commit(display);
>> +			igt_remove_fb(drm.fd, &data->fb[0]);
>> +			igt_remove_fb(drm.fd, &data->fb[1]);
>> +			return -1;
>> +		}
>> +
>> +		/* expecting High RR */
>> +		ret =  check_refresh_rate(data, &high_rr);
>> +
>> +		if (ret == -1)
>> +			return -1;
>> +
>> +		if (ret == 1)
>> +			test_failed = 1;
>> +
>> +		/*
>> +		 * Poll kernel debugfs entry for DRRS
>> +		 * transition from High to Low
>> +		 */
>> +		ret = wait_for_drrs_switch_to_low(data);
>> +
>> +		if (ret == -1)
>> +			return 1;
>> +
>> +		/* expecting Low RR */
>> +		ret = check_refresh_rate(data, &low_rr);
>> +
>> +		if (ret == -1)
>> +			return -1;
>> +
>> +		if (ret == 1)
>> +			test_failed = 1;
>> +	}
>> +
>> +	return test_failed;
>> +}
>> +
>> +/*
>> + * Func to free the framebuffers after the test completion.
>> + */
>> +static void finish_crtc(drrs_data_t *data)
>> +{
>> +	igt_plane_set_fb(data->primary, NULL);
>> +	igt_output_set_pipe(data->output, PIPE_ANY);
>> +	igt_display_commit(&data->display);
>> +
>> +	igt_remove_fb(drm.fd, &data->fb[0]);
>> +	igt_remove_fb(drm.fd, &data->fb[1]);
>> +}
>> +
>> +/*
>> + * Func to reset the display structures after the test completion.
>> + */
>> +static void reset_display(drrs_data_t *data)
>> +{
>> +	igt_display_t *display = &data->display;
>> +	enum pipe pipe_id;
>> +
>> +	for_each_pipe(display, pipe_id) {
>> +		igt_pipe_t *pipe = &display->pipes[pipe_id];
>> +		igt_plane_t *plane = igt_pipe_get_plane_type(pipe,
>> +					DRM_PLANE_TYPE_PRIMARY);
>> +
>> +		if (plane->fb)
>> +			igt_plane_set_fb(plane, NULL);
>> +	}
>> +
>> +	for_each_connected_output(display, data->output)
>> +		igt_output_set_pipe(data->output, PIPE_ANY);
>> +}
>> +
>> +/*
>> + * Func to run the drrs test for the eDP display.
>> + */
>> +static void run_test(drrs_data_t *data)
>> +{
>> +	int ret;
>> +	igt_display_t *display = &data->display;
>> +
>> +	reset_display(data);
>> +
>> +	for_each_pipe_with_valid_output(display, data->pipe, data-
>>> output) {
>> +		drmModeConnectorPtr c = data->output-
>>> config.connector;
>> +
>> +		if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
>> +			c->connection != DRM_MODE_CONNECTED)
>> +			continue;
>> +
>> +		ret = execute_test(data);
>> +
>> +		igt_skip_on_f(ret == -1,
>> +				"%s on pipe %s, connector
>> %s:SKIPPED\n",
>> +					igt_subtest_name(),
>> +					kmstest_pipe_name(data-
>>> pipe),
>> +					igt_output_name(data-
>>> output));
>> +
>> +		igt_fail_on_f(ret == 1,
>> +				"%s on pipe %s, connector
>> %s:FAILED\n",
>> +					igt_subtest_name(),
>> +					kmstest_pipe_name(data-
>>> pipe),
>> +					igt_output_name(data-
>>> output));
>> +
>> +		igt_assert_f(ret == 0,
>> +				"%s on pipe %s, connector %s:
>> PASSED\n",
>> +					igt_subtest_name(),
>> +					kmstest_pipe_name(data-
>>> pipe),
>> +					igt_output_name(data-
>>> output));
>> +
>> +		finish_crtc(data);
>> +	}
>> +}
>> +
>> +/*
>> + * Function to test edp-DRRS feature.Exits from the function if PSR
>> is enabled
>> + */
>> +void edp_drrs_test(void)
>> +{
>> +	drrs_data_t data = {};
>> +
>> +	igt_assert_f(!psr.can_test,
>> +			"DRRS cannot be tested as PSR is
>> enabled\n");
>> +	igt_skip_on_simulation();
>> +
>> +	/*
>> +	 * Using the same drm.fd which was opened during
>> setup_environment
>> +	 */
>> +	igt_assert_f(drm.fd != -1, "Invalid fd\n");
>> +	data.devid = intel_get_drm_devid(drm.fd);
>> +	igt_assert_f(data.devid >= 0, "Invalid dev id\n");
>> +
>> +	/*
>> +	 * Check if the DRRS is supported.If yes call the Idleness
>> DRRS test
>> +	 */
>> +	igt_require_f(is_drrs_supported(),
>> +			"DRRS not supported:check VBT/panel
>> caps\n");
>> +	igt_display_init(&data.display, drm.fd);
>> +	run_test(&data);
>> +	igt_display_fini(&data.display);
>> +}
>> +
>>   int main(int argc, char *argv[])
>>   {
>>   	struct test_mode t;
>> @@ -3628,6 +4076,9 @@ int main(int argc, char *argv[])
>>   			suspend_subtest(&t);
>>   	TEST_MODE_ITER_END
>>   
>> +	igt_subtest_f("edp-DRRS")
>> +		edp_drrs_test();
>> +
>>   	t.pipes = PIPE_SINGLE;
>>   	t.screen = SCREEN_PRIM;
>>   	t.plane = PLANE_PRI;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/intel-gfx/attachments/20170720/f4949f90/attachment-0001.html>


More information about the Intel-gfx mailing list