[Intel-gfx] [PATCH 2/2] tests: add kms_edp_vdd_race

Daniel Vetter daniel at ffwll.ch
Mon Nov 11 19:15:46 CET 2013


On Mon, Nov 11, 2013 at 03:06:10PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni at intel.com>
> 
> We recently fixed a bug where it was impossible to do I2C transactions
> on eDP panels when they were disabled. Now it should be possible to do
> these transactions when the panel is disabled, but there's a race
> condition that triggers dmesg errors if we try do do the I2C
> transactions and set a mode on the panel at the same time. This
> program should reproduce this bug and check dmesg for errors.
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>

Like I've said in the previous mail I think the generic dmesg error
checking should be somewhere generic (and probably in piglit). Otherwise
the test looks good. And the naming also matches the new convention ;-)
-Daniel

> ---
>  tests/.gitignore         |   1 +
>  tests/Makefile.am        |   2 +
>  tests/kms_edp_vdd_race.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 229 insertions(+)
>  create mode 100644 tests/kms_edp_vdd_race.c
> 
> diff --git a/tests/.gitignore b/tests/.gitignore
> index 09ea074..ddb61f9 100644
> --- a/tests/.gitignore
> +++ b/tests/.gitignore
> @@ -102,6 +102,7 @@ igt_no_exit_list_only
>  igt_no_subtest
>  kms_addfb
>  kms_cursor_crc
> +kms_edp_vdd_race
>  kms_flip
>  kms_pipe_crc_basic
>  kms_render
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 0426ec0..955d2a3 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -52,6 +52,7 @@ TESTS_progs_M = \
>  	gem_write_read_ring_switch \
>  	kms_addfb \
>  	kms_cursor_crc \
> +	kms_edp_vdd_race \
>  	kms_flip \
>  	kms_pipe_crc_basic \
>  	kms_render \
> @@ -236,6 +237,7 @@ gem_fence_thrash_LDADD = $(LDADD) -lpthread
>  gem_flink_race_LDADD = $(LDADD) -lpthread
>  gem_threaded_access_tiled_LDADD = $(LDADD) -lpthread
>  prime_self_import_LDADD = $(LDADD) -lpthread
> +kms_edp_vdd_race_LDADD = $(LDADD) -lpthread
>  
>  gem_wait_render_timeout_LDADD = $(LDADD) -lrt
>  kms_flip_LDADD = $(LDADD) -lrt
> diff --git a/tests/kms_edp_vdd_race.c b/tests/kms_edp_vdd_race.c
> new file mode 100644
> index 0000000..a6bff65
> --- /dev/null
> +++ b/tests/kms_edp_vdd_race.c
> @@ -0,0 +1,226 @@
> +/*
> + * Copyright © 2013 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.
> + *
> + * Authors: Paulo Zanoni <paulo.r.zanoni at intel.com>
> + *
> + */
> +
> +#include <dirent.h>
> +#include <fcntl.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c-dev.h>
> +#include <pthread.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +
> +#include "drmtest.h"
> +
> +int drm_fd, kmsg_fd;
> +drmModeResPtr res;
> +drmModeConnectorPtr edp_connector;
> +bool stop;
> +
> +static void disable_all_screens(void)
> +{
> +	int i, rc;
> +
> +	for (i = 0; i < res->count_crtcs; i++) {
> +		rc = drmModeSetCrtc(drm_fd, res->crtcs[i], -1, 0, 0,
> +				    NULL, 0, NULL);
> +		igt_assert(rc == 0);
> +	}
> +}
> +
> +static void find_edp_connector(void)
> +{
> +	int i;
> +	drmModeConnectorPtr c;
> +
> +	edp_connector = NULL;
> +	for (i = 0; i < res->count_connectors; i++) {
> +		c = drmModeGetConnector(drm_fd, res->connectors[i]);
> +
> +		if (c->connector_type == DRM_MODE_CONNECTOR_eDP) {
> +			igt_require(c->connection == DRM_MODE_CONNECTED);
> +			edp_connector = c;
> +			break;
> +		}
> +
> +		drmModeFreeConnector(c);
> +	}
> +	igt_require(edp_connector);
> +}
> +
> +static void read_edid_ioctl(int fd)
> +{
> +	unsigned char edid[128] = {};
> +	struct i2c_msg msgs[] = {
> +		{ /* Start at 0. */
> +			.addr = 0x50,
> +			.flags = 0,
> +			.len = 1,
> +			.buf = edid,
> +		}, { /* Now read the EDID. */
> +			.addr = 0x50,
> +			.flags = I2C_M_RD,
> +			.len = 128,
> +			.buf = edid,
> +		}
> +	};
> +	struct i2c_rdwr_ioctl_data msgset = {
> +		.msgs = msgs,
> +		.nmsgs = 2,
> +	};
> +
> +	ioctl(fd, I2C_RDWR, &msgset);
> +}
> +
> +/* TODO: We're currently just trying to read all the I2C files. We should try to
> + * find which one is really the eDP I2C file and just read from it. */
> +static void read_i2c_edid(void)
> +{
> +	int fd;
> +	DIR *dir;
> +
> +	struct dirent *dirent;
> +	char full_name[32];
> +
> +	dir = opendir("/dev/");
> +	igt_assert(dir);
> +
> +	while ((dirent = readdir(dir))) {
> +		if (strncmp(dirent->d_name, "i2c-", 4) == 0) {
> +			snprintf(full_name, 32, "/dev/%s", dirent->d_name);
> +			fd = open(full_name, O_RDWR);
> +			igt_assert(fd != -1);
> +			read_edid_ioctl(fd);
> +			close(fd);
> +		}
> +	}
> +
> +	closedir(dir);
> +}
> +
> +static void *i2c_thread_func(void *unused)
> +{
> +	while (!stop)
> +		read_i2c_edid();
> +
> +	pthread_exit(NULL);
> +}
> +
> +static uint32_t create_fb(int width, int height)
> +{
> +	struct kmstest_fb fb;
> +	cairo_t *cr;
> +	uint32_t buffer_id;
> +
> +	buffer_id = kmstest_create_fb(drm_fd, width, height, 32, 24, false,
> +				      &fb);
> +	cr = kmstest_get_cairo_ctx(drm_fd, &fb);
> +	kmstest_paint_test_pattern(cr, width, height);
> +	return buffer_id;
> +}
> +
> +static void enable_edp_screen(void)
> +{
> +	int rc;
> +	uint32_t buffer_id = 0, crtc_id, connector_id;
> +	drmModeModeInfoPtr mode;
> +
> +	crtc_id = res->crtcs[0];
> +	connector_id = edp_connector->connector_id;
> +	mode = &edp_connector->modes[0];
> +
> +	buffer_id = create_fb(mode->hdisplay, mode->vdisplay);
> +
> +	rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id,
> +			    1, mode);
> +	igt_assert(rc == 0);
> +}
> +
> +static void *modeset_thread_func(void *unused)
> +{
> +	while (!stop) {
> +		disable_all_screens();
> +		sleep(1);
> +		enable_edp_screen();
> +		sleep(1);
> +	}
> +
> +	pthread_exit(NULL);
> +}
> +
> +/* This test exercises a race condition that happens when we're trying to read
> + * the I2C data from an eDP panel at the same time we're trying to set a mode on
> + * the same panel. If we have the bug, we print error messages on dmesg, which
> + * we should catch with the kmsg functions. */
> +static void i2c_modeset_vdd_race(void)
> +{
> +	pthread_t i2c_thread, modeset_thread;
> +	void *status;
> +
> +	kmsg_error_reset(kmsg_fd);
> +
> +	stop = false;
> +	pthread_create(&i2c_thread, NULL, i2c_thread_func, NULL);
> +	pthread_create(&modeset_thread, NULL, modeset_thread_func, NULL);
> +
> +	/* This effectively sleeps for 100 seconds, but kills the program in
> +	 * case there's error on dmesg. */
> +	kmsg_error_detect(kmsg_fd, 100 * 1000, "");
> +
> +	stop = true;
> +	pthread_join(i2c_thread, &status);
> +	pthread_join(modeset_thread, &status);
> +
> +	/* Make sure we check everything after the threads have actually
> +	 * stopped. */
> +	kmsg_error_detect(kmsg_fd, 1 * 1000, "");
> +}
> +
> +igt_main
> +{
> +	igt_fixture {
> +		drm_fd = drm_open_any();
> +		igt_require(drm_fd >= 0);
> +
> +		res = drmModeGetResources(drm_fd);
> +		igt_assert(res);
> +
> +		kmsg_fd = kmsg_error_setup();
> +
> +		find_edp_connector();
> +	}
> +
> +	igt_subtest("i2c-modeset-vdd-race")
> +		i2c_modeset_vdd_race();
> +
> +	igt_fixture {
> +		kmsg_error_teardown(kmsg_fd);
> +		drmModeFreeConnector(edp_connector);
> +		drmModeFreeResources(res);
> +		close(drm_fd);
> +	}
> +}
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch



More information about the Intel-gfx mailing list