From patchwork Mon Feb 19 22:06:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 10229141 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4E9E1602B1 for ; Mon, 19 Feb 2018 22:06:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 38AFC27B13 for ; Mon, 19 Feb 2018 22:06:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2D39727B81; Mon, 19 Feb 2018 22:06:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9BFD027B13 for ; Mon, 19 Feb 2018 22:06:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 018596E334; Mon, 19 Feb 2018 22:06:44 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from fireflyinternet.com (mail.fireflyinternet.com [109.228.58.192]) by gabe.freedesktop.org (Postfix) with ESMTPS id 02A7A6E334 for ; Mon, 19 Feb 2018 22:06:42 +0000 (UTC) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 10744338-1500050 for multiple; Mon, 19 Feb 2018 22:06:33 +0000 Received: by haswell.alporthouse.com (sSMTP sendmail emulation); Mon, 19 Feb 2018 22:06:32 +0000 From: Chris Wilson To: intel-gfx@lists.freedesktop.org Date: Mon, 19 Feb 2018 22:06:31 +0000 Message-Id: <20180219220631.25001-1-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180219161921.10257-1-chris@chris-wilson.co.uk> References: <20180219161921.10257-1-chris@chris-wilson.co.uk> X-Originating-IP: 78.156.65.138 X-Country: code=GB country="United Kingdom" ip=78.156.65.138 Subject: [Intel-gfx] [PATCH v2] drm/i915: Track number of pending freed objects X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 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-Virus-Scanned: ClamAV using ClamSMTP During igt, we frequently call into the driver to reset both HW and driver state (idling the device, waiting for it to become idle and freeing off old objects) to ensure that we start each test/subtest/pass from known state. This process incurs an RCU barrier or two to ensure that any such pending frees are indeed flushed before we return. However, unconditionally waiting on the RCU barrier adds needless delay to many callers, which adds up to several seconds when repeated thousands of times. We can skip the rcu_barrier() if by tracking how many outstanding frees we have, we know there are none. The same path is used along suspend, where we may be able to save the unconditional RCU barrier. To put it into perspective with a completely meaningless microbenchmark, igt/gem_sync/idle is improved from 50ms to 30us on bdw. v2: Remove the extra synchronize_rcu() inside i915_drop_caches_set() Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +--- drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0cbe154e517d..05b41045b8f9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4079,10 +4079,8 @@ i915_drop_caches_set(void *data, u64 val) if (val & DROP_IDLE) drain_delayed_work(&dev_priv->gt.idle_work); - if (val & DROP_FREED) { - synchronize_rcu(); + if (val & DROP_FREED) i915_gem_drain_freed_objects(dev_priv); - } return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b215c411338..76bfe909168c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1095,6 +1095,11 @@ struct i915_gem_mm { struct llist_head free_list; struct work_struct free_work; spinlock_t free_lock; + /** + * Count of objects pending destructions. Used to skip needlessly + * waiting on an RCU barrier if no objects are waiting to be freed. + */ + atomic_t free_count; /** * Small stash of WC pages @@ -3134,6 +3139,9 @@ void i915_gem_free_object(struct drm_gem_object *obj); static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915) { + if (!atomic_read(&i915->mm.free_count)) + return; + /* A single pass should suffice to release all the freed objects (along * most call paths) , but be a little more paranoid in that freeing * the objects does take a little amount of time, during which the rcu diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f530cd247724..631a2db2bb6e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4758,6 +4758,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, kfree(obj->bit_17); i915_gem_object_free(obj); + GEM_BUG_ON(!atomic_read(&i915->mm.free_count)); + atomic_dec(&i915->mm.free_count); + if (on) cond_resched(); } @@ -4846,6 +4849,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) * i915_gem_busy_ioctl(). For the corresponding synchronized * lookup see i915_gem_object_lookup_rcu(). */ + atomic_inc(&to_i915(obj->base.dev)->mm.free_count); call_rcu(&obj->rcu, __i915_gem_free_object_rcu); } @@ -5546,7 +5550,8 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) { i915_gem_drain_freed_objects(dev_priv); - WARN_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); WARN_ON(dev_priv->mm.object_count); mutex_lock(&dev_priv->drm.struct_mutex);