From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: [PATCH] drm/i915: adjust fence registers asynchronously on tiling changes v2 Date: Fri, 23 Apr 2010 00:28:29 +0200 Message-ID: <1271975309-2159-1-git-send-email-daniel.vetter@ffwll.ch> References: <1271967172-3174-4-git-send-email-daniel.vetter@ffwll.ch> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from localhost.localdomain (cable-static-49-187.intergga.ch [157.161.49.187]) by gabe.freedesktop.org (Postfix) with ESMTP id 9E25E9E817 for ; Thu, 22 Apr 2010 15:27:47 -0700 (PDT) In-Reply-To: <1271967172-3174-4-git-send-email-daniel.vetter@ffwll.ch> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org To: Eric Anholt Cc: Daniel Vetter , intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org This avoids stalling on the gpu. With the preparation from the previous patch, this is really just a small change. Thanks to Owain Ainsworth for coming up with the idea for this patch and hashing out the implementation with me on irc. v2: Reset obj_priv->fence_invalid in put_fence. No functional change because put_fence checks whether there is actually a fence allocated, so the put_fence in adjust_fencing won't harm. But IMHO the code makes slightly more sense this way around. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_gem.c | 10 ++++++++++ drivers/gpu/drm/i915/i915_gem_tiling.c | 26 ++++++-------------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7aec3ec..174269c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -698,6 +698,12 @@ struct drm_i915_gem_object { */ int fence_reg; + /** + * Tiling changes can happen asynchronously to avoid gpu stalls. + * This will be set if the current fencing may be invalid. + */ + int fence_invalid; + /** How many users have pinned this object in GTT space */ int pin_count; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8e73a12..023f4db 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2485,6 +2485,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) struct drm_i915_fence_reg *reg = NULL; int ret; + BUG_ON(obj_priv->fence_invalid); + /* Just update our place in the LRU if our fence is getting used. */ if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list); @@ -2554,6 +2556,12 @@ i915_gem_object_adjust_fencing(struct drm_gem_object *obj) struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int ret; + if (obj_priv->fence_invalid) { + ret = i915_gem_object_put_fence_reg(obj); + if (ret != 0) + return ret; + } + if (!i915_gem_object_fence_offset_ok(obj, obj_priv->tiling_mode)) { ret = i915_gem_object_unbind(obj); if (ret != 0) @@ -2621,6 +2629,8 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + obj_priv->fence_invalid = 0; + if (obj_priv->fence_reg == I915_FENCE_REG_NONE) return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 00f264d..aadaaa6 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -322,30 +322,16 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); if (args->tiling_mode != obj_priv->tiling_mode || args->stride != obj_priv->stride) { - /* We need to rebind the object if its current allocation - * no longer meets the alignment restrictions for its new - * tiling mode. Otherwise we can just leave it alone, but - * need to ensure that any fence register is cleared. - */ - if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) - ret = i915_gem_object_unbind(obj); - else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - ret = i915_gem_object_put_fence_reg(obj); - else - i915_gem_release_mmap(obj); - - if (ret != 0) { - WARN(ret != -ERESTARTSYS, - "failed to reset object for tiling switch"); - args->tiling_mode = obj_priv->tiling_mode; - args->stride = obj_priv->stride; - goto err; - } + /* Change tiling parameter asynchronously to avoid + * gpu stalls. */ + obj_priv->fence_invalid = 1; + + i915_gem_release_mmap(obj); obj_priv->tiling_mode = args->tiling_mode; obj_priv->stride = args->stride; } -err: + drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); -- 1.6.6.1