From patchwork Fri Jun 13 15:37:57 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: oscar.mateo@intel.com X-Patchwork-Id: 4350091 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3000B9F314 for ; Fri, 13 Jun 2014 15:43:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 70F6F2022A for ; Fri, 13 Jun 2014 15:43:34 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 68A4A2026F for ; Fri, 13 Jun 2014 15:43:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F12136EA7D; Fri, 13 Jun 2014 08:43:31 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 63FFE6EA74 for ; Fri, 13 Jun 2014 08:43:31 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 13 Jun 2014 08:43:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.01,471,1400050800"; d="scan'208";a="555136600" Received: from omateolo-linux2.iwi.intel.com ([172.28.253.145]) by fmsmga002.fm.intel.com with ESMTP; 13 Jun 2014 08:43:30 -0700 From: oscar.mateo@intel.com To: intel-gfx@lists.freedesktop.org Date: Fri, 13 Jun 2014 16:37:57 +0100 Message-Id: <1402673891-14618-40-git-send-email-oscar.mateo@intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1402673891-14618-1-git-send-email-oscar.mateo@intel.com> References: <1402673891-14618-1-git-send-email-oscar.mateo@intel.com> Subject: [Intel-gfx] [PATCH 39/53] drm/i915/bdw: Two-stage execlist submit process X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Michel Thierry Context switch (and execlist submission) should happen only when other contexts are not active, otherwise pre-emption occurs. To assure this, we place context switch requests in a queue and those request are later consumed when the right context switch interrupt is received (still TODO). v2: Use a spinlock, do not remove the requests on unqueue (wait for context switch completion). Signed-off-by: Thomas Daniel v3: Several rebases and code changes. Use unique ID. v4: - Move the queue/lock init to the late ring initialization. - Damien's kmalloc review comments: check return, use sizeof(*req), do not cast. v5: - Do not reuse drm_i915_gem_request. Instead, create our own. - New namespace. Signed-off-by: Michel Thierry (v1) Signed-off-by: Oscar Mateo (v2-v5) --- drivers/gpu/drm/i915/intel_lrc.c | 63 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_lrc.h | 8 +++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 ++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index cd4512f..49d3c00 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -214,6 +214,63 @@ static int execlists_submit_context(struct intel_engine_cs *ring, return 0; } +static void execlists_context_unqueue(struct intel_engine_cs *ring) +{ + struct intel_ctx_submit_request *req0 = NULL, *req1 = NULL; + struct intel_ctx_submit_request *cursor = NULL, *tmp = NULL; + + if (list_empty(&ring->execlist_queue)) + return; + + /* Try to read in pairs */ + list_for_each_entry_safe(cursor, tmp, &ring->execlist_queue, execlist_link) { + if (!req0) + req0 = cursor; + else if (req0->ctx == cursor->ctx) { + /* Same ctx: ignore first request, as second request + * will update tail past first request's workload */ + list_del(&req0->execlist_link); + i915_gem_context_unreference(req0->ctx); + kfree(req0); + req0 = cursor; + } else { + req1 = cursor; + break; + } + } + + BUG_ON(execlists_submit_context(ring, req0->ctx, req0->tail, + req1? req1->ctx : NULL, req1? req1->tail : 0)); +} + +static int execlists_context_queue(struct intel_engine_cs *ring, + struct intel_context *to, + u32 tail) +{ + struct intel_ctx_submit_request *req = NULL; + unsigned long flags; + bool was_empty; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (req == NULL) + return -ENOMEM; + req->ctx = to; + i915_gem_context_reference(req->ctx); + req->ring = ring; + req->tail = tail; + + spin_lock_irqsave(&ring->execlist_lock, flags); + + was_empty = list_empty(&ring->execlist_queue); + list_add_tail(&req->execlist_link, &ring->execlist_queue); + if (was_empty) + execlists_context_unqueue(ring); + + spin_unlock_irqrestore(&ring->execlist_lock, flags); + + return 0; +} + static inline struct intel_ringbuffer * logical_ringbuf_get(struct intel_engine_cs *ring, struct intel_context *ctx) { @@ -891,8 +948,7 @@ static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno) static void gen8_submit_ctx(struct intel_engine_cs *ring, struct intel_context *ctx, u32 value) { - /* FIXME: too cheeky, we don't even check if the ELSP is ready */ - execlists_submit_context(ring, ctx, value, NULL, 0); + execlists_context_queue(ring, ctx, value); } static int gen8_emit_request(struct intel_engine_cs *ring, @@ -988,6 +1044,9 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin INIT_LIST_HEAD(&ring->request_list); init_waitqueue_head(&ring->irq_queue); + INIT_LIST_HEAD(&ring->execlist_queue); + spin_lock_init(&ring->execlist_lock); + ret = intel_lr_context_deferred_create(dctx, ring); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index eeb90ec..e1938a3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -44,4 +44,12 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj); bool intel_enable_execlists(struct drm_device *dev); +struct intel_ctx_submit_request { + struct intel_context *ctx; + struct intel_engine_cs *ring; + u32 tail; + + struct list_head execlist_link; +}; + #endif /* _INTEL_LRC_H_ */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index ca02b5d..c3342e1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -156,6 +156,8 @@ struct intel_engine_cs { } semaphore; /* Execlists */ + spinlock_t execlist_lock; + struct list_head execlist_queue; u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ void (*submit_ctx)(struct intel_engine_cs *ring, struct intel_context *ctx, u32 value);