From patchwork Fri May 9 12:09:09 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: 4142511 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 ED3419F1E1 for ; Fri, 9 May 2014 12:15:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E44EB201FA for ; Fri, 9 May 2014 12:15:13 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id E3FCF201D3 for ; Fri, 9 May 2014 12:15:12 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6492A6EF87; Fri, 9 May 2014 05:15:12 -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 A21A56EF8A for ; Fri, 9 May 2014 05:15:10 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 09 May 2014 05:15:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="4.97,1018,1389772800"; d="scan'208"; a="529107250" Received: from omateolo-linux2.iwi.intel.com ([172.28.253.145]) by fmsmga001.fm.intel.com with ESMTP; 09 May 2014 05:15:08 -0700 From: oscar.mateo@intel.com To: intel-gfx@lists.freedesktop.org Date: Fri, 9 May 2014 13:09:09 +0100 Message-Id: <1399637360-4277-40-git-send-email-oscar.mateo@intel.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1399637360-4277-1-git-send-email-oscar.mateo@intel.com> References: <1399637360-4277-1-git-send-email-oscar.mateo@intel.com> Cc: Thomas Daniel Subject: [Intel-gfx] [PATCH 39/50] drm/i915/bdw: Get prepared for a 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. Signed-off-by: Michel Thierry 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. Signed-off-by: Oscar Mateo --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++ drivers/gpu/drm/i915/intel_lrc.c | 57 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 ++ 4 files changed, 69 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b39fed..f2aae6a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1745,6 +1745,9 @@ struct drm_i915_gem_request { struct drm_i915_file_private *file_priv; /** file_priv list entry for this request */ struct list_head client_list; + + /** execlist queue entry for this request */ + struct list_head execlist_link; }; struct drm_i915_file_private { @@ -2443,6 +2446,9 @@ static inline u32 intel_get_lr_contextid(struct drm_i915_gem_object *ctx_obj) * (which leaves one HwCtxId bit free) */ return lrca >> 13; } +int gen8_switch_context_queue(struct intel_engine *ring, + struct i915_hw_context *to, + u32 tail); /* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index b06098e..6da7db9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -199,6 +199,63 @@ static int gen8_switch_context(struct intel_engine *ring, return 0; } +static void gen8_switch_context_unqueue(struct intel_engine *ring) +{ + struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; + struct drm_i915_gem_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(gen8_switch_context(ring, req0->ctx, req0->tail, + req1? req1->ctx : NULL, req1? req1->tail : 0)); +} + +int gen8_switch_context_queue(struct intel_engine *ring, + struct i915_hw_context *to, + u32 tail) +{ + struct drm_i915_gem_request *req = NULL; + unsigned long flags; + bool was_empty; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (req == NULL) + return -ENOMEM; + req->ring = ring; + req->ctx = to; + i915_gem_context_reference(req->ctx); + 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) + gen8_switch_context_unqueue(ring); + + spin_unlock_irqrestore(&ring->execlist_lock, flags); + + return 0; +} + struct i915_hw_context * gen8_gem_validate_context(struct drm_device *dev, struct drm_file *file, struct intel_engine *ring, const u32 ctx_id) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 847fec5..35ced7c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1554,6 +1554,9 @@ static int intel_init_ring(struct drm_device *dev, init_waitqueue_head(&ring->irq_queue); + INIT_LIST_HEAD(&ring->execlist_queue); + spin_lock_init(&ring->execlist_lock); + if (dev_priv->lrc_enabled) { struct drm_i915_gem_object *obj; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 709b1f1..daf91de 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -176,6 +176,9 @@ struct intel_engine { wait_queue_head_t irq_queue; + spinlock_t execlist_lock; + struct list_head execlist_queue; + struct i915_hw_context *default_context; struct i915_hw_context *last_context;