2013/11/11 Daniel Vetter <daniel@xxxxxxxx>: > 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 ;-) Then this test will always give a SUCCESS. Not really what I wanted :( > -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 -- Paulo Zanoni _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx