From patchwork Wed Apr 10 00:12:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 2418661 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id D69483FD8C for ; Wed, 10 Apr 2013 00:10:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AA3F3E63BE for ; Tue, 9 Apr 2013 17:10:21 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from shiva.localdomain (unknown [209.20.75.48]) by gabe.freedesktop.org (Postfix) with ESMTP id 946C4E5C13 for ; Tue, 9 Apr 2013 17:10:07 -0700 (PDT) Received: by shiva.localdomain (Postfix, from userid 1005) id 1031288626; Wed, 10 Apr 2013 00:10:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on shiva.chad-versace.us X-Spam-Level: X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00, URIBL_BLOCKED autolearn=unavailable version=3.3.2 Received: from lundgren.ptp (unknown [72.11.84.62]) by shiva.localdomain (Postfix) with ESMTPSA id 87957880AB; Wed, 10 Apr 2013 00:10:03 +0000 (UTC) From: Ben Widawsky To: intel-gfx@lists.freedesktop.org Date: Tue, 9 Apr 2013 17:12:22 -0700 Message-Id: <1365552742-3358-1-git-send-email-ben@bwidawsk.net> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <20130409221823.GA21133@cantiga.alporthouse.com> References: <20130409221823.GA21133@cantiga.alporthouse.com> Cc: Ben Widawsky , Mika Kuoppala Subject: [Intel-gfx] [PATCH] drm/i915: reference count for i915_hw_contexts X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org From: Mika Kuoppala In preparation to do analysis of which context was guilty of gpu hung, store kreffed context pointer into request struct. This allows us to inspect contexts when gpu is reset even if those contexts would already be released by userspace. v2: track i915_hw_context pointers instead of using ctx_ids (from Chris Wilson) v3 (Ben): Get rid of do_release() and handle refcounting more compactly. (recommended by Chis) v4: kref_* put inside static inlines (Daniel Vetter) remove code duplication on freeing context (Chris Wilson) v5: idr_remove and ctx->file_priv = NULL in destroy ioctl (Chris) This actually will cause a problem if one destroys a context and later refers to the idea of the context (multiple contexts may have the same id, but only 1 will exist in the idr). Signed-off-by: Mika Kuoppala (v2) Signed-off-by: Ben Widawsky (v3) Signed-off-by: Mika Kuoppala (v4) Signed-off-by: Ben Widawsky (v5) Tested-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_drv.h | 20 ++++++++++++++++++-- drivers/gpu/drm/i915/i915_gem.c | 27 ++++++++++++++++++++------- drivers/gpu/drm/i915/i915_gem_context.c | 21 ++++++++++++++++----- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 ++++--- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 00a0da8..156c5a0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -456,6 +456,7 @@ struct i915_hw_ppgtt { /* This must match up with the value previously used for execbuf2.rsvd1. */ #define DEFAULT_CONTEXT_ID 0 struct i915_hw_context { + struct kref ref; int id; bool is_initialized; struct drm_i915_file_private *file_priv; @@ -1261,6 +1262,9 @@ struct drm_i915_gem_request { /** Postion in the ringbuffer of the end of the request */ u32 tail; + /** Context related to this request */ + struct i915_hw_context *ctx; + /** Time at which this request was emitted, in jiffies. */ unsigned long emitted_jiffies; @@ -1648,9 +1652,10 @@ int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_idle(struct drm_device *dev); int _i915_add_request(struct intel_ring_buffer *ring, u32 *seqno, - struct drm_file *file); + struct drm_file *file, + struct i915_hw_context *ctx); #define i915_add_request(ring, seqno) \ - _i915_add_request(ring, seqno, NULL) + _i915_add_request(ring, seqno, NULL, NULL) int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); @@ -1694,6 +1699,17 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); struct i915_hw_context * __must_check i915_switch_context(struct intel_ring_buffer *ring, struct drm_file *file, int to_id); +void i915_gem_context_free(struct kref *ctx_ref); +static inline void i915_gem_context_reference(struct i915_hw_context *ctx) +{ + kref_get(&ctx->ref); +} + +static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) +{ + kref_put(&ctx->ref, i915_gem_context_free); +} + int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file); int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4e8d7b2..98b04db 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2001,7 +2001,8 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno) int _i915_add_request(struct intel_ring_buffer *ring, u32 *out_seqno, - struct drm_file *file) + struct drm_file *file, + struct i915_hw_context *ctx) { drm_i915_private_t *dev_priv = ring->dev->dev_private; struct drm_i915_gem_request *request; @@ -2041,6 +2042,11 @@ int _i915_add_request(struct intel_ring_buffer *ring, request->seqno = intel_ring_get_seqno(ring); request->ring = ring; request->tail = request_ring_position; + request->ctx = ctx; + + if (request->ctx) + i915_gem_context_reference(ctx); + request->emitted_jiffies = jiffies; was_empty = list_empty(&ring->request_list); list_add_tail(&request->list, &ring->request_list); @@ -2093,6 +2099,17 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) spin_unlock(&file_priv->mm.lock); } +static void i915_gem_free_request(struct drm_i915_gem_request *request) +{ + list_del(&request->list); + i915_gem_request_remove_from_client(request); + + if (request->ctx) + i915_gem_context_unreference(request->ctx); + + kfree(request); +} + static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, struct intel_ring_buffer *ring) { @@ -2103,9 +2120,7 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, struct drm_i915_gem_request, list); - list_del(&request->list); - i915_gem_request_remove_from_client(request); - kfree(request); + i915_gem_free_request(request); } while (!list_empty(&ring->active_list)) { @@ -2197,9 +2212,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) */ ring->last_retired_head = request->tail; - list_del(&request->list); - i915_gem_request_remove_from_client(request); - kfree(request); + i915_gem_free_request(request); } /* Move any buffers on the active list that are no longer referenced diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 7f36248..747a750 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -126,11 +126,19 @@ static int get_context_size(struct drm_device *dev) static void do_destroy(struct i915_hw_context *ctx) { + drm_gem_object_unreference(&ctx->obj->base); + kfree(ctx); +} + +void i915_gem_context_free(struct kref *ctx_ref) +{ + struct i915_hw_context *ctx = container_of(ctx_ref, + typeof(*ctx), ref); + if (ctx->file_priv) idr_remove(&ctx->file_priv->context_idr, ctx->id); - drm_gem_object_unreference(&ctx->obj->base); - kfree(ctx); + do_destroy(ctx); } static struct i915_hw_context * @@ -145,6 +153,7 @@ create_hw_context(struct drm_device *dev, if (ctx == NULL) return ERR_PTR(-ENOMEM); + kref_init(&ctx->ref); ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); if (ctx->obj == NULL) { kfree(ctx); @@ -282,8 +291,8 @@ static int context_idr_cleanup(int id, void *p, void *data) BUG_ON(id == DEFAULT_CONTEXT_ID); - do_destroy(ctx); - + ctx->file_priv = NULL; + i915_gem_context_unreference(ctx); return 0; } @@ -518,7 +527,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, return -ENOENT; } - do_destroy(ctx); + idr_remove(&ctx->file_priv->context_idr, ctx->id); + ctx->file_priv = NULL; + i915_gem_context_unreference(ctx); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 6624937..dd278ed 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -796,13 +796,14 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects, static void i915_gem_execbuffer_retire_commands(struct drm_device *dev, struct drm_file *file, - struct intel_ring_buffer *ring) + struct intel_ring_buffer *ring, + struct i915_hw_context *ctx) { /* Unconditionally force add_request to emit a full flush. */ ring->gpu_caches_dirty = true; /* Add a breadcrumb for the completion of the batch buffer */ - (void)_i915_add_request(ring, NULL, file); + (void)_i915_add_request(ring, NULL, file, ctx); } static int @@ -1077,7 +1078,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags); i915_gem_execbuffer_move_to_active(&eb->objects, ring); - i915_gem_execbuffer_retire_commands(dev, file, ring); + i915_gem_execbuffer_retire_commands(dev, file, ring, ctx); err: eb_destroy(eb);