From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Hellstrom Subject: [PATCH -fixes 2/2] drm/ttm: Fix a theoretical race in ttm_bo_cleanup_refs() Date: Mon, 22 Oct 2012 14:51:26 +0200 Message-ID: <1350910286-8073-3-git-send-email-thellstrom@vmware.com> References: <1350910286-8073-1-git-send-email-thellstrom@vmware.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from smtp-outbound-2.vmware.com (smtp-outbound-2.vmware.com [208.91.2.13]) by gabe.freedesktop.org (Postfix) with ESMTP id 7F8779E7D9 for ; Mon, 22 Oct 2012 05:51:49 -0700 (PDT) In-Reply-To: <1350910286-8073-1-git-send-email-thellstrom@vmware.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org To: airlied@gmail.com, airlied@redhat.com Cc: Thomas Hellstrom , dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org In theory, that function could release the lru lock between checking for bo on ddestroy list and a successful reserve if the bo was already reserved, and the function was called with waiting reserves allowed. However, all current reservers of a bo on the ddestroy list would atomically take the bo off the list after a successful reserve so this race should not have been hit, so no need to backport for stable. This patch also fixes a case found by Maarten Lankhorst where ttm_mem_evict_first called with no_wait_gpu would incorrectly spin waiting for bo idle if trying to evict a busy buffer that also sits on the ddestroy list. Signed-off-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_bo.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d42631c..043cd33 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -580,6 +580,7 @@ retry: if (unlikely(ret != 0)) return ret; +retry_reserve: spin_lock(&glob->lru_lock); if (unlikely(list_empty(&bo->ddestroy))) { @@ -587,14 +588,20 @@ retry: return 0; } - ret = ttm_bo_reserve_locked(bo, interruptible, - no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0); - if (unlikely(ret != 0)) { + if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - return ret; + if (likely(!no_wait_reserve)) + ret = ttm_bo_wait_unreserved(bo, interruptible); + if (unlikely(ret != 0)) + return ret; + + goto retry_reserve; } + BUG_ON(ret != 0); + /** * We can re-check for sync object without taking * the bo::lock since setting the sync object requires @@ -810,11 +817,8 @@ retry: ret = ttm_bo_cleanup_refs(bo, interruptible, no_wait_reserve, no_wait_gpu); kref_put(&bo->list_kref, ttm_bo_release_list); - - if (likely(ret == 0 || ret == -ERESTARTSYS)) - return ret; - - goto retry; + + return ret; } ret = ttm_bo_reserve_locked(bo, false, true, false, 0); -- 1.7.4.4