From patchwork Thu Feb 12 20:05:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rafael.barbalho@intel.com X-Patchwork-Id: 5821941 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A1642BF440 for ; Thu, 12 Feb 2015 20:05:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7DD212022A for ; Thu, 12 Feb 2015 20:05:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 4D96320254 for ; Thu, 12 Feb 2015 20:05:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DA73E6E74A; Thu, 12 Feb 2015 12:05:51 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id DA7916E74A for ; Thu, 12 Feb 2015 12:05:49 -0800 (PST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga102.jf.intel.com with ESMTP; 12 Feb 2015 12:01:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.09,566,1418112000"; d="scan'208";a="526756189" Received: from rbarbalh-linux.isw.intel.com ([10.102.226.86]) by orsmga003.jf.intel.com with ESMTP; 12 Feb 2015 11:57:05 -0800 From: rafael.barbalho@intel.com To: intel-gfx@lists.freedesktop.org Date: Thu, 12 Feb 2015 20:05:02 +0000 Message-Id: <1423771502-9766-3-git-send-email-rafael.barbalho@intel.com> X-Mailer: git-send-email 2.3.0 In-Reply-To: <1423771502-9766-1-git-send-email-rafael.barbalho@intel.com> References: <1423771502-9766-1-git-send-email-rafael.barbalho@intel.com> Subject: [Intel-gfx] [RFC 2/2] drm/i915: Clean-up PPGTT on context destruction 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: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_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: Rafael Barbalho With full PPGTT enabled an object's VMA entry into a PPGTT VM needs to be cleaned up so that the PPGTT PDE & PTE allocations can be freed. This problem only shows up with full PPGTT because an object's VMA is only cleaned-up when the object is destroyed. However, if the object has been shared between multiple processes this may not happen, which leads to references to the PPGTT still being kept the object was shared. Under android the sharing of GEM objects is a fairly common operation, thus the clean-up has to be more agressive. Signed-off-by: Rafael Barbalho Cc: Daniel Vetter Cc: Jon Bloomfield --- drivers/gpu/drm/i915/i915_gem.c | 7 +++--- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 43 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_gem_gtt.h | 7 ++++++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 60b8bd1..e509d89 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4529,11 +4529,12 @@ void i915_gem_vma_destroy(struct i915_vma *vma) return; vm = vma->vm; + list_del(&vma->vma_link); - if (!i915_is_ggtt(vm)) + if (!i915_is_ggtt(vm)) { + list_del(&vma->vm_link); i915_ppgtt_put(i915_vm_to_ppgtt(vm)); - - list_del(&vma->vma_link); + } kfree(vma); } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index a5221d8..4319a93 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -140,7 +140,7 @@ void i915_gem_context_free(struct kref *ctx_ref) if (i915.enable_execlists) intel_lr_context_free(ctx); - i915_ppgtt_put(ctx->ppgtt); + i915_ppgtt_destroy(ctx->ppgtt); if (ctx->legacy_hw_ctx.rcs_state) drm_gem_object_unreference(&ctx->legacy_hw_ctx.rcs_state->base); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6f410cf..9ef2f67 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1097,6 +1097,7 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) else BUG(); } + int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1108,6 +1109,8 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, ppgtt->base.total); i915_init_vm(dev_priv, &ppgtt->base); + + INIT_LIST_HEAD(&ppgtt->vma_list); } return ret; @@ -1177,14 +1180,49 @@ void i915_ppgtt_release(struct kref *kref) /* vmas should already be unbound */ WARN_ON(!list_empty(&ppgtt->base.active_list)); WARN_ON(!list_empty(&ppgtt->base.inactive_list)); + WARN_ON(!list_empty(&ppgtt->vma_list)); list_del(&ppgtt->base.global_link); drm_mm_takedown(&ppgtt->base.mm); ppgtt->base.cleanup(&ppgtt->base); + kfree(ppgtt); } +void +i915_ppgtt_destroy(struct i915_hw_ppgtt *ppgtt) +{ + struct i915_vma *vma, *tmp; + struct i915_address_space *vm; + int ret; + + if (!ppgtt) + return; + + vm = &ppgtt->base; + + /* + * If this fires it means that the context reference counting went + * awry. + */ + WARN_ON(!list_empty(&ppgtt->base.active_list)); + + if (!list_empty(&ppgtt->vma_list)) + list_for_each_entry_safe(vma, tmp, &ppgtt->vma_list, vm_link) { + WARN_ON(vma->pin_count != 0); + /* + * The object should be inactive at this point, thus + * its pin_count should be 0. We will zero it anyway + * make sure that the unbind call succeeds. + */ + vma->pin_count = 0; + ret = i915_vma_unbind(vma); + } + + i915_ppgtt_put(ppgtt); +} + static void ppgtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, @@ -2109,6 +2147,7 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&vma->vma_link); + INIT_LIST_HEAD(&vma->vm_link); INIT_LIST_HEAD(&vma->mm_list); INIT_LIST_HEAD(&vma->exec_list); vma->vm = vm; @@ -2142,8 +2181,10 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, if (i915_is_ggtt(vm)) list_add(&vma->vma_link, &obj->vma_list); else { + struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); list_add_tail(&vma->vma_link, &obj->vma_list); - i915_ppgtt_get(i915_vm_to_ppgtt(vm)); + i915_ppgtt_get(ppgtt); + list_add_tail(&vma->vm_link, &ppgtt->vma_list); } return vma; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index d5c14af..323bbc6 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -128,6 +128,8 @@ struct i915_vma { struct list_head vma_link; /* Link in the object's VMA list */ + struct list_head vm_link; /* Link in the VM's VMA list */ + /** This vma's place in the batchbuffer or on the eviction list */ struct list_head exec_list; @@ -149,6 +151,7 @@ struct i915_vma { * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3 * bits with absolutely no headroom. So use 4 bits. */ unsigned int pin_count:4; + #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf /** Unmap an object from an address space. This usually consists of @@ -262,6 +265,8 @@ struct i915_hw_ppgtt { struct drm_i915_file_private *file_priv; + struct list_head vma_list; + int (*enable)(struct i915_hw_ppgtt *ppgtt); int (*switch_mm)(struct i915_hw_ppgtt *ppgtt, struct intel_engine_cs *ring); @@ -280,6 +285,8 @@ int i915_ppgtt_init_hw(struct drm_device *dev); void i915_ppgtt_release(struct kref *kref); struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_device *dev, struct drm_i915_file_private *fpriv); +void i915_ppgtt_destroy(struct i915_hw_ppgtt *ppgtt); + static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) { if (ppgtt)