* [igt-dev] [PATCH i-g-t 2/5] lib/confifs: Add helpers for mounting/unmounting configfs
2023-09-01 9:28 [igt-dev] [PATCH i-g-t 0/4] Add vkms configfs testing Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 1/5] lib/drmtest: Add VKMS as a known driver type Marius Vlad
@ 2023-09-01 9:28 ` Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 3/5] tests/vkms: Add a small library for VKMS testing Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 4/5] tests/vkms: Add more tests for VKMS Marius Vlad
3 siblings, 0 replies; 5+ messages in thread
From: Marius Vlad @ 2023-09-01 9:28 UTC (permalink / raw)
To: igt-dev; +Cc: tzimmermann, yixie, seanpaul, daniel, brpol, igormtorrente
From: Jim Shargo <jshargo@chromium.org>
This change supports the subsequent testing of ConfigFS-based VKMS
features, which require their own mounting.
With this change, we also make is_mountpoint public renamaning to
igt_is_mountpoint and we make use of it.
Signed-off-by: Jim Shargo <jshargo@chromium.org>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
---
lib/igt.h | 2 +-
lib/igt_aux.c | 25 +++++++++++
lib/igt_aux.h | 2 +
lib/igt_configfs.c | 105 +++++++++++++++++++++++++++++++++++++++++++++
lib/igt_configfs.h | 36 ++++++++++++++++
lib/igt_debugfs.c | 29 +------------
lib/meson.build | 1 +
7 files changed, 172 insertions(+), 28 deletions(-)
create mode 100644 lib/igt_configfs.c
create mode 100644 lib/igt_configfs.h
diff --git a/lib/igt.h b/lib/igt.h
index 73b6f7727..6108d9615 100644
--- a/lib/igt.h
+++ b/lib/igt.h
@@ -28,7 +28,7 @@
#include "i915_3d.h"
#include "igt_aux.h"
#include "igt_core.h"
-#include "igt_core.h"
+#include "igt_configfs.h"
#include "igt_debugfs.h"
#include "igt_draw.h"
#include "igt_dummyload.h"
diff --git a/lib/igt_aux.c b/lib/igt_aux.c
index 18edc5ef9..8b38b5a3e 100644
--- a/lib/igt_aux.c
+++ b/lib/igt_aux.c
@@ -2035,6 +2035,31 @@ bool igt_allow_unlimited_files(void)
return setrlimit(RLIMIT_NOFILE, &rlim) == 0;
}
+bool igt_is_mountpoint(const char *path)
+{
+ char buf[strlen(path) + 4];
+ struct stat st;
+ dev_t dev;
+
+ igt_assert_lt(snprintf(buf, sizeof(buf), "%s/.", path), sizeof(buf));
+ if (stat(buf, &st))
+ return false;
+
+ if (!S_ISDIR(st.st_mode))
+ return false;
+
+ dev = st.st_dev;
+
+ igt_assert_lt(snprintf(buf, sizeof(buf), "%s/..", path), sizeof(buf));
+ if (stat(buf, &st))
+ return false;
+
+ if (!S_ISDIR(st.st_mode))
+ return false;
+
+ return dev != st.st_dev;
+}
+
/**
* vfs_file_max: report maximum number of files
*
diff --git a/lib/igt_aux.h b/lib/igt_aux.h
index fb76b0313..298c610f2 100644
--- a/lib/igt_aux.h
+++ b/lib/igt_aux.h
@@ -311,6 +311,8 @@ double igt_stop_siglatency(struct igt_mean *result);
bool igt_allow_unlimited_files(void);
+bool igt_is_mountpoint(const char *path);
+
int igt_is_process_running(const char *comm);
int igt_terminate_process(int sig, const char *comm);
void igt_lsof(const char *dpath);
diff --git a/lib/igt_configfs.c b/lib/igt_configfs.c
new file mode 100644
index 000000000..89acab315
--- /dev/null
+++ b/lib/igt_configfs.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2023 Google LLC.
+ * Copyright 2023 Collabora, Ltd.
+ *
+ * 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.
+ *
+ */
+
+#include "igt_configfs.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+
+#include "igt_aux.h"
+
+/**
+ * SECTION:igt_configfs
+ * @short_description: Support code for configfs features
+ * @title: configfs
+ * @include: igt_configfs.h
+ *
+ * Helper methods for managing configfs.
+ */
+
+static const char *__igt_configfs_mount(void)
+{
+ if (igt_is_mountpoint("/sys/kernel/config"))
+ return "/sys/kernel/config";
+
+ if (igt_is_mountpoint("/config"))
+ return "/config";
+
+ if (mount("config", "/sys/kernel/config", "configfs", 0, 0))
+ return NULL;
+
+ return "/sys/kernel/config";
+}
+
+/**
+ * igt_configfs_mount:
+ *
+ * This searches for configfs in typical locations and will try to mount at
+ * /sys/kernel/config if it can't be found.
+ *
+ * Returns:
+ * The path to the configfs mount point (e.g. /sys/kernel/debug)
+ */
+const char *igt_configfs_mount(void)
+{
+ static const char *path;
+
+ if (!path)
+ path = __igt_configfs_mount();
+
+ return path;
+}
+
+const char *igt_configfs_vkms_mount(void)
+{
+ static char vkms_path[CONFIGFS_VKMS_DIR_SIZE];
+ const char *path = igt_configfs_mount();
+
+ if (!path)
+ return NULL;
+
+ snprintf(vkms_path, sizeof(vkms_path), "%s/%s", path, "vkms");
+
+ igt_debug("VKMS path: %s\n", vkms_path);
+ return vkms_path;
+}
+
+/**
+ * igt_configfs_dir: Open and return the fd of configfs, or -1 on failure.
+ *
+ * Returns:
+ */
+int igt_configfs_dir(void)
+{
+ const char *path = igt_configfs_mount();
+
+ if (!path)
+ return -1;
+
+ igt_debug("Opening configfs directory '%s'\n", path);
+ return open(path, O_RDWR);
+}
diff --git a/lib/igt_configfs.h b/lib/igt_configfs.h
new file mode 100644
index 000000000..238007ab7
--- /dev/null
+++ b/lib/igt_configfs.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 Google LLC.
+ * Copyright 2023 Collabora, Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __IGT_CONFIGFS_H__
+#define __IGT_CONFIGFS_H__
+
+#define CONFIGFS_VKMS_DIR_SIZE 64
+
+const char *igt_configfs_mount(void);
+const char *igt_configfs_vkms_mount(void);
+
+int igt_configfs_dir(void);
+
+#endif /* __IGT_CONFIGFS_H__ */
diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index a7b54bae5..63fc6b9e7 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -67,37 +67,12 @@
* General debugfs helpers
*/
-static bool is_mountpoint(const char *path)
-{
- char buf[strlen(path) + 4];
- struct stat st;
- dev_t dev;
-
- igt_assert_lt(snprintf(buf, sizeof(buf), "%s/.", path), sizeof(buf));
- if (stat(buf, &st))
- return false;
-
- if (!S_ISDIR(st.st_mode))
- return false;
-
- dev = st.st_dev;
-
- igt_assert_lt(snprintf(buf, sizeof(buf), "%s/..", path), sizeof(buf));
- if (stat(buf, &st))
- return false;
-
- if (!S_ISDIR(st.st_mode))
- return false;
-
- return dev != st.st_dev;
-}
-
static const char *__igt_debugfs_mount(void)
{
- if (is_mountpoint("/sys/kernel/debug"))
+ if (igt_is_mountpoint("/sys/kernel/debug"))
return "/sys/kernel/debug";
- if (is_mountpoint("/debug"))
+ if (igt_is_mountpoint("/debug"))
return "/debug";
if (mount("debug", "/sys/kernel/debug", "debugfs", 0, 0))
diff --git a/lib/meson.build b/lib/meson.build
index 21ea9d5ac..d727529f0 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -19,6 +19,7 @@ lib_sources = [
'igt_collection.c',
'igt_color_encoding.c',
'igt_crc.c',
+ 'igt_configfs.c',
'igt_debugfs.c',
'igt_device.c',
'igt_device_scan.c',
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [igt-dev] [PATCH i-g-t 3/5] tests/vkms: Add a small library for VKMS testing
2023-09-01 9:28 [igt-dev] [PATCH i-g-t 0/4] Add vkms configfs testing Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 1/5] lib/drmtest: Add VKMS as a known driver type Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 2/5] lib/confifs: Add helpers for mounting/unmounting configfs Marius Vlad
@ 2023-09-01 9:28 ` Marius Vlad
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 4/5] tests/vkms: Add more tests for VKMS Marius Vlad
3 siblings, 0 replies; 5+ messages in thread
From: Marius Vlad @ 2023-09-01 9:28 UTC (permalink / raw)
To: igt-dev; +Cc: tzimmermann, yixie, seanpaul, daniel, brpol, igormtorrente
From: Jim Shargo <jshargo@chromium.org>
And with it, this adds a basic test that makes use of it,
creating a device and with it a pipeline.
One should create a vkms device, add pipeline elements, like encoders,
crtc, and connectors, compose the pipeline by attaching each element
using the _attach_ functions, set the connector as connected and
finally, enable the vkms device.
This works in-tandem with the vkms driver which requires to enable the
device and set the connector as connected.
Signed-off-by: Jim Shargo <jshargo@chromium.org>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
---
lib/igt.h | 1 +
lib/igt_vkms.c | 532 +++++++++++++++++++++++++++++++++++++
lib/igt_vkms.h | 66 +++++
lib/meson.build | 1 +
tests/meson.build | 13 +
tests/vkms/vkms_configfs.c | 83 ++++++
6 files changed, 696 insertions(+)
create mode 100644 lib/igt_vkms.c
create mode 100644 lib/igt_vkms.h
create mode 100644 tests/vkms/vkms_configfs.c
diff --git a/lib/igt.h b/lib/igt.h
index 6108d9615..d3771c1f1 100644
--- a/lib/igt.h
+++ b/lib/igt.h
@@ -41,6 +41,7 @@
#include "igt_pm.h"
#include "igt_stats.h"
#include "igt_dsc.h"
+#include "igt_vkms.h"
#ifdef HAVE_CHAMELIUM
#include "igt_alsa.h"
#include "igt_audio.h"
diff --git a/lib/igt_vkms.c b/lib/igt_vkms.c
new file mode 100644
index 000000000..7ae8dde55
--- /dev/null
+++ b/lib/igt_vkms.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright 2023 Google LLC.
+ * Copyright 2023 Collabora, Ltd.
+ *
+ * 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.
+ *
+ */
+
+#include "igt_vkms.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <ftw.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "drmtest.h"
+#include "igt_configfs.h"
+#include "igt_core.h"
+
+/**
+ * SECTION:igt_vkms
+ * @short_description: Library with creating and dynamically configure a vkms device
+ * @title: vkms
+ * @include: igt_vkms.h
+ *
+ * This library contains helpers for creating a vkms device and configuring it
+ * dynamically.
+ *
+ * One should create a vkms device, add pipeline elements, like encoders, crtc,
+ * and connectors, compose the pipeline by attaching each element using the
+ * _attach_ functions, set the connector as connected and finally, enable the
+ * vkms device.
+ */
+
+
+static void create_device_from_directory(igt_vkms_t *device, const char *name)
+{
+ const char *vkms_root = igt_configfs_vkms_mount();
+ memset(device, 0, sizeof(*device));
+
+ snprintf(device->name, sizeof(device->name), "%s", name);
+ snprintf(device->device_dir, sizeof(device->device_dir), "%s/%s", vkms_root, name);
+}
+
+/**
+ * igt_vkms_destroy_all_devices:
+ *
+ * Iterates over all directories found in the ConfigFS mountpoint and calls
+ * igt_vkms_device_destroy, which cleans up any previous directories,
+ * symlinks and objects.
+ */
+void igt_vkms_destroy_all_devices(void)
+{
+ const char *vkms_root = igt_configfs_vkms_mount();
+ igt_vkms_t device = { 0 };
+ DIR *dir;
+ struct dirent *ent;
+ int ret = 0;
+
+ if (!vkms_root) {
+ igt_warn("Unable to find VKMS configfs directory.\n");
+ return;
+ }
+
+ dir = opendir(vkms_root);
+ if (!dir) {
+ igt_warn("Unable to open VKMS configfs directory '%s'. "
+ "Got errno=%d (%s)\n", vkms_root, errno, strerror(errno));
+ return;
+ }
+
+ while ((ent = readdir(dir)) != NULL) {
+ if (strcmp(ent->d_name, ".") == 0 ||
+ strcmp(ent->d_name, "..") == 0)
+ continue;
+
+ create_device_from_directory(&device, ent->d_name);
+ igt_vkms_device_destroy(&device);
+ if (ret)
+ igt_warn("Unable to reset device '%s/%s'\n", vkms_root,
+ ent->d_name);
+ }
+
+ closedir(dir);
+}
+
+/**
+ * igt_vkms_device_create:
+ * @device: a statically allocated object that denotes a vkms device
+ * @name: a string that signifies the vkms device to be created
+ *
+ * This creates a directory in the ConfigFS root mountpoint directory, where
+ * the entire pipeline will be configured.
+ */
+void igt_vkms_device_create(igt_vkms_t *device, const char *name)
+{
+ const char *vkms_root = igt_configfs_vkms_mount();
+ DIR *dir;
+ int ret;
+
+ igt_assert_f(vkms_root, "Unable to find VKMS root '%s'.\n", name);
+
+ dir = opendir(vkms_root);
+ igt_assert_f(dir, "VKMS configfs directory not available at '%s'. "
+ "Got errno=%d (%s)\n", vkms_root, errno, strerror(errno));
+ if (dir)
+ closedir(dir);
+
+ create_device_from_directory(device, name);
+
+ igt_debug("mkdir'ing VKMS device at '%s'\n", device->device_dir);
+
+ ret = mkdir(device->device_dir, 0777);
+ igt_assert_f(ret == 0,
+ "Unable to mkdir device directory '%s'. Got errno=%d (%s)\n",
+ device->device_dir, errno, strerror(errno));
+}
+
+static int igt_vkms_unlink_symlinks(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ if (typeflag != FTW_SL)
+ return 0;
+
+ if (unlink(fpath)) {
+ igt_warn("Unable to unlink vkms object: '%s'. "
+ "Got errno=%d (%s)\n", fpath, errno, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int igt_vkms_delete_objects(const char *fpath, const struct stat *sb,
+ int typeflag, struct FTW *ftwbuf)
+{
+ char *dirbase;
+ char path_buf[VKMS_CARD_OBJECT_DIR_SIZE];
+
+ memset(path_buf, 0x0, sizeof(path_buf));
+ snprintf(path_buf, sizeof(path_buf), "%s", fpath);
+ dirbase = basename(dirname(path_buf));
+
+ if (strcmp(dirbase, "planes") != 0 &&
+ strcmp(dirbase, "encoders") != 0 &&
+ strcmp(dirbase, "connectors") != 0 &&
+ strcmp(dirbase, "crtcs") != 0) {
+ return 0;
+ }
+
+ if (rmdir(fpath)) {
+ igt_warn("Unable to rmdir vkms object: '%s'. Got errno=%d (%s)\n",
+ fpath, errno, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * igt_vkms_device_destroy:
+ * @device: the vkms device in question
+ *
+ * Removes any possible symlinks, objects and directories, and clears the
+ * device for later usage.
+ *
+ * Users can then create a new vkms device with igt_vkms_device_create().
+ */
+void igt_vkms_device_destroy(igt_vkms_t *device)
+{
+ int ret = 0;
+
+ igt_debug("Destroying device %s\n", device->device_dir);
+
+ /* Some notes on device destruction:
+ * - FTW_PHYS keeps us from following symlinks
+ * - FTW_DEPTH does a DFS of the tree, which lets us delete
+ * bottom-up.
+ */
+ ret = nftw(device->device_dir, &igt_vkms_unlink_symlinks,
+ /* nopenfd= */ 16, FTW_PHYS | FTW_DEPTH);
+ igt_assert_f(ret == 0,
+ "Unable to remove symlinks for device directory '%s'\n",
+ device->device_dir);
+
+ ret = nftw(device->device_dir, &igt_vkms_delete_objects,
+ /* nopenfd= */ 16, FTW_PHYS | FTW_DEPTH);
+ igt_assert_f(ret == 0,
+ "Unable to remove objects for device directory '%s'\n",
+ device->device_dir);
+
+ ret = rmdir(device->device_dir);
+ igt_assert_f(ret == 0,
+ "Unable to rmdir device directory '%s'. Got errno=%d (%s)\n",
+ device->device_dir, errno, strerror(errno));
+
+ memset(device, 0, sizeof(*device));
+}
+
+/**
+ * igt_vkms_device_add_plane:
+ * @device: the device in question
+ * @name: the name of the plane, as a string
+ * @type: the type of the HW plane, as an integer, one of DRM_PLANE_TYPE_PRIMARY,
+ * DRM_PLANE_TYPE_OVERLAY or DRM_PLANE_TYPE_CURSOR.
+ *
+ * mkdirs and creates a plane using the provided name and the type.
+ */
+void igt_vkms_device_add_plane(igt_vkms_t *device, const char *name, int type)
+{
+ char path[VKMS_CARD_OBJECT_DIR_SIZE];
+ char writebuf[2];
+ int fd, ret;
+
+ memset(path, 0x0, sizeof(path));
+ snprintf(path, sizeof(path), "%s/planes/%s", device->device_dir, name);
+
+ ret = mkdir(path, 0777);
+ igt_assert_f(ret == 0,
+ "Failed to mkdir VKMS plane '%s'. Got errno=%d (%s)\n",
+ path, errno, strerror(errno));
+
+ strcat(path, "/type");
+ fd = open(path, O_WRONLY);
+ igt_assert_f(fd > 0,
+ "Failed to open plane type for writing '%s'. Got errno=%d (%s)\n",
+ path, errno, strerror(errno));
+
+ snprintf(writebuf, 2, "%d", type);
+ write(fd, writebuf, 1);
+ close(fd);
+}
+
+/**
+ * igt_vkms_device_add_connector:
+ * @device: the device in question
+ * @name: the name of the connector, as a string
+ *
+ * mkdirs and creates a connector using the provided name.
+ *
+ */
+void igt_vkms_device_add_connector(igt_vkms_t *device, const char *name)
+{
+ char path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(path, 0x0, sizeof(path));
+ snprintf(path, sizeof(path), "%s/connectors/%s", device->device_dir, name);
+
+ ret = mkdir(path, 0777);
+ igt_assert_f(ret == 0,
+ "Failed to mkdir VKMS plane '%s'. Got errno=%d (%s)\n",
+ path, errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_device_add_encoder:
+ * @device: the device in question
+ * @name: the name of the encoder, as a string
+ *
+ * mkdirs and creates an encoder using the provided name.
+ */
+void igt_vkms_device_add_encoder(igt_vkms_t *device, const char *name)
+{
+ char path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(path, 0x0, sizeof(path));
+ snprintf(path, sizeof(path), "%s/encoders/%s", device->device_dir, name);
+
+ ret = mkdir(path, 0777);
+ igt_assert_f(ret == 0,
+ "Failed to mkdir VKMS encoder '%s'. Got errno=%d (%s)\n",
+ path, errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_device_add_crtc:
+ * @device: the device in question
+ * @name: the name of the crtc, as a string
+ *
+ * mkdirs and creates a crtc using the provided name.
+ */
+void igt_vkms_device_add_crtc(igt_vkms_t *device, const char *name)
+{
+ char path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(path, 0x0, sizeof(path));
+ snprintf(path, sizeof(path), "%s/crtcs/%s", device->device_dir, name);
+
+ ret = mkdir(path, 0777);
+ igt_assert_f(ret == 0,
+ "Failed to mkdir VKMS crtc '%s'. Got errno=%d (%s)\n",
+ path, errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_device_attach_plane_to_crtc:
+ * @device: the vkms device in question
+ * @plane_name: the plane name, as a string
+ * @crtc_name: the crtc name, as a string
+ *
+ * This function symlinks the crtc, as pointed by crtc_name to the planes
+ * possible_crtcs directory.
+ */
+void igt_vkms_device_attach_plane_to_crtc(igt_vkms_t *device, const char *plane_name,
+ const char *crtc_name)
+{
+ char plane_crtcs_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ char crtc_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(crtc_path, 0x0, sizeof(crtc_path));
+ memset(plane_crtcs_path, 0x0, sizeof(plane_crtcs_path));
+
+ snprintf(plane_crtcs_path, sizeof(plane_crtcs_path),
+ "%s/planes/%s/possible_crtcs/%s",
+ device->device_dir, plane_name, crtc_name);
+ snprintf(crtc_path, sizeof(crtc_path), "%s/crtcs/%s",
+ device->device_dir, crtc_name);
+
+ ret = symlink(crtc_path, plane_crtcs_path);
+ igt_assert_f(ret == 0,
+ "Failed to symlink VKMS crtc '%s' to plane '%s'. Got errno=%d (%s)\n",
+ crtc_name, plane_name, errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_device_attach_crtc_to_encoder:
+ * @device: the vkms device in question
+ * @encoder_name: the encoder name, as a string
+ * @crtc_name: the crtc name, as a string
+ *
+ * This function symlinks the crtc, as pointed by crtc_name to the encoders
+ * possible_crtcs directory.
+ */
+void igt_vkms_device_attach_crtc_to_encoder(igt_vkms_t *device, const char *encoder_name,
+ const char *crtc_name)
+{
+ char encoder_crtcs_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ char crtc_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(crtc_path, 0x0, sizeof(crtc_path));
+ memset(encoder_crtcs_path, 0x0, sizeof(encoder_crtcs_path));
+
+ snprintf(encoder_crtcs_path, sizeof(encoder_crtcs_path),
+ "%s/encoders/%s/possible_crtcs/%s", device->device_dir,
+ encoder_name, crtc_name);
+ snprintf(crtc_path, sizeof(crtc_path), "%s/crtcs/%s",
+ device->device_dir, crtc_name);
+
+ ret = symlink(crtc_path, encoder_crtcs_path);
+ igt_assert_f(ret == 0,
+ "Failed to symlink VKMS crtc '%s' to encoder '%s'. Got errno=%d (%s)\n",
+ crtc_name, encoder_name, errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_device_attach_encoder_to_connector:
+ * @device: the vkms device in question
+ * @connector_name: the connector name, as a string
+ * @encoder_name: the encoder name, as a string
+ *
+ * This function symlinks the encoder, pointed by encoder_name to the
+ * connectors possible_encoders directory.
+ */
+void igt_vkms_device_attach_encoder_to_connector(igt_vkms_t *device,
+ const char *connector_name,
+ const char *encoder_name)
+{
+ char connector_encoders_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ char encoder_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int ret;
+
+ memset(encoder_path, 0x0, sizeof(encoder_path));
+ memset(connector_encoders_path, 0x0, sizeof(connector_encoders_path));
+
+ snprintf(connector_encoders_path, sizeof(connector_encoders_path),
+ "%s/connectors/%s/possible_encoders/%s", device->device_dir,
+ connector_name, encoder_name);
+ snprintf(encoder_path, sizeof(encoder_path), "%s/encoders/%s",
+ device->device_dir, encoder_name);
+
+ ret = symlink(encoder_path, connector_encoders_path);
+ igt_assert_f(ret == 0,
+ "Failed to symlink VKMS encoder '%s' to connector '%s'. "
+ "Got errno=%d (%s)\n", encoder_name, connector_name,
+ errno, strerror(errno));
+}
+
+/**
+ * igt_vkms_enable:
+ * @device: the vkms device in question
+ *
+ * This would enable the vkms device after setting up the pipeline. Use this
+ * function after you've set up the entire pipeline to probe and add the vkms
+ * device.
+ *
+ */
+void igt_vkms_enable(igt_vkms_t *device)
+{
+ char enabled_file[VKMS_CARD_OBJECT_DIR_SIZE];
+ int fd, ret;
+
+ memset(enabled_file, 0x0, sizeof(enabled_file));
+ snprintf(enabled_file, sizeof(enabled_file),
+ "%s/enabled", device->device_dir);
+
+ fd = open(enabled_file, O_WRONLY);
+ igt_assert_f(fd > 0, "Unable to open '%s'\n", enabled_file);
+
+ ret = write(fd, "1", 1);
+ igt_assert_f(ret >= 0, "Unable to write '%s'. Got errno=%d (%s)\n",
+ enabled_file, errno, strerror(errno));
+
+ ret = close(fd);
+ igt_assert_eq(ret, 0);
+}
+
+/**
+ * igt_vkms_connector_connect:
+ * @device: the vkms device in question
+ * @connector_name: the connector name, as a string
+ *
+ * By default the connector will be created as disconnected so you'd need to
+ * mark the connector as connected. This will generate connected hot-plug
+ * event.
+ *
+ * You can either call this before enabling the vkms device, or after.
+ */
+void igt_vkms_connector_connect(igt_vkms_t *device, const char *connector_name)
+{
+ char connector_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int fd, ret;
+
+ memset(connector_path, 0x0, sizeof(connector_path));
+ snprintf(connector_path, sizeof(connector_path),
+ "%s/connectors/%s/connected", device->device_dir, connector_name);
+
+ fd = open(connector_path, O_WRONLY);
+ igt_assert_f(fd > 0, "Unable to open '%s'\n", connector_path);
+
+ ret = write(fd, "1", 1);
+ igt_assert_f(ret >= 0, "Unable to write '%s'. Got errno=%d (%s)\n",
+ connector_path, errno, strerror(errno));
+
+ ret = close(fd);
+ igt_assert_eq(ret, 0);
+}
+
+/**
+ * igt_vkms_connector_disconnect:
+ * @device: the vkms device in question
+ * @connector_name: the connector name as a string
+ *
+ * Mark the connector, pointed by @connector_name as disconnected.
+ * This will generate a disconnected hot-plug event.
+ */
+void igt_vkms_connector_disconnect(igt_vkms_t *device, const char *connector_name)
+{
+ char connector_path[VKMS_CARD_OBJECT_DIR_SIZE];
+ int fd, ret;
+
+ memset(connector_path, 0x0, sizeof(connector_path));
+ snprintf(connector_path, sizeof(connector_path),
+ "%s/connectors/%s/connected", device->device_dir, connector_name);
+
+ fd = open(connector_path, O_WRONLY);
+ igt_assert_f(fd > 0, "Unable to open '%s'\n", connector_path);
+
+ ret = write(fd, "1", 1);
+ igt_assert_f(ret >= 0, "Unable to write '%s'. Got errno=%d (%s)\n",
+ connector_path, errno, strerror(errno));
+
+ ret = close(fd);
+ igt_assert_eq(ret, 0);
+}
+
+/**
+ * igt_vkms_is_enabled:
+ * @device:
+ *
+ * This checks out if the device has been indeed enabled by checking that
+ * underlying file has the value of '1'.
+ *
+ * Returns true if the device has been enabled, or false otherwise.
+ */
+bool igt_vkms_is_enabled(igt_vkms_t *device)
+{
+ char registration_file[VKMS_CARD_OBJECT_DIR_SIZE];
+ char is_enabled[2];
+ int fd, ret = 0;
+
+ memset(registration_file, 0x0, sizeof(registration_file));
+ snprintf(registration_file, sizeof(registration_file),
+ "%s/enabled", device->device_dir);
+
+ fd = open(registration_file, O_RDONLY);
+ igt_assert_f(fd > 0, "Unable to open '%s'\n",
+ registration_file);
+
+ ret = read(fd, is_enabled, sizeof(is_enabled));
+ igt_assert_eq(0, close(fd));
+ if (ret < 0) {
+ return false;
+ }
+
+ return strncmp("1", is_enabled, sizeof(char)) == 0;
+}
diff --git a/lib/igt_vkms.h b/lib/igt_vkms.h
new file mode 100644
index 000000000..174039ca0
--- /dev/null
+++ b/lib/igt_vkms.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023 Google LLC.
+ * Copyright 2023 Collabora, Ltd.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __IGT_VKMS_H__
+#define __IGT_VKMS_H__
+
+#include <stdbool.h>
+#include <limits.h>
+
+#define VKMS_CARD_NAME_SIZE (PATH_MAX / 4)
+#define VKMS_CARD_DIR_SIZE (PATH_MAX / 2)
+#define VKMS_CARD_OBJECT_DIR_SIZE PATH_MAX
+
+
+void igt_vkms_destroy_all_devices(void);
+
+typedef struct igt_vkms {
+ char name[VKMS_CARD_NAME_SIZE];
+ char device_dir[VKMS_CARD_DIR_SIZE];
+} igt_vkms_t;
+
+void igt_vkms_device_create(igt_vkms_t *device, const char *name);
+void igt_vkms_device_destroy(igt_vkms_t *device);
+
+void igt_vkms_device_add_plane(igt_vkms_t *device, const char *name, int type);
+void igt_vkms_device_add_connector(igt_vkms_t *device, const char *name);
+void igt_vkms_device_add_encoder(igt_vkms_t *device, const char *name);
+void igt_vkms_device_add_crtc(igt_vkms_t *device, const char *name);
+
+void igt_vkms_device_attach_plane_to_crtc(igt_vkms_t *device, const char *plane_name,
+ const char *crtc_name);
+void igt_vkms_device_attach_crtc_to_encoder(igt_vkms_t *device,
+ const char *encoder_name,
+ const char *crtc_name);
+void igt_vkms_device_attach_encoder_to_connector(igt_vkms_t *device,
+ const char *connector_name,
+ const char *encoder_name);
+
+void igt_vkms_enable(igt_vkms_t *device);
+void igt_vkms_connector_connect(igt_vkms_t *device, const char *connector_name);
+void igt_vkms_connector_disconnect(igt_vkms_t *device, const char *connector_name);
+bool igt_vkms_is_enabled(igt_vkms_t *device);
+
+#endif /* __IGT_VKMS_H__ */
diff --git a/lib/meson.build b/lib/meson.build
index d727529f0..600bbcc0c 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -20,6 +20,7 @@ lib_sources = [
'igt_color_encoding.c',
'igt_crc.c',
'igt_configfs.c',
+ 'igt_vkms.c',
'igt_debugfs.c',
'igt_device.c',
'igt_device_scan.c',
diff --git a/tests/meson.build b/tests/meson.build
index c683e468d..db1545fe0 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -316,6 +316,10 @@ chamelium_progs = [
'kms_chamelium_hpd',
]
+vkms_progs = [
+ 'vkms_configfs',
+]
+
test_deps = [ igt_deps ]
if libdrm_nouveau.found()
@@ -459,6 +463,15 @@ if chamelium.found()
output : name + '.testlist')
endif
+foreach prog : vkms_progs
+ test_executables += executable(prog, join_paths('vkms', prog + '.c'),
+ dependencies : test_deps,
+ install_dir : libexecdir,
+ install_rpath : libexecdir_rpathdir,
+ install : true)
+ test_list += prog
+endforeach
+
subdir('amdgpu')
subdir('v3d')
diff --git a/tests/vkms/vkms_configfs.c b/tests/vkms/vkms_configfs.c
new file mode 100644
index 000000000..974753318
--- /dev/null
+++ b/tests/vkms/vkms_configfs.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 Google LLC.
+ * Copyright 2023 Collabora, Ltd.
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <xf86drmMode.h>
+
+#include "drmtest.h"
+#include "igt.h"
+#include "igt_configfs.h"
+#include "igt_core.h"
+#include "igt_vkms.h"
+
+IGT_TEST_DESCRIPTION("Basic tests for VKMS, including configfs support");
+
+static void vkms_basic_test(igt_vkms_t *device)
+{
+ igt_warn("Path: %s\n", device->device_dir);
+
+ igt_vkms_device_add_plane(device, "primary", DRM_PLANE_TYPE_PRIMARY);
+ igt_vkms_device_add_crtc(device, "crtc");
+ igt_vkms_device_add_encoder(device, "encoder");
+ igt_vkms_device_add_connector(device, "connector");
+ igt_vkms_connector_connect(device, "connector");
+
+ igt_vkms_device_attach_plane_to_crtc(device, "primary", "crtc");
+ igt_vkms_device_attach_encoder_to_connector(device, "connector", "encoder");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder", "crtc");
+
+ igt_vkms_enable(device);
+ igt_assert(igt_vkms_is_enabled(device));
+}
+
+
+igt_main
+{
+ igt_vkms_t device;
+
+ /* By clearing out all existing devices, we don't end up with confusing
+ * name collision errors. */
+ igt_fixture
+ {
+ igt_require_vkms();
+ igt_vkms_destroy_all_devices();
+ }
+
+ igt_describe("Can create a minimal device.");
+ igt_subtest("basic_device")
+ {
+ igt_vkms_device_create(&device, "basic-device");
+ vkms_basic_test(&device);
+ igt_vkms_device_destroy(&device);
+ }
+
+ igt_fixture
+ {
+ igt_require_vkms();
+ /* avoid potential dangling directories/objects if some of the
+ * tests failed */
+ if (strcmp(device.name, ""))
+ igt_vkms_device_destroy(&device);
+ }
+}
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [igt-dev] [PATCH i-g-t 4/5] tests/vkms: Add more tests for VKMS
2023-09-01 9:28 [igt-dev] [PATCH i-g-t 0/4] Add vkms configfs testing Marius Vlad
` (2 preceding siblings ...)
2023-09-01 9:28 ` [igt-dev] [PATCH i-g-t 3/5] tests/vkms: Add a small library for VKMS testing Marius Vlad
@ 2023-09-01 9:28 ` Marius Vlad
3 siblings, 0 replies; 5+ messages in thread
From: Marius Vlad @ 2023-09-01 9:28 UTC (permalink / raw)
To: igt-dev; +Cc: tzimmermann, yixie, seanpaul, daniel, brpol, igormtorrente
From: Jim Shargo <jshargo@chromium.org>
This adds four more tests, one that should fail when no primary plane
is created and added to the pipeline, one that creates a device with
multiple overlay and cursor planes, another one that create two outputs,
and tests that disable works.
Signed-off-by: Jim Shargo <jshargo@chromium.org>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
---
lib/igt_vkms.c | 27 ++++++++
lib/igt_vkms.h | 1 +
tests/vkms/vkms_configfs.c | 132 +++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+)
diff --git a/lib/igt_vkms.c b/lib/igt_vkms.c
index 7ae8dde55..1128a9328 100644
--- a/lib/igt_vkms.c
+++ b/lib/igt_vkms.c
@@ -440,6 +440,33 @@ void igt_vkms_enable(igt_vkms_t *device)
igt_assert_eq(ret, 0);
}
+/**
+ * igt_vkms_disable:
+ * @device: the vkms device in question
+ *
+ * This would disable the vkms device.
+ *
+ */
+void igt_vkms_disable(igt_vkms_t *device)
+{
+ char enabled_file[VKMS_CARD_OBJECT_DIR_SIZE];
+ int fd, ret;
+
+ memset(enabled_file, 0x0, sizeof(enabled_file));
+ snprintf(enabled_file, sizeof(enabled_file),
+ "%s/enabled", device->device_dir);
+
+ fd = open(enabled_file, O_WRONLY);
+ igt_assert_f(fd > 0, "Unable to open '%s'\n", enabled_file);
+
+ ret = write(fd, "0", 1);
+ igt_assert_f(ret >= 0, "Unable to write '%s'. Got errno=%d (%s)\n",
+ enabled_file, errno, strerror(errno));
+
+ ret = close(fd);
+ igt_assert_eq(ret, 0);
+}
+
/**
* igt_vkms_connector_connect:
* @device: the vkms device in question
diff --git a/lib/igt_vkms.h b/lib/igt_vkms.h
index 174039ca0..48bdb063f 100644
--- a/lib/igt_vkms.h
+++ b/lib/igt_vkms.h
@@ -59,6 +59,7 @@ void igt_vkms_device_attach_encoder_to_connector(igt_vkms_t *device,
const char *encoder_name);
void igt_vkms_enable(igt_vkms_t *device);
+void igt_vkms_disable(igt_vkms_t *device);
void igt_vkms_connector_connect(igt_vkms_t *device, const char *connector_name);
void igt_vkms_connector_disconnect(igt_vkms_t *device, const char *connector_name);
bool igt_vkms_is_enabled(igt_vkms_t *device);
diff --git a/tests/vkms/vkms_configfs.c b/tests/vkms/vkms_configfs.c
index 974753318..1d3fa2ec1 100644
--- a/tests/vkms/vkms_configfs.c
+++ b/tests/vkms/vkms_configfs.c
@@ -51,6 +51,105 @@ static void vkms_basic_test(igt_vkms_t *device)
igt_assert(igt_vkms_is_enabled(device));
}
+static void vkms_crtc_no_primary_test(igt_vkms_t *device)
+{
+ igt_vkms_device_add_crtc(device, "crtc");
+ igt_vkms_device_add_encoder(device, "encoder");
+ igt_vkms_device_add_connector(device, "connector");
+ igt_vkms_connector_connect(device, "connector");
+
+ igt_vkms_device_attach_encoder_to_connector(device, "connector", "encoder");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder", "crtc");
+
+ igt_vkms_enable(device);
+ igt_assert(!igt_vkms_is_enabled(device));
+}
+
+static void vkms_multiple_overlays_test(igt_vkms_t *device)
+{
+ igt_vkms_device_add_plane(device, "primary", DRM_PLANE_TYPE_PRIMARY);
+ igt_vkms_device_add_plane(device, "cursor", DRM_PLANE_TYPE_CURSOR);
+ igt_vkms_device_add_plane(device, "overlay0", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay1", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay2", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay3", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_crtc(device, "crtc");
+ igt_vkms_device_add_encoder(device, "encoder");
+ igt_vkms_device_add_connector(device, "connector");
+ igt_vkms_connector_connect(device, "connector");
+
+ igt_vkms_device_attach_plane_to_crtc(device, "primary", "crtc");
+ igt_vkms_device_attach_plane_to_crtc(device, "cursor", "crtc");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay0", "crtc");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay1", "crtc");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay2", "crtc");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay3", "crtc");
+ igt_vkms_device_attach_encoder_to_connector(device, "connector", "encoder");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder", "crtc");
+
+ igt_vkms_enable(device);
+ igt_assert(igt_vkms_is_enabled(device));
+}
+
+static void vkms_multiple_displays_test(igt_vkms_t *device)
+{
+ igt_vkms_device_add_plane(device, "primary0", DRM_PLANE_TYPE_PRIMARY);
+ igt_vkms_device_add_plane(device, "primary1", DRM_PLANE_TYPE_PRIMARY);
+ igt_vkms_device_add_plane(device, "cursor0", DRM_PLANE_TYPE_CURSOR);
+ igt_vkms_device_add_plane(device, "cursor1", DRM_PLANE_TYPE_CURSOR);
+ igt_vkms_device_add_plane(device, "overlay0", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay1", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay2", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_plane(device, "overlay3", DRM_PLANE_TYPE_OVERLAY);
+ igt_vkms_device_add_crtc(device, "crtc0");
+ igt_vkms_device_add_crtc(device, "crtc1");
+ igt_vkms_device_add_encoder(device, "encoder0");
+ igt_vkms_device_add_encoder(device, "encoder1");
+ igt_vkms_device_add_connector(device, "connector0");
+ igt_vkms_connector_connect(device, "connector0");
+ igt_vkms_device_add_connector(device, "connector1");
+ igt_vkms_connector_connect(device, "connector1");
+
+ igt_vkms_device_attach_plane_to_crtc(device, "primary0", "crtc0");
+ igt_vkms_device_attach_plane_to_crtc(device, "cursor0", "crtc0");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay0", "crtc0");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay1", "crtc0");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay2", "crtc0");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay3", "crtc0");
+ igt_vkms_device_attach_encoder_to_connector(device, "connector0", "encoder0");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder0", "crtc0");
+
+ igt_vkms_device_attach_plane_to_crtc(device, "primary1", "crtc1");
+ igt_vkms_device_attach_plane_to_crtc(device, "cursor1", "crtc1");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay0", "crtc1");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay1", "crtc1");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay2", "crtc1");
+ igt_vkms_device_attach_plane_to_crtc(device, "overlay3", "crtc1");
+ igt_vkms_device_attach_encoder_to_connector(device, "connector1", "encoder1");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder1", "crtc1");
+
+ igt_vkms_enable(device);
+ igt_assert(igt_vkms_is_enabled(device));
+}
+
+static void disable_device(igt_vkms_t *device)
+{
+ igt_vkms_device_add_plane(device, "primary", DRM_PLANE_TYPE_PRIMARY);
+ igt_vkms_device_add_crtc(device, "crtc");
+ igt_vkms_device_add_encoder(device, "encoder");
+ igt_vkms_device_add_connector(device, "connector");
+ igt_vkms_connector_connect(device, "connector");
+
+ igt_vkms_device_attach_plane_to_crtc(device, "primary", "crtc");
+ igt_vkms_device_attach_encoder_to_connector(device, "connector", "encoder");
+ igt_vkms_device_attach_crtc_to_encoder(device, "encoder", "crtc");
+
+ igt_vkms_enable(device);
+ igt_assert(igt_vkms_is_enabled(device));
+
+ igt_vkms_disable(device);
+ igt_assert(!igt_vkms_is_enabled(device));
+}
igt_main
{
@@ -72,6 +171,39 @@ igt_main
igt_vkms_device_destroy(&device);
}
+ igt_describe("Registering a CRTC with no primary fails");
+ igt_subtest("no_primary")
+ {
+ igt_vkms_device_create(&device, "no-primary");
+ vkms_crtc_no_primary_test(&device);
+ igt_vkms_device_destroy(&device);
+ }
+
+
+ igt_describe("Can create a device with multiple overlays");
+ igt_subtest("multiple_overlays_device")
+ {
+ igt_vkms_device_create(&device, "multiple-overlays-device");
+ vkms_multiple_overlays_test(&device);
+ igt_vkms_device_destroy(&device);
+ }
+
+ igt_describe("Can create a device with multiple displays");
+ igt_subtest("multiple_displays_device")
+ {
+ igt_vkms_device_create(&device, "multiple-displays-device");
+ vkms_multiple_displays_test(&device);
+ igt_vkms_device_destroy(&device);
+ }
+
+ igt_describe("Disable the device");
+ igt_subtest("disable_device")
+ {
+ igt_vkms_device_create(&device, "device-disable");
+ disable_device(&device);
+ igt_vkms_device_destroy(&device);
+ }
+
igt_fixture
{
igt_require_vkms();
--
2.40.1
^ permalink raw reply related [flat|nested] 5+ messages in thread