Merge tag 'drm-intel-next-2018-07-19' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
On GEM side: - GuC related fixes (Chris, Michal) - GTT read-only pages support (Jon, Chris) - More selftests fixes (Chris) - More GPU reset improvements (Chris) - Flush caches after GGTT writes (Chris) - Handle recursive shrinker for vma->last_active allocation (Chris) - Other execlists fixes (Chris) On Display side: - GLK HDMI fix (Clint) - Rework and cleanup around HPD pin (Ville) - Preparation work for Display Stream Compression support coming on ICL (Anusha) - Nuke LVDS lid notification (Ville) - Assume eDP is always connected (Ville) - Kill intel panel detection (Ville) Signed-off-by: Dave Airlie <airlied@redhat.com> # gpg: Signature made Fri 20 Jul 2018 01:51:45 AM AEST # gpg: using RSA key FA625F640EEB13CA # gpg: Good signature from "Rodrigo Vivi <rodrigo.vivi@intel.com>" # gpg: aka "Rodrigo Vivi <rodrigo.vivi@gmail.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6D20 7068 EEDD 6509 1C2C E2A3 FA62 5F64 0EEB 13CA # Conflicts: # drivers/gpu/drm/i915/intel_lrc.c Link: https://patchwork.freedesktop.org/patch/msgid/20180719171257.GA12199@intel.com
此提交包含在:
@@ -570,6 +570,7 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg)
|
||||
i915_vma_close(vma);
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
|
||||
@@ -597,6 +598,7 @@ static void close_object_list(struct list_head *objects,
|
||||
|
||||
list_del(&obj->st_link);
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
}
|
||||
@@ -866,6 +868,7 @@ static int igt_mock_ppgtt_64K(void *arg)
|
||||
i915_vma_close(vma);
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
}
|
||||
@@ -1265,6 +1268,7 @@ static int igt_ppgtt_exhaust_huge(void *arg)
|
||||
}
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
}
|
||||
@@ -1326,6 +1330,7 @@ static int igt_ppgtt_internal_huge(void *arg)
|
||||
}
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
|
||||
@@ -1394,6 +1399,7 @@ static int igt_ppgtt_gemfs_huge(void *arg)
|
||||
}
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
|
||||
i915_gem_object_put(obj);
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "../i915_selftest.h"
|
||||
#include "i915_random.h"
|
||||
#include "igt_flush_test.h"
|
||||
|
||||
#include "mock_drm.h"
|
||||
@@ -252,9 +253,9 @@ static int cpu_check(struct drm_i915_gem_object *obj, unsigned int max)
|
||||
}
|
||||
|
||||
for (; m < DW_PER_PAGE; m++) {
|
||||
if (map[m] != 0xdeadbeef) {
|
||||
if (map[m] != STACK_MAGIC) {
|
||||
pr_err("Invalid value at page %d, offset %d: found %x expected %x\n",
|
||||
n, m, map[m], 0xdeadbeef);
|
||||
n, m, map[m], STACK_MAGIC);
|
||||
err = -EINVAL;
|
||||
goto out_unmap;
|
||||
}
|
||||
@@ -310,7 +311,7 @@ create_test_object(struct i915_gem_context *ctx,
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = cpu_fill(obj, 0xdeadbeef);
|
||||
err = cpu_fill(obj, STACK_MAGIC);
|
||||
if (err) {
|
||||
pr_err("Failed to fill object with cpu, err=%d\n",
|
||||
err);
|
||||
@@ -432,6 +433,111 @@ out_unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int igt_ctx_readonly(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
struct drm_i915_gem_object *obj = NULL;
|
||||
struct drm_file *file;
|
||||
I915_RND_STATE(prng);
|
||||
IGT_TIMEOUT(end_time);
|
||||
LIST_HEAD(objects);
|
||||
struct i915_gem_context *ctx;
|
||||
struct i915_hw_ppgtt *ppgtt;
|
||||
unsigned long ndwords, dw;
|
||||
int err = -ENODEV;
|
||||
|
||||
/*
|
||||
* Create a few read-only objects (with the occasional writable object)
|
||||
* and try to write into these object checking that the GPU discards
|
||||
* any write to a read-only object.
|
||||
*/
|
||||
|
||||
file = mock_file(i915);
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = i915_gem_create_context(i915, file->driver_priv);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ppgtt = ctx->ppgtt ?: i915->mm.aliasing_ppgtt;
|
||||
if (!ppgtt || !ppgtt->vm.has_read_only) {
|
||||
err = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ndwords = 0;
|
||||
dw = 0;
|
||||
while (!time_after(jiffies, end_time)) {
|
||||
struct intel_engine_cs *engine;
|
||||
unsigned int id;
|
||||
|
||||
for_each_engine(engine, i915, id) {
|
||||
if (!intel_engine_can_store_dword(engine))
|
||||
continue;
|
||||
|
||||
if (!obj) {
|
||||
obj = create_test_object(ctx, file, &objects);
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (prandom_u32_state(&prng) & 1)
|
||||
i915_gem_object_set_readonly(obj);
|
||||
}
|
||||
|
||||
intel_runtime_pm_get(i915);
|
||||
err = gpu_fill(obj, ctx, engine, dw);
|
||||
intel_runtime_pm_put(i915);
|
||||
if (err) {
|
||||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
engine->name, ctx->hw_id,
|
||||
yesno(!!ctx->ppgtt), err);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (++dw == max_dwords(obj)) {
|
||||
obj = NULL;
|
||||
dw = 0;
|
||||
}
|
||||
ndwords++;
|
||||
}
|
||||
}
|
||||
pr_info("Submitted %lu dwords (across %u engines)\n",
|
||||
ndwords, INTEL_INFO(i915)->num_rings);
|
||||
|
||||
dw = 0;
|
||||
list_for_each_entry(obj, &objects, st_link) {
|
||||
unsigned int rem =
|
||||
min_t(unsigned int, ndwords - dw, max_dwords(obj));
|
||||
unsigned int num_writes;
|
||||
|
||||
num_writes = rem;
|
||||
if (i915_gem_object_is_readonly(obj))
|
||||
num_writes = 0;
|
||||
|
||||
err = cpu_check(obj, num_writes);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
dw += rem;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
if (igt_flush_test(i915, I915_WAIT_LOCKED))
|
||||
err = -EIO;
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
|
||||
static __maybe_unused const char *
|
||||
__engine_name(struct drm_i915_private *i915, unsigned int engines)
|
||||
{
|
||||
@@ -608,6 +714,7 @@ int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv)
|
||||
static const struct i915_subtest tests[] = {
|
||||
SUBTEST(igt_switch_to_kernel_context),
|
||||
SUBTEST(igt_ctx_exec),
|
||||
SUBTEST(igt_ctx_readonly),
|
||||
};
|
||||
bool fake_alias = false;
|
||||
int err;
|
||||
|
@@ -1244,6 +1244,7 @@ static int exercise_mock(struct drm_i915_private *i915,
|
||||
u64 hole_start, u64 hole_end,
|
||||
unsigned long end_time))
|
||||
{
|
||||
const u64 limit = totalram_pages << PAGE_SHIFT;
|
||||
struct i915_gem_context *ctx;
|
||||
struct i915_hw_ppgtt *ppgtt;
|
||||
IGT_TIMEOUT(end_time);
|
||||
@@ -1256,7 +1257,7 @@ static int exercise_mock(struct drm_i915_private *i915,
|
||||
ppgtt = ctx->ppgtt;
|
||||
GEM_BUG_ON(!ppgtt);
|
||||
|
||||
err = func(i915, &ppgtt->vm, 0, ppgtt->vm.total, end_time);
|
||||
err = func(i915, &ppgtt->vm, 0, min(ppgtt->vm.total, limit), end_time);
|
||||
|
||||
mock_context_close(ctx);
|
||||
return err;
|
||||
|
@@ -375,7 +375,8 @@ static int igt_partial_tiling(void *arg)
|
||||
}
|
||||
|
||||
GEM_BUG_ON(tile.swizzle == I915_BIT_6_SWIZZLE_UNKNOWN);
|
||||
if (tile.swizzle == I915_BIT_6_SWIZZLE_9_10_17)
|
||||
if (tile.swizzle == I915_BIT_6_SWIZZLE_9_17 ||
|
||||
tile.swizzle == I915_BIT_6_SWIZZLE_9_10_17)
|
||||
continue;
|
||||
|
||||
if (INTEL_GEN(i915) <= 2) {
|
||||
|
@@ -210,6 +210,8 @@ int __i915_subtests(const char *caller,
|
||||
return -EINTR;
|
||||
|
||||
pr_debug(DRIVER_NAME ": Running %s/%s\n", caller, st->name);
|
||||
GEM_TRACE("Running %s/%s\n", caller, st->name);
|
||||
|
||||
err = st->func(data);
|
||||
if (err && err != -EINTR) {
|
||||
pr_err(DRIVER_NAME "/%s: %s failed with error %d\n",
|
||||
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef IGT_WEDGE_ME_H
|
||||
#define IGT_WEDGE_ME_H
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "../i915_gem.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
struct igt_wedge_me {
|
||||
struct delayed_work work;
|
||||
struct drm_i915_private *i915;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static void __igt_wedge_me(struct work_struct *work)
|
||||
{
|
||||
struct igt_wedge_me *w = container_of(work, typeof(*w), work.work);
|
||||
|
||||
pr_err("%s timed out, cancelling test.\n", w->name);
|
||||
|
||||
GEM_TRACE("%s timed out.\n", w->name);
|
||||
GEM_TRACE_DUMP();
|
||||
|
||||
i915_gem_set_wedged(w->i915);
|
||||
}
|
||||
|
||||
static void __igt_init_wedge(struct igt_wedge_me *w,
|
||||
struct drm_i915_private *i915,
|
||||
long timeout,
|
||||
const char *name)
|
||||
{
|
||||
w->i915 = i915;
|
||||
w->name = name;
|
||||
|
||||
INIT_DELAYED_WORK_ONSTACK(&w->work, __igt_wedge_me);
|
||||
schedule_delayed_work(&w->work, timeout);
|
||||
}
|
||||
|
||||
static void __igt_fini_wedge(struct igt_wedge_me *w)
|
||||
{
|
||||
cancel_delayed_work_sync(&w->work);
|
||||
destroy_delayed_work_on_stack(&w->work);
|
||||
w->i915 = NULL;
|
||||
}
|
||||
|
||||
#define igt_wedge_on_timeout(W, DEV, TIMEOUT) \
|
||||
for (__igt_init_wedge((W), (DEV), (TIMEOUT), __func__); \
|
||||
(W)->i915; \
|
||||
__igt_fini_wedge((W)))
|
||||
|
||||
#endif /* IGT_WEDGE_ME_H */
|
@@ -196,19 +196,23 @@ static int igt_guc_clients(void *args)
|
||||
}
|
||||
|
||||
unreserve_doorbell(guc->execbuf_client);
|
||||
err = guc_clients_doorbell_init(guc);
|
||||
|
||||
__create_doorbell(guc->execbuf_client);
|
||||
err = __guc_allocate_doorbell(guc, guc->execbuf_client->stage_id);
|
||||
if (err != -EIO) {
|
||||
pr_err("unexpected (err = %d)", err);
|
||||
goto out;
|
||||
goto out_db;
|
||||
}
|
||||
|
||||
if (!available_dbs(guc, guc->execbuf_client->priority)) {
|
||||
pr_err("doorbell not available when it should\n");
|
||||
err = -EIO;
|
||||
goto out;
|
||||
goto out_db;
|
||||
}
|
||||
|
||||
out_db:
|
||||
/* clean after test */
|
||||
__destroy_doorbell(guc->execbuf_client);
|
||||
err = reserve_doorbell(guc->execbuf_client);
|
||||
if (err) {
|
||||
pr_err("failed to reserve back the doorbell back\n");
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "../i915_selftest.h"
|
||||
#include "i915_random.h"
|
||||
#include "igt_flush_test.h"
|
||||
#include "igt_wedge_me.h"
|
||||
|
||||
#include "mock_context.h"
|
||||
#include "mock_drm.h"
|
||||
@@ -921,7 +922,7 @@ static u32 fake_hangcheck(struct i915_request *rq, u32 mask)
|
||||
return reset_count;
|
||||
}
|
||||
|
||||
static int igt_wait_reset(void *arg)
|
||||
static int igt_reset_wait(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
struct i915_request *rq;
|
||||
@@ -995,6 +996,170 @@ unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
struct evict_vma {
|
||||
struct completion completion;
|
||||
struct i915_vma *vma;
|
||||
};
|
||||
|
||||
static int evict_vma(void *data)
|
||||
{
|
||||
struct evict_vma *arg = data;
|
||||
struct i915_address_space *vm = arg->vma->vm;
|
||||
struct drm_i915_private *i915 = vm->i915;
|
||||
struct drm_mm_node evict = arg->vma->node;
|
||||
int err;
|
||||
|
||||
complete(&arg->completion);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
err = i915_gem_evict_for_node(vm, &evict, 0);
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __igt_reset_evict_vma(struct drm_i915_private *i915,
|
||||
struct i915_address_space *vm)
|
||||
{
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct task_struct *tsk = NULL;
|
||||
struct i915_request *rq;
|
||||
struct evict_vma arg;
|
||||
struct hang h;
|
||||
int err;
|
||||
|
||||
if (!intel_engine_can_store_dword(i915->engine[RCS]))
|
||||
return 0;
|
||||
|
||||
/* Check that we can recover an unbind stuck on a hanging request */
|
||||
|
||||
global_reset_lock(i915);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
err = hang_init(&h, i915);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
goto fini;
|
||||
}
|
||||
|
||||
arg.vma = i915_vma_instance(obj, vm, NULL);
|
||||
if (IS_ERR(arg.vma)) {
|
||||
err = PTR_ERR(arg.vma);
|
||||
goto out_obj;
|
||||
}
|
||||
|
||||
rq = hang_create_request(&h, i915->engine[RCS]);
|
||||
if (IS_ERR(rq)) {
|
||||
err = PTR_ERR(rq);
|
||||
goto out_obj;
|
||||
}
|
||||
|
||||
err = i915_vma_pin(arg.vma, 0, 0,
|
||||
i915_vma_is_ggtt(arg.vma) ? PIN_GLOBAL : PIN_USER);
|
||||
if (err)
|
||||
goto out_obj;
|
||||
|
||||
err = i915_vma_move_to_active(arg.vma, rq, EXEC_OBJECT_WRITE);
|
||||
i915_vma_unpin(arg.vma);
|
||||
|
||||
i915_request_get(rq);
|
||||
i915_request_add(rq);
|
||||
if (err)
|
||||
goto out_rq;
|
||||
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
if (!wait_until_running(&h, rq)) {
|
||||
struct drm_printer p = drm_info_printer(i915->drm.dev);
|
||||
|
||||
pr_err("%s: Failed to start request %x, at %x\n",
|
||||
__func__, rq->fence.seqno, hws_seqno(&h, rq));
|
||||
intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name);
|
||||
|
||||
i915_gem_set_wedged(i915);
|
||||
goto out_reset;
|
||||
}
|
||||
|
||||
init_completion(&arg.completion);
|
||||
|
||||
tsk = kthread_run(evict_vma, &arg, "igt/evict_vma");
|
||||
if (IS_ERR(tsk)) {
|
||||
err = PTR_ERR(tsk);
|
||||
tsk = NULL;
|
||||
goto out_reset;
|
||||
}
|
||||
|
||||
wait_for_completion(&arg.completion);
|
||||
|
||||
if (wait_for(waitqueue_active(&rq->execute), 10)) {
|
||||
struct drm_printer p = drm_info_printer(i915->drm.dev);
|
||||
|
||||
pr_err("igt/evict_vma kthread did not wait\n");
|
||||
intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name);
|
||||
|
||||
i915_gem_set_wedged(i915);
|
||||
goto out_reset;
|
||||
}
|
||||
|
||||
out_reset:
|
||||
fake_hangcheck(rq, intel_engine_flag(rq->engine));
|
||||
|
||||
if (tsk) {
|
||||
struct igt_wedge_me w;
|
||||
|
||||
/* The reset, even indirectly, should take less than 10ms. */
|
||||
igt_wedge_on_timeout(&w, i915, HZ / 10 /* 100ms timeout*/)
|
||||
err = kthread_stop(tsk);
|
||||
}
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
out_rq:
|
||||
i915_request_put(rq);
|
||||
out_obj:
|
||||
i915_gem_object_put(obj);
|
||||
fini:
|
||||
hang_fini(&h);
|
||||
unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
global_reset_unlock(i915);
|
||||
|
||||
if (i915_terminally_wedged(&i915->gpu_error))
|
||||
return -EIO;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int igt_reset_evict_ggtt(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
|
||||
return __igt_reset_evict_vma(i915, &i915->ggtt.vm);
|
||||
}
|
||||
|
||||
static int igt_reset_evict_ppgtt(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
struct i915_gem_context *ctx;
|
||||
int err;
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
ctx = kernel_context(i915);
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
if (IS_ERR(ctx))
|
||||
return PTR_ERR(ctx);
|
||||
|
||||
err = 0;
|
||||
if (ctx->ppgtt) /* aliasing == global gtt locking, covered above */
|
||||
err = __igt_reset_evict_vma(i915, &ctx->ppgtt->vm);
|
||||
|
||||
kernel_context_close(ctx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int wait_for_others(struct drm_i915_private *i915,
|
||||
struct intel_engine_cs *exclude)
|
||||
{
|
||||
@@ -1240,8 +1405,10 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
|
||||
SUBTEST(igt_reset_idle_engine),
|
||||
SUBTEST(igt_reset_active_engine),
|
||||
SUBTEST(igt_reset_engines),
|
||||
SUBTEST(igt_wait_reset),
|
||||
SUBTEST(igt_reset_queue),
|
||||
SUBTEST(igt_reset_wait),
|
||||
SUBTEST(igt_reset_evict_ggtt),
|
||||
SUBTEST(igt_reset_evict_ppgtt),
|
||||
SUBTEST(igt_handle_error),
|
||||
};
|
||||
bool saved_hangcheck;
|
||||
|
@@ -451,12 +451,127 @@ err_wedged:
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
static int live_preempt_hang(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
struct i915_gem_context *ctx_hi, *ctx_lo;
|
||||
struct spinner spin_hi, spin_lo;
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
int err = -ENOMEM;
|
||||
|
||||
if (!HAS_LOGICAL_RING_PREEMPTION(i915))
|
||||
return 0;
|
||||
|
||||
if (!intel_has_reset_engine(i915))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
if (spinner_init(&spin_hi, i915))
|
||||
goto err_unlock;
|
||||
|
||||
if (spinner_init(&spin_lo, i915))
|
||||
goto err_spin_hi;
|
||||
|
||||
ctx_hi = kernel_context(i915);
|
||||
if (!ctx_hi)
|
||||
goto err_spin_lo;
|
||||
ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY;
|
||||
|
||||
ctx_lo = kernel_context(i915);
|
||||
if (!ctx_lo)
|
||||
goto err_ctx_hi;
|
||||
ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY;
|
||||
|
||||
for_each_engine(engine, i915, id) {
|
||||
struct i915_request *rq;
|
||||
|
||||
if (!intel_engine_has_preemption(engine))
|
||||
continue;
|
||||
|
||||
rq = spinner_create_request(&spin_lo, ctx_lo, engine,
|
||||
MI_ARB_CHECK);
|
||||
if (IS_ERR(rq)) {
|
||||
err = PTR_ERR(rq);
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
i915_request_add(rq);
|
||||
if (!wait_for_spinner(&spin_lo, rq)) {
|
||||
GEM_TRACE("lo spinner failed to start\n");
|
||||
GEM_TRACE_DUMP();
|
||||
i915_gem_set_wedged(i915);
|
||||
err = -EIO;
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
rq = spinner_create_request(&spin_hi, ctx_hi, engine,
|
||||
MI_ARB_CHECK);
|
||||
if (IS_ERR(rq)) {
|
||||
spinner_end(&spin_lo);
|
||||
err = PTR_ERR(rq);
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
init_completion(&engine->execlists.preempt_hang.completion);
|
||||
engine->execlists.preempt_hang.inject_hang = true;
|
||||
|
||||
i915_request_add(rq);
|
||||
|
||||
if (!wait_for_completion_timeout(&engine->execlists.preempt_hang.completion,
|
||||
HZ / 10)) {
|
||||
pr_err("Preemption did not occur within timeout!");
|
||||
GEM_TRACE_DUMP();
|
||||
i915_gem_set_wedged(i915);
|
||||
err = -EIO;
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags);
|
||||
i915_reset_engine(engine, NULL);
|
||||
clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags);
|
||||
|
||||
engine->execlists.preempt_hang.inject_hang = false;
|
||||
|
||||
if (!wait_for_spinner(&spin_hi, rq)) {
|
||||
GEM_TRACE("hi spinner failed to start\n");
|
||||
GEM_TRACE_DUMP();
|
||||
i915_gem_set_wedged(i915);
|
||||
err = -EIO;
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
|
||||
spinner_end(&spin_hi);
|
||||
spinner_end(&spin_lo);
|
||||
if (igt_flush_test(i915, I915_WAIT_LOCKED)) {
|
||||
err = -EIO;
|
||||
goto err_ctx_lo;
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
err_ctx_lo:
|
||||
kernel_context_close(ctx_lo);
|
||||
err_ctx_hi:
|
||||
kernel_context_close(ctx_hi);
|
||||
err_spin_lo:
|
||||
spinner_fini(&spin_lo);
|
||||
err_spin_hi:
|
||||
spinner_fini(&spin_hi);
|
||||
err_unlock:
|
||||
igt_flush_test(i915, I915_WAIT_LOCKED);
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
int intel_execlists_live_selftests(struct drm_i915_private *i915)
|
||||
{
|
||||
static const struct i915_subtest tests[] = {
|
||||
SUBTEST(live_sanitycheck),
|
||||
SUBTEST(live_preempt),
|
||||
SUBTEST(live_late_preempt),
|
||||
SUBTEST(live_preempt_hang),
|
||||
};
|
||||
|
||||
if (!HAS_EXECLISTS(i915))
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "../i915_selftest.h"
|
||||
|
||||
#include "igt_wedge_me.h"
|
||||
#include "mock_context.h"
|
||||
|
||||
static struct drm_i915_gem_object *
|
||||
@@ -111,6 +112,7 @@ static int check_whitelist(const struct whitelist *w,
|
||||
struct intel_engine_cs *engine)
|
||||
{
|
||||
struct drm_i915_gem_object *results;
|
||||
struct igt_wedge_me wedge;
|
||||
u32 *vaddr;
|
||||
int err;
|
||||
int i;
|
||||
@@ -119,7 +121,11 @@ static int check_whitelist(const struct whitelist *w,
|
||||
if (IS_ERR(results))
|
||||
return PTR_ERR(results);
|
||||
|
||||
err = i915_gem_object_set_to_cpu_domain(results, false);
|
||||
err = 0;
|
||||
igt_wedge_on_timeout(&wedge, ctx->i915, HZ / 5) /* a safety net! */
|
||||
err = i915_gem_object_set_to_cpu_domain(results, false);
|
||||
if (i915_terminally_wedged(&ctx->i915->gpu_error))
|
||||
err = -EIO;
|
||||
if (err)
|
||||
goto out_put;
|
||||
|
||||
|
新增問題並參考
封鎖使用者