From patchwork Thu Oct 19 18:36:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Micha=C5=82_Winiarski?= X-Patchwork-Id: 10018163 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BB03460224 for ; Thu, 19 Oct 2017 18:40:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B33E428DF9 for ; Thu, 19 Oct 2017 18:40:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A622A28E05; Thu, 19 Oct 2017 18:40:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 05D3C28DFE for ; Thu, 19 Oct 2017 18:40:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B1FD76EB4E; Thu, 19 Oct 2017 18:40:33 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9EC136EB4E for ; Thu, 19 Oct 2017 18:40:32 +0000 (UTC) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 19 Oct 2017 11:40:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.43,402,1503385200"; d="scan'208";a="140127173" Received: from irsmsx102.ger.corp.intel.com ([163.33.3.155]) by orsmga004.jf.intel.com with ESMTP; 19 Oct 2017 11:40:30 -0700 Received: from localhost (172.28.171.152) by IRSMSX102.ger.corp.intel.com (163.33.3.155) with Microsoft SMTP Server (TLS) id 14.3.319.2; Thu, 19 Oct 2017 19:40:30 +0100 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= To: Date: Thu, 19 Oct 2017 20:36:18 +0200 Message-ID: <20171019183619.6235-14-michal.winiarski@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171019183619.6235-1-michal.winiarski@intel.com> References: <20171019183619.6235-1-michal.winiarski@intel.com> MIME-Version: 1.0 X-Originating-IP: [172.28.171.152] Subject: [Intel-gfx] [PATCH 13/14] drm/i915/guc: Workaround the missing user interrupt after preemption X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP With GuC, we're scheduling tasklet on USER_INTERRUPT - since some work has completed, perhaps we're able to submit some more work. We're doing similar thing for preemption - after preemption has completed, it's time to schedule the tasklet and submit more work (since the engine is now idle). Unfortunately, we can hit the scenarios where the preemption is done, but the interrupt is nowhere to be seen. To work around the problem, let's use a delayed work that's kicking the tasklet if preemption is done, and queueing itself otherwise. Testcase: igt/gem_exec_whisper/*-priority Signed-off-by: MichaƂ Winiarski Cc: Chris Wilson Cc: Jeff McGee Cc: John Harrison Cc: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_guc_submission.c | 36 +++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_guc.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index a11ed4deff4b..dbb03b5481d2 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -574,6 +574,26 @@ static void flush_ggtt_writes(struct i915_vma *vma) POSTING_READ_FW(GUC_STATUS); } +#define GUC_LOST_IRQ_WORK_DELAY_MS 100 +static void guc_lost_user_interrupt(struct work_struct *work) +{ + struct guc_preempt_work *preempt_work = + container_of(to_delayed_work(work), typeof(*preempt_work), + lost_irq_work); + struct intel_engine_cs *engine = preempt_work->engine; + struct intel_guc *guc = &engine->i915->guc; + struct guc_shared_ctx_data *data = guc->shared_data_vaddr; + struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id]; + + if (report->report_return_status == INTEL_GUC_REPORT_STATUS_COMPLETE) + tasklet_schedule(&engine->execlists.irq_tasklet); + else + queue_delayed_work(guc->preempt_wq, + &preempt_work->lost_irq_work, + msecs_to_jiffies(GUC_LOST_IRQ_WORK_DELAY_MS)); + +} + #define GUC_PREEMPT_FINISHED 0x1 #define GUC_PREEMPT_BREADCRUMB_DWORDS 0x8 static void inject_preempt_context(struct work_struct *work) @@ -629,7 +649,13 @@ static void inject_preempt_context(struct work_struct *work) if (WARN_ON(intel_guc_send(guc, data, ARRAY_SIZE(data)))) { WRITE_ONCE(engine->execlists.preempt, false); tasklet_schedule(&engine->execlists.irq_tasklet); + + return; } + + queue_delayed_work(engine->i915->guc.preempt_wq, + &preempt_work->lost_irq_work, + msecs_to_jiffies(GUC_LOST_IRQ_WORK_DELAY_MS)); } /* @@ -647,6 +673,10 @@ static void wait_for_guc_preempt_report(struct intel_engine_cs *engine) struct guc_shared_ctx_data *data = guc->shared_data_vaddr; struct guc_ctx_report *report = &data->preempt_ctx_report[engine->guc_id]; + /* If we landed here, it means that we didn't lose an interrupt, and + * we can safely cancel the worker */ + cancel_delayed_work(&guc->preempt_work[engine->id].lost_irq_work); + WARN_ON(wait_for_atomic(report->report_return_status == INTEL_GUC_REPORT_STATUS_COMPLETE, GUC_PREEMPT_POSTPROCESS_DELAY_MS)); @@ -1229,6 +1259,8 @@ static int guc_preempt_work_create(struct intel_guc *guc) for_each_engine(engine, dev_priv, id) { guc->preempt_work[id].engine = engine; INIT_WORK(&guc->preempt_work[id].work, inject_preempt_context); + INIT_DELAYED_WORK(&guc->preempt_work[id].lost_irq_work, + guc_lost_user_interrupt); } return 0; @@ -1240,8 +1272,10 @@ static void guc_preempt_work_destroy(struct intel_guc *guc) struct intel_engine_cs *engine; enum intel_engine_id id; - for_each_engine(engine, dev_priv, id) + for_each_engine(engine, dev_priv, id) { + cancel_delayed_work_sync(&guc->preempt_work[id].lost_irq_work); cancel_work_sync(&guc->preempt_work[id].work); + } destroy_workqueue(guc->preempt_wq); } diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 7273a6be7dc1..0c9338b5c4b8 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -49,6 +49,7 @@ enum i915_guc_client_id { struct guc_preempt_work { struct intel_engine_cs *engine; struct work_struct work; + struct delayed_work lost_irq_work; }; struct intel_guc {