summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/igt_debugfs.c173
-rw-r--r--lib/igt_debugfs.h65
2 files changed, 225 insertions, 13 deletions
diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index 131dccc0..5c029019 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -34,9 +34,54 @@
#include "igt_display.h"
#include "igt_debugfs.h"
+/**
+ * SECTION:igt_debugfs
+ * @short_description: Support code for debugfs features
+ * @title: i-g-t debugfs
+ *
+ * This library provides helpers to access debugfs features. On top of some
+ * basic functions to access debugfs files with e.g. igt_debugfs_open() it also
+ * provides higher-level wrappers for some debugfs features
+ *
+ * # Pipe CRC Support
+ *
+ * This library wraps up the kernel's support for capturing pipe CRCs into a
+ * neat and tidy package. For the datailed usage see all the functions which
+ * work on #igt_pipe_crc_t. This is supported on all platforms and outputs.
+ *
+ * Actually using pipe CRCs to write modeset tests is a bit tricky though, so
+ * there is no way to directly check a CRC: Both the details of the plane
+ * blending, color correction and other hardware and how exactly the CRC is
+ * computed at each tap point vary by hardware generation and are not disclosed.
+ *
+ * The only way to use #igt_crc_t CRCs therefors is to compare CRCs among each
+ * another either for equality or difference. Otherwise CRCs must be treated as
+ * completely opaque values. Note that not even CRCs from different pipes or tap
+ * points on the same platform can be compared. Hence only use igt_crc_is_null()
+ * and igt_crc_equal() to insepct CRC values captured by the same
+ * #igt_pipe_crc_t object.
+ *
+ * # Other debugfs interface wrappers
+ *
+ * This covers the miscellaneous debugfs interface wrappers:
+ *
+ * - drm/i915 supports interfaces to evict certain clases of gem buffer objects,
+ * see igt_drop_caches_set().
+ *
+ * - drm/i915 supports an interface to disable prefaulting, useful to test
+ * slowpaths in ioctls. See igt_disable_prefault().
+ */
+
/*
* General debugfs helpers
*/
+
+/**
+ * igt_debugfs_init:
+ * @debugfs: debugfs access structure to initialize
+ *
+ * Initializes the debugfs access helper library.
+ */
void igt_debugfs_init(igt_debugfs_t *debugfs)
{
const char *path = "/sys/kernel/debug";
@@ -71,6 +116,15 @@ find_minor:
igt_fail(4);
}
+/**
+ * igt_debugfs_open:
+ * @debugfs: debugfs access structure
+ * @filename: name of the debugfs node to open
+ * @mode: mode bits as used by open()
+ *
+ * This opens a debugfs file as a Unix file descriptor. The filename should be
+ * relative to the drm device's root, i.e without "drm/<minor>".
+ */
int igt_debugfs_open(igt_debugfs_t *debugfs, const char *filename, int mode)
{
char buf[1024];
@@ -79,6 +133,15 @@ int igt_debugfs_open(igt_debugfs_t *debugfs, const char *filename, int mode)
return open(buf, mode);
}
+/**
+ * igt_debugfs_fopen:
+ * @debugfs: debugfs access structure
+ * @filename: name of the debugfs node to open
+ * @mode: mode string as used by fopen()
+ *
+ * This opens a debugfs file as a libc FILE. The filename should be
+ * relative to the drm device's root, i.e without "drm/<minor>".
+ */
FILE *igt_debugfs_fopen(igt_debugfs_t *debugfs, const char *filename,
const char *mode)
{
@@ -92,6 +155,13 @@ FILE *igt_debugfs_fopen(igt_debugfs_t *debugfs, const char *filename,
* Pipe CRC
*/
+/**
+ * igt_crc_is_null:
+ * @crc: pipe CRC value to check
+ *
+ * Returns: True if the CRC is null/invalid, false if it represents a captured
+ * valid CRC.
+ */
bool igt_crc_is_null(igt_crc_t *crc)
{
int i;
@@ -103,6 +173,15 @@ bool igt_crc_is_null(igt_crc_t *crc)
return true;
}
+/**
+ * igt_crc_equal:
+ * @a: first pipe CRC value
+ * @b: second pipe CRC value
+ *
+ * Compares two CRC values.
+ *
+ * Returns: Retruns true if the two CRCs match, false otherwise.
+ */
bool igt_crc_equal(igt_crc_t *a, igt_crc_t *b)
{
int i;
@@ -117,6 +196,16 @@ bool igt_crc_equal(igt_crc_t *a, igt_crc_t *b)
return true;
}
+/**
+ * igt_crc_to_string:
+ * @crc: pipe CRC value to print
+ *
+ * This formats @crc into a string buffer which is owned by igt_crc_to_string().
+ * The next call will override the buffer again, which makes this multithreading
+ * unsafe.
+ *
+ * This should only ever be used for diagnostic debug output.
+ */
char *igt_crc_to_string(igt_crc_t *crc)
{
char buf[128];
@@ -205,6 +294,14 @@ static void pipe_crc_exit_handler(int sig)
igt_pipe_crc_reset();
}
+/**
+ * igt_pipe_crc_check:
+ * @debugfs: debugfs access structure
+ *
+ * Convenience helper to check whether pipe CRC capturing is supported by the
+ * kernel. Uses igt_skip to automatically skip the test/subtest if this isn't
+ * the case.
+ */
void igt_pipe_crc_check(igt_debugfs_t *debugfs)
{
const char *cmd = "pipe A none";
@@ -223,6 +320,18 @@ void igt_pipe_crc_check(igt_debugfs_t *debugfs)
fclose(ctl);
}
+/**
+ * igt_pipe_crc_new:
+ * @debugfs: debugfs access structure
+ * @pipe: display pipe to use as source
+ * @source: CRC tap point to use as source
+ *
+ * This sets up a new pipe CRC capture object for the given @pipe and @source.
+ *
+ * Returns: A pipe CRC object if the given @pipe and @source is available, NULL
+ * otherwise. Tests can use this to intelligently skip if they require a
+ * specific pipe CRC source to function properly.
+ */
igt_pipe_crc_t *
igt_pipe_crc_new(igt_debugfs_t *debugfs, enum pipe pipe,
enum intel_pipe_crc_source source)
@@ -258,6 +367,12 @@ igt_pipe_crc_new(igt_debugfs_t *debugfs, enum pipe pipe,
return pipe_crc;
}
+/**
+ * igt_pipe_crc_free:
+ * @pipe_crc: pipe CRC object
+ *
+ * Frees all resources associated with @pipe_crc.
+ */
void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc)
{
if (!pipe_crc)
@@ -268,6 +383,12 @@ void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc)
free(pipe_crc);
}
+/**
+ * igt_pipe_crc_start:
+ * @pipe_crc: pipe CRC object
+ *
+ * Starts the CRC capture process on @pipe_crc.
+ */
void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc)
{
igt_crc_t *crcs = NULL;
@@ -282,6 +403,12 @@ void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc)
free(crcs);
}
+/**
+ * igt_pipe_crc_stop:
+ * @pipe_crc: pipe CRC object
+ *
+ * Stops the CRC capture process on @pipe_crc.
+ */
void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc)
{
char buf[32];
@@ -315,9 +442,18 @@ static bool read_one_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out)
return true;
}
-/*
- * Read @n_crcs from the @pipe_crc. This function blocks until @n_crcs are
- * retrieved.
+/**
+ * igt_pipe_crc_get_crcs:
+ * @pipe_crc: pipe CRC object
+ * @n_crcs: number of CRCs to capture
+ * @out_crcs: buffer pointer for the captured CRC values
+ *
+ * Read @n_crcs from @pipe_crc. This function blocks until @n_crcs are
+ * retrieved. @out_crcs is alloced by this function and must be released with
+ * free() by the caller.
+ *
+ * Callers must start and stop the capturing themselves by calling
+ * igt_pipe_crc_start() and igt_pipe_crc_stop().
*/
void
igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs,
@@ -340,9 +476,13 @@ igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs,
*out_crcs = crcs;
}
-/*
- * Read 1 CRC from @pipe_crc. This function blocks until the CRC is retrieved.
- * @out_crc must be allocated by the caller.
+/**
+ * igt_pipe_crc_collect_crc:
+ * @pipe_crc: pipe CRC object
+ * @out_crc: buffer for the captured CRC values
+ *
+ * Read a single CRC from @pipe_crc. This function blocks until the CRC is
+ * retrieved. @out_crc must be allocated by the caller.
*
* This function takes care of the pipe_crc book-keeping, it will start/stop
* the collection of the CRC.
@@ -358,6 +498,13 @@ void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc)
* Drop caches
*/
+/**
+ * igt_drop_caches_set:
+ * @val: bitmask for DROP_* values
+ *
+ * This calls the debugfs interface the drm/i915 GEM driver exposes to drop or
+ * evict certain classes of gem buffer objects.
+ */
void igt_drop_caches_set(uint64_t val)
{
igt_debugfs_t debugfs;
@@ -406,6 +553,15 @@ static void enable_prefault_at_exit(int sig)
igt_enable_prefault();
}
+/**
+ * igt_disable_prefault:
+ *
+ * Disable prefaulting in certain gem ioctls through the debugfs interface. As
+ * usual this installs an exit handler to clean up and re-enable prefaulting
+ * even when the test exited abnormally.
+ *
+ * igt_enable_prefault() will enable normale operation again.
+ */
void igt_disable_prefault(void)
{
igt_prefault_control(false);
@@ -413,6 +569,11 @@ void igt_disable_prefault(void)
igt_install_exit_handler(enable_prefault_at_exit);
}
+/**
+ * igt_enable_prefault:
+ *
+ * Enable prefault (again) through the debugfs interface.
+ */
void igt_enable_prefault(void)
{
igt_prefault_control(true);
diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
index 04ac2dc5..90e31d70 100644
--- a/lib/igt_debugfs.h
+++ b/lib/igt_debugfs.h
@@ -31,6 +31,11 @@
#include "igt_display.h"
+/**
+ * igt_debugfs_t:
+ *
+ * debugfs access structure. Needs to be initialized with igt_debugfs_init().
+ */
typedef struct {
char root[128];
char dri_path[128];
@@ -45,6 +50,38 @@ FILE *igt_debugfs_fopen(igt_debugfs_t *debugfs, const char *filename,
* Pipe CRC
*/
+/**
+ * igt_pipe_crc_t:
+ *
+ * Pipe CRC support structure. Needs to be allocated and set up with
+ * igt_pipe_crc_new() for a specific pipe and pipe CRC source value.
+ */
+typedef struct _igt_pipe_crc igt_pipe_crc_t;
+
+/**
+ * igt_crc_t:
+ * @frame: frame number of the capture CRC
+ * @n_words: internal field, don't access
+ * @crc: internal field, don't access
+ *
+ * Pipe CRC value. All other members than @frame are private and should not be
+ * inspected by testcases.
+ */
+typedef struct {
+ uint32_t frame;
+ int n_words;
+ uint32_t crc[5];
+} igt_crc_t;
+
+/**
+ * intel_pipe_crc_source:
+ *
+ * Enumeration of all supported pipe CRC sources. Not all platforms and all
+ * outputs support all of them. Generic tests should just use
+ * INTEL_PIPE_CRC_SOURCE_AUTO. It should always map to an end-of-pipe CRC
+ * suitable for checking planes, cursor, color correction and any other
+ * output-agnostic features.
+ */
enum intel_pipe_crc_source {
INTEL_PIPE_CRC_SOURCE_NONE,
INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -59,13 +96,6 @@ enum intel_pipe_crc_source {
INTEL_PIPE_CRC_SOURCE_MAX,
};
-typedef struct _igt_pipe_crc igt_pipe_crc_t;
-typedef struct {
- uint32_t frame;
- int n_words;
- uint32_t crc[5];
-} igt_crc_t;
-
bool igt_crc_is_null(igt_crc_t *crc);
bool igt_crc_equal(igt_crc_t *a, igt_crc_t *b);
char *igt_crc_to_string(igt_crc_t *crc);
@@ -85,9 +115,30 @@ void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc);
* Drop caches
*/
+/**
+ * DROP_UNBOUND:
+ *
+ * Drop all currently unbound gem buffer objects from the cache.
+ */
#define DROP_UNBOUND 0x1
+/**
+ * DROP_BOUND:
+ *
+ * Drop all inactive objects which are bound into some gpu address space.
+ */
#define DROP_BOUND 0x2
+/**
+ * DROP_RETIRE:
+ *
+ * Wait for all outstanding gpu commands to complete, but do not take any
+ * further actions.
+ */
#define DROP_RETIRE 0x4
+/**
+ * DROP_ACTIVE:
+ *
+ * Also drop active objects once retired.
+ */
#define DROP_ACTIVE 0x8
#define DROP_ALL (DROP_UNBOUND | \
DROP_BOUND | \