blob: 2fd460d5ed2b270f6392480fd97da7bccecdfad6 [file] [log] [blame]
/*
* Copyright © 2017 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.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <i915_drm.h>
#include "igt_core.h"
#include "igt_gt.h"
#include "igt_sysfs.h"
#include "intel_chipset.h"
#include "intel_reg.h"
#include "ioctl_wrappers.h"
#include "i915/gem_submission.h"
/**
* SECTION:gem_submission
* @short_description: Helpers for determining submission method
* @title: GEM Submission
*
* This helper library contains functions used for getting information on
* currently used hardware submission method. Different generations of hardware
* support different submission backends, currently we're distinguishing 3
* different methods: legacy ringbuffer submission, execlists, GuC submission.
* For legacy ringbuffer submission, there's also a variation where we're using
* semaphores for synchronization between engines.
*/
static bool has_semaphores(int fd, int dir)
{
int val = 0;
struct drm_i915_getparam gp = {
gp.param = I915_PARAM_HAS_SEMAPHORES,
gp.value = &val,
};
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) < 0)
val = igt_sysfs_get_boolean(dir, "semaphores");
return val;
}
/**
* gem_submission_method:
* @fd: open i915 drm file descriptor
*
* Returns: Submission method bitmap.
*/
unsigned gem_submission_method(int fd)
{
const int gen = intel_gen(intel_get_drm_devid(fd));
unsigned flags = 0;
int result;
int dir;
dir = igt_sysfs_open_parameters(fd);
if (dir < 0)
return 0;
if (igt_sysfs_get_u32(dir, "enable_guc") & 1) {
flags |= GEM_SUBMISSION_GUC | GEM_SUBMISSION_EXECLISTS;
goto out;
}
if (igt_sysfs_get_boolean(dir, "enable_guc_submission")) {
flags |= GEM_SUBMISSION_GUC | GEM_SUBMISSION_EXECLISTS;
goto out;
}
if (igt_sysfs_scanf(dir, "enable_execlists", "%d", &result) != 1)
result = gen >= 8;
if (result) {
flags |= GEM_SUBMISSION_EXECLISTS;
goto out;
}
if (has_semaphores(fd, dir))
flags |= GEM_SUBMISSION_SEMAPHORES;
out:
close(dir);
return flags;
}
/**
* gem_submission_print_method:
* @fd: open i915 drm file descriptor
*
* Helper for pretty-printing currently used submission method
*/
void gem_submission_print_method(int fd)
{
const unsigned flags = gem_submission_method(fd);
if (flags & GEM_SUBMISSION_GUC) {
igt_info("Using GuC submission\n");
return;
}
if (flags & GEM_SUBMISSION_EXECLISTS) {
igt_info("Using Execlists submission\n");
return;
}
igt_info("Using Legacy submission%s\n",
flags & GEM_SUBMISSION_SEMAPHORES ? ", with semaphores" : "");
}
/**
* gem_has_semaphores:
* @fd: open i915 drm file descriptor
*
* Feature test macro to query whether the driver is using semaphores for
* synchronization between engines.
*/
bool gem_has_semaphores(int fd)
{
return gem_submission_method(fd) & GEM_SUBMISSION_SEMAPHORES;
}
/**
* gem_has_execlists:
* @fd: open i915 drm file descriptor
*
* Feature test macro to query whether the driver is using execlists as a
* hardware submission method.
*/
bool gem_has_execlists(int fd)
{
return gem_submission_method(fd) & GEM_SUBMISSION_EXECLISTS;
}
/**
* gem_has_guc_submission:
* @fd: open i915 drm file descriptor
*
* Feature test macro to query whether the driver is using the GuC as a
* hardware submission method.
*/
bool gem_has_guc_submission(int fd)
{
return gem_submission_method(fd) & GEM_SUBMISSION_GUC;
}
/**
* gem_reopen_driver:
* @fd: re-open the i915 drm file descriptor
*
* Re-opens the drm fd which is useful in instances where a clean default
* context is needed.
*/
int gem_reopen_driver(int fd)
{
char path[256];
snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
fd = open(path, O_RDWR);
igt_assert_fd(fd);
return fd;
}
static bool is_wedged(int i915)
{
int err = 0;
if (ioctl(i915, DRM_IOCTL_I915_GEM_THROTTLE))
err = -errno;
return err == -EIO;
}
/**
* gem_test_engine:
* @i915: open i915 drm file descriptor
* @engine: the engine (I915_EXEC_RING id) to exercise
*
* Execute a nop batch on the engine specified, or ALL_ENGINES for all,
* and check it executes.
*/
void gem_test_engine(int i915, unsigned int engine)
{
const uint32_t bbe = MI_BATCH_BUFFER_END;
struct drm_i915_gem_exec_object2 obj = { };
struct drm_i915_gem_execbuffer2 execbuf = {
.buffers_ptr = to_user_pointer(&obj),
.buffer_count = 1,
};
i915 = gem_reopen_driver(i915);
igt_assert(!is_wedged(i915));
obj.handle = gem_create(i915, 4096);
gem_write(i915, obj.handle, 0, &bbe, sizeof(bbe));
if (engine == ALL_ENGINES) {
for_each_physical_engine(i915, engine) {
execbuf.flags = engine;
gem_execbuf(i915, &execbuf);
}
} else {
execbuf.flags = engine;
gem_execbuf(i915, &execbuf);
}
gem_sync(i915, obj.handle);
gem_close(i915, obj.handle);
igt_assert(!is_wedged(i915));
close(i915);
}