From patchwork Wed Mar 16 13:07:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tejas Upadhyay X-Patchwork-Id: 12782705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B26AC433F5 for ; Wed, 16 Mar 2022 13:21:06 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BDA7310E595; Wed, 16 Mar 2022 13:21:05 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 1EB5710E595 for ; Wed, 16 Mar 2022 13:21:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647436864; x=1678972864; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=vbcyDn5W2ZO3IS5FhgpNZ/lbFoeZwu0FItNvf0w6rNs=; b=S6+F6j4wFg8GylGSRVU3PrBX6SBAl33MrkB5y7it1cjEnKcGuMSg3sO+ L6qfNcwxUsSN9Dbkjd3xhAZcRRhrs8+Dgz+qCi3Mry4HtMPSgKi1ELp5S tVfn3MnI4saj2bkIgLz7XJgWhK00tno1qqZPblf4Mhb5hIxquHYmRDajG hxO8+hbfGq8dmE8HY0enDubYNZV6oVwqw8HGtyCMKupnSHVlKgbj139Ee R1PjApLhY/l45nNfaNyisDTiSAbw/tS4+cfJL1uM59GzyvVurIqM8hs+1 xYb8AZ1bIYgXcTZ/ENYotnyWFKN/HE0ZUl2FXwMloYCxCr3DNSuj9CMMY Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10286"; a="281364288" X-IronPort-AV: E=Sophos;i="5.90,186,1643702400"; d="scan'208";a="281364288" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Mar 2022 06:21:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,186,1643702400"; d="scan'208";a="646643908" Received: from tejas-system-product-name.iind.intel.com ([10.145.162.130]) by orsmga004.jf.intel.com with ESMTP; 16 Mar 2022 06:21:01 -0700 From: Tejas Upadhyay To: intel-gfx@lists.freedesktop.org Date: Wed, 16 Mar 2022 18:37:53 +0530 Message-Id: <20220316130754.813761-1-tejaskumarx.surendrakumar.upadhyay@intel.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 1/2] drm/i915/gt: preempt engine to idle before reset X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tejas Upadhyay , Chris Wilson Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" From: Chris Wilson We need to be able to suspend execution along an engine and flush any active contexts away from the HW, back into the execution queue. This is done using a preempt-to-idle, disabling the submission backed while sending a preemption request to ELSP. Unpon completion of the context switch into the preemption context, we know the existing contexts are now idle. This is useful for reset, as it means we can proceed knowing that the engine is idle or hung (and so needs a reset). Suggested-by: Chris Wilson Signed-off-by: Chris Wilson Signed-off-by: Tejas Upadhyay --- drivers/gpu/drm/i915/gt/intel_engine_types.h | 4 +- .../drm/i915/gt/intel_execlists_submission.c | 131 +++++++++++++++++- drivers/gpu/drm/i915/gt/intel_reset.c | 9 ++ 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index eac20112709c..194155de900d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -237,6 +237,7 @@ struct intel_engine_execlists { */ struct rb_root_cached virtual; + struct intel_context *preempt_context; /** * @csb_write: control register for Context Switch buffer * @@ -445,8 +446,9 @@ struct intel_engine_cs { void (*irq_disable)(struct intel_engine_cs *engine); void (*irq_handler)(struct intel_engine_cs *engine, u16 iir); - void (*sanitize)(struct intel_engine_cs *engine); + int (*suspend)(struct intel_engine_cs *engine); int (*resume)(struct intel_engine_cs *engine); + void (*sanitize)(struct intel_engine_cs *engine); struct { void (*prepare)(struct intel_engine_cs *engine); diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index e1470bb60f34..006e2d9a53e3 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2440,6 +2440,125 @@ static void execlists_submission_tasklet(struct tasklet_struct *t) rcu_read_unlock(); } +static void suspend_tasklet(struct tasklet_struct *t) +{ + struct i915_sched_engine *se = from_tasklet(se, t, tasklet); + struct intel_engine_cs * const engine = se->private_data; + struct i915_request *post[EXECLIST_MAX_PORTS]; + + rcu_read_lock(); + post_process_csb(post, process_csb(engine, post)); + rcu_read_unlock(); +} + +/* XXX return error and force a full reset if we fail to + * preempt-to-idle + */ +static int execlists_suspend(struct intel_engine_cs *engine) +{ + struct i915_sched_engine *se = engine->sched_engine; + struct intel_engine_execlists * const el = &engine->execlists; + unsigned long timeout; + int err; + + /* Stop further submissions, but listen for our own preempt-to-idle */ + tasklet_disable(&se->tasklet); + se->tasklet.callback = suspend_tasklet; + tasklet_enable(&se->tasklet); + + /* + * We have to wait for the HW to complete a pending context switch + * before we can write to ELS[PQ] again. Otherwise the behaviour + * is undefined... + * + * If the engine is truly hung, it will neither clear pending + * nor respond to our preemption request. In the later case, + * we have the dilemma of how to restore hang detection... + */ + timeout = jiffies + HZ / 2; + while (READ_ONCE(el->pending[0]) && time_before(jiffies, timeout)) + intel_engine_flush_submission(engine); + if (READ_ONCE(el->pending[0])) { + err = -EBUSY; + goto err; + } + + if (*el->active) { /* preempt to idle required */ + struct i915_request **pending = el->pending; + struct intel_context *ce = el->preempt_context; + u64 desc; + int n; + + /* Always submit an empty / idle context */ + desc = lrc_update_regs(ce, engine, ce->ring->tail); + + /* + * As we submit a dummy context, we will get two events. + * First a preemption of the running context, causing us + * to promote el->pending to el->inflight. And then + * we will receive a completion event as our context + * idles. + * + * We can use any dummy request here for tracking the + * preemption events. + */ + execlists_schedule_in(*el->active, 0); + *pending++ = i915_request_get(*el->active); + *pending++ = NULL; + + /* Tell the HW to preempt to our special context */ + for (n = execlists_num_ports(el); --n; ) + write_desc(el, 0, n); + write_desc(el, desc, 0); + if (el->ctrl_reg) + writel(EL_CTRL_LOAD, el->ctrl_reg); + + timeout = jiffies + HZ / 2; + while (READ_ONCE(el->pending[0]) && + time_before(jiffies, timeout)) + intel_engine_flush_submission(engine); + + if (READ_ONCE(el->pending[0])) { + err = -EIO; + goto err; + } + } + + return 0; + +err: + tasklet_disable(&se->tasklet); + se->tasklet.callback = execlists_submission_tasklet; + tasklet_enable(&se->tasklet); + return err; +} + +static int setup_preempt_to_idle(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const el = &engine->execlists; + static struct lock_class_key preempt; + struct intel_context *ce; + + ce = intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K, + I915_GEM_HWS_SEQNO_ADDR, /* unused */ + &preempt, "preempt_context"); + if (IS_ERR(ce)) + return PTR_ERR(ce); + + el->preempt_context = ce; + return 0; +} + +static void cleanup_preempt_to_idle(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const el = &engine->execlists; + + if (el->preempt_context) { + intel_engine_destroy_pinned_context(el->preempt_context); + el->preempt_context = NULL; + } +} + static void execlists_irq_handler(struct intel_engine_cs *engine, u16 iir) { bool tasklet = false; @@ -2907,6 +3026,10 @@ static void enable_execlists(struct intel_engine_cs *engine) static int execlists_resume(struct intel_engine_cs *engine) { + struct i915_sched_engine *se = engine->sched_engine; + + se->tasklet.callback = execlists_submission_tasklet; + intel_mocs_init_engine(engine); intel_breadcrumbs_reset(engine->breadcrumbs); @@ -3337,6 +3460,7 @@ static void execlists_release(struct intel_engine_cs *engine) engine->sanitize = NULL; /* no longer in control, nothing to sanitize */ execlists_shutdown(engine); + cleanup_preempt_to_idle(engine); intel_engine_cleanup_common(engine); lrc_fini_wa_ctx(engine); @@ -3378,7 +3502,7 @@ static void logical_ring_default_vfuncs(struct intel_engine_cs *engine) { /* Default vfuncs which can be overridden by each engine. */ - + engine->suspend = execlists_suspend; engine->resume = execlists_resume; engine->cops = &execlists_context_ops; @@ -3480,6 +3604,7 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) struct drm_i915_private *i915 = engine->i915; struct intel_uncore *uncore = engine->uncore; u32 base = engine->mmio_base; + int err; tasklet_setup(&engine->sched_engine->tasklet, execlists_submission_tasklet); timer_setup(&engine->execlists.timer, execlists_timeslice, 0); @@ -3491,6 +3616,10 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) if (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE) rcs_submission_override(engine); + err = setup_preempt_to_idle(engine); + if (err) + return err; + lrc_init_wa_ctx(engine); if (HAS_LOGICAL_RING_ELSQ(i915)) { diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index a6ae213c7d89..e10718e2eee9 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -772,6 +772,12 @@ static intel_engine_mask_t reset_prepare(struct intel_gt *gt) intel_engine_mask_t awake = 0; enum intel_engine_id id; + intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL); + /* XXX Assumes we have reset_domain broadening */ + for_each_engine(engine, gt, id) + if (engine->suspend) + engine->suspend(engine); + for_each_engine(engine, gt, id) { if (intel_engine_pm_get_if_awake(engine)) awake |= engine->mask; @@ -830,11 +836,14 @@ static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake) for_each_engine(engine, gt, id) { reset_finish_engine(engine); + if (engine->resume) + engine->resume(engine); if (awake & engine->mask) intel_engine_pm_put(engine); } intel_uc_reset_finish(>->uc); + intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL); } static void nop_submit_request(struct i915_request *request) From patchwork Wed Mar 16 13:07:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tejas Upadhyay X-Patchwork-Id: 12782706 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8B200C433FE for ; Wed, 16 Mar 2022 13:21:07 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AFD0C10E5A4; Wed, 16 Mar 2022 13:21:06 +0000 (UTC) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 71D3F10E595 for ; Wed, 16 Mar 2022 13:21:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647436865; x=1678972865; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=19ij2+SRzg2EtKxLzdh9fi15KB9aF1UupWGrPfrttBk=; b=kyvzwzQ+ggk5hrxXktxvNQeR00juAM0RbmQxzBye7kF+3iC147i4wPUn 8c7EEgYtz7VjPKE9vOtocHXD5cB5cq2gnnsUFYOPsXGFrvn4d0OD0Jd+b iMRPJL1a1d051FhkD/BN4As+8fqouAXLO7vu0czLIYbOvH1lNnV422V91 ilMz+vASUCFcA+dmvucmvw9sO+NZtZ8o88mbOYEi6jgmKmoFNlnYh4Jep mrsmkvmuuM6/t6Uf70oP5LY8j2nSXqOZRTfA9yFSXlth5wltoaCQBXDbb Uws6OPJO+hw9GuRlhbijp7W668h7dHE+xh2/d9egCjAC9xnchXTR//a7Z g==; X-IronPort-AV: E=McAfee;i="6200,9189,10286"; a="281364303" X-IronPort-AV: E=Sophos;i="5.90,186,1643702400"; d="scan'208";a="281364303" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Mar 2022 06:21:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,186,1643702400"; d="scan'208";a="646643915" Received: from tejas-system-product-name.iind.intel.com ([10.145.162.130]) by orsmga004.jf.intel.com with ESMTP; 16 Mar 2022 06:21:03 -0700 From: Tejas Upadhyay To: intel-gfx@lists.freedesktop.org Date: Wed, 16 Mar 2022 18:37:54 +0530 Message-Id: <20220316130754.813761-2-tejaskumarx.surendrakumar.upadhyay@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220316130754.813761-1-tejaskumarx.surendrakumar.upadhyay@intel.com> References: <20220316130754.813761-1-tejaskumarx.surendrakumar.upadhyay@intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH 2/2] drm/i915/gt: preempt and reset based on reset domain X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tejas Upadhyay , Chris Wilson Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" When we have shared reset domains, as we the engine may be indirectly coupled to the stalled engine, and we need to idle the current context to prevent collateral damage. Suggested-by: Chris Wilson Signed-off-by: Tejas Upadhyay Reported-by: kernel test robot --- drivers/gpu/drm/i915/gt/intel_engine.h | 3 ++- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 6 ++++++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 8 ++++++++ drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 7 ++++++- drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c | 2 +- drivers/gpu/drm/i915/gt/selftest_execlists.c | 4 ++-- drivers/gpu/drm/i915/selftests/i915_request.c | 5 ++--- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 1c0ab05c3c40..a6ea0cdd8b53 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -282,7 +282,8 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine) if (!CONFIG_DRM_I915_PREEMPT_TIMEOUT) return false; - return intel_engine_has_preemption(engine); + return intel_engine_has_preemption(engine) && + !intel_engine_has_shared_reset_domain(engine); } #define FORCE_VIRTUAL BIT(0) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 8080479f27aa..b28120f0158a 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -472,7 +472,13 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, static void __setup_engine_capabilities(struct intel_engine_cs *engine) { struct drm_i915_private *i915 = engine->i915; + enum intel_engine_id id; + struct intel_engine_cs *e; + for_each_engine(e, engine->gt, id) + if ((e->reset_domain & engine->reset_domain) && + e->id != engine->id) + engine->flags |= I915_ENGINE_HAS_SHARED_RESET_DOMAIN; if (engine->class == VIDEO_DECODE_CLASS) { /* * HEVC support is present on first engine instance diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 194155de900d..d27103b23318 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -531,6 +531,8 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITY BIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) +#define I915_ENGINE_HAS_SHARED_RESET_DOMAIN BIT(9) + unsigned int flags; /* @@ -598,6 +600,12 @@ intel_engine_supports_stats(const struct intel_engine_cs *engine) return engine->flags & I915_ENGINE_SUPPORTS_STATS; } +static inline bool +intel_engine_has_shared_reset_domain(const struct intel_engine_cs *engine) +{ + return engine->flags & I915_ENGINE_HAS_SHARED_RESET_DOMAIN; +} + static inline bool intel_engine_has_preemption(const struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 006e2d9a53e3..9dda02956494 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2461,6 +2461,9 @@ static int execlists_suspend(struct intel_engine_cs *engine) unsigned long timeout; int err; + if (!intel_engine_pm_get_if_awake(engine)) + return 0; + ENGINE_TRACE(engine, "supending active engine\n"); /* Stop further submissions, but listen for our own preempt-to-idle */ tasklet_disable(&se->tasklet); se->tasklet.callback = suspend_tasklet; @@ -2524,12 +2527,14 @@ static int execlists_suspend(struct intel_engine_cs *engine) } } - return 0; + goto out; err: tasklet_disable(&se->tasklet); se->tasklet.callback = execlists_submission_tasklet; tasklet_enable(&se->tasklet); +out: + intel_engine_pm_put(engine); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index 273d440a53e3..939bbea7ce1b 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -356,7 +356,7 @@ static int live_heartbeat_off(void *arg) return 0; for_each_engine(engine, gt, id) { - if (!intel_engine_has_preemption(engine)) + if (!intel_engine_has_preempt_reset(engine)) continue; err = __live_heartbeat_off(engine); diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index 09f8cd2d0e2c..3eb3496cfb7e 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c @@ -2389,7 +2389,7 @@ static int live_preempt_cancel(void *arg) goto err_client_a; for_each_engine(data.engine, gt, id) { - if (!intel_engine_has_preemption(data.engine)) + if (!intel_engine_has_preempt_reset(data.engine)) continue; err = __cancel_active0(&data); @@ -3399,7 +3399,7 @@ static int live_preempt_timeout(void *arg) unsigned long saved_timeout; struct i915_request *rq; - if (!intel_engine_has_preemption(engine)) + if (!intel_engine_has_preempt_reset(engine)) continue; rq = spinner_create_request(&spin_lo, ctx_lo, engine, diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index c56a0c2cd2f7..e80363c81d6b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -803,8 +803,7 @@ static int __cancel_reset(struct drm_i915_private *i915, unsigned long preempt_timeout_ms; int err = 0; - if (!CONFIG_DRM_I915_PREEMPT_TIMEOUT || - !intel_has_reset_engine(engine->gt)) + if (!intel_engine_has_preempt_reset(engine)) return 0; preempt_timeout_ms = engine->props.preempt_timeout_ms; @@ -906,7 +905,7 @@ static int live_cancel_request(void *arg) struct igt_live_test t; int err, err2; - if (!intel_engine_has_preemption(engine)) + if (!intel_engine_has_preempt_reset(engine)) continue; err = igt_live_test_begin(&t, i915, __func__, engine->name);