On Mon, Nov 11, 2013 at 03:06:10PM -0200, Paulo Zanoni wrote: > From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > > 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@xxxxxxxxx> 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@xxxxxxxxx> > + * > + */ > + > +#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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx