[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