[kernel] r16974 - in dists/squeeze/linux-2.6/debian: . patches/bugfix/all patches/series

Maximilian Attems maks at alioth.debian.org
Thu Mar 3 10:43:35 UTC 2011


Author: maks
Date: Thu Mar  3 10:43:33 2011
New Revision: 16974

Log:
drm/ttm: Fix two race conditions + fix busy codepaths

will test on my desktop next 2 days, backport was easy enough to be worth.

Added:
   dists/squeeze/linux-2.6/debian/patches/bugfix/all/drm-ttm-Fix-two-race-conditions-fix-busy-codepaths.patch
Modified:
   dists/squeeze/linux-2.6/debian/changelog
   dists/squeeze/linux-2.6/debian/patches/series/31

Modified: dists/squeeze/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze/linux-2.6/debian/changelog	Thu Mar  3 00:56:01 2011	(r16973)
+++ dists/squeeze/linux-2.6/debian/changelog	Thu Mar  3 10:43:33 2011	(r16974)
@@ -78,6 +78,7 @@
   * [xen] do not release any memory under 1M in domain 0. (closes: #613823)
   * virtio: set pci bus master enable bit. (closes: #610360)
   * sctp: Fix oops when sending queued ASCONF chunks (CVE-2010-1173).
+  * drm/ttm: Fix two race conditions + fix busy codepaths (closes: #591061)
 
   [ Aurelien Jarno ]
   * init: fix race between init and kthreadd, fixes a kernel panic on 

Added: dists/squeeze/linux-2.6/debian/patches/bugfix/all/drm-ttm-Fix-two-race-conditions-fix-busy-codepaths.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/bugfix/all/drm-ttm-Fix-two-race-conditions-fix-busy-codepaths.patch	Thu Mar  3 10:43:33 2011	(r16974)
@@ -0,0 +1,173 @@
+From: Thomas Hellstrom <thellstrom at vmware.com>
+Date: Thu, 30 Sep 2010 12:36:45 +0200
+Subject: [PATCH] drm/ttm: Fix two race conditions + fix busy codepaths
+
+commit 1df6a2ebd75067aefbdf07482bf8e3d0584e04ee upstream.
+
+This fixes a race pointed out by Dave Airlie where we don't take a buffer
+object about to be destroyed off the LRU lists properly. It also fixes a rare
+case where a buffer object could be destroyed in the middle of an
+accelerated eviction.
+
+The patch also adds a utility function that can be used to prematurely
+release GPU memory space usage of an object waiting to be destroyed.
+For example during eviction or swapout.
+
+The above mentioned commit didn't queue the buffer on the delayed destroy
+list under some rare circumstances. It also didn't completely honor the
+remove_all parameter.
+
+Fixes:
+https://bugzilla.redhat.com/show_bug.cgi?id=615505
+http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=591061
+
+Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
+Signed-off-by: Dave Airlie <airlied at redhat.com>
+[ Backported to 2.6.33 -maks ]
+---
+ drivers/gpu/drm/ttm/ttm_bo.c |   83 ++++++++++++++++++++++++++++++++++++------
+ include/drm/ttm/ttm_bo_api.h |    4 ++-
+ 2 files changed, 74 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
+index cb4cf7e..db809e0 100644
+--- a/drivers/gpu/drm/ttm/ttm_bo.c
++++ b/drivers/gpu/drm/ttm/ttm_bo.c
+@@ -442,6 +442,43 @@ out_err:
+ }
+ 
+ /**
++ * Call bo::reserved and with the lru lock held.
++ * Will release GPU memory type usage on destruction.
++ * This is the place to put in driver specific hooks.
++ * Will release the bo::reserved lock and the
++ * lru lock on exit.
++ */
++
++static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
++{
++	struct ttm_bo_global *glob = bo->glob;
++
++	if (bo->ttm) {
++
++		/**
++		 * Release the lru_lock, since we don't want to have
++		 * an atomic requirement on ttm_tt[unbind|destroy].
++		 */
++
++		spin_unlock(&glob->lru_lock);
++		ttm_tt_unbind(bo->ttm);
++		ttm_tt_destroy(bo->ttm);
++		bo->ttm = NULL;
++		spin_lock(&glob->lru_lock);
++	}
++
++	if (bo->mem.mm_node) {
++		drm_mm_put_block(bo->mem.mm_node);
++		bo->mem.mm_node = NULL;
++	}
++
++	atomic_set(&bo->reserved, 0);
++	wake_up_all(&bo->event_queue);
++	spin_unlock(&glob->lru_lock);
++}
++
++
++/**
+  * If bo idle, remove from delayed- and lru lists, and unref.
+  * If not idle, and already on delayed list, do nothing.
+  * If not idle, and not on delayed list, put on delayed list,
+@@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
+ 	int ret;
+ 
+ 	spin_lock(&bo->lock);
++retry:
+ 	(void) ttm_bo_wait(bo, false, false, !remove_all);
+ 
+ 	if (!bo->sync_obj) {
+@@ -464,32 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
+ 		spin_unlock(&bo->lock);
+ 
+ 		spin_lock(&glob->lru_lock);
+-		put_count = ttm_bo_del_from_lru(bo);
++		ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0);
++
++		/**
++		 * Someone else has the object reserved. Bail and retry.
++		 */
+ 
+-		ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
+-		BUG_ON(ret);
+-		if (bo->ttm)
+-			ttm_tt_unbind(bo->ttm);
++		if (unlikely(ret == -EBUSY)) {
++			spin_unlock(&glob->lru_lock);
++			spin_lock(&bo->lock);
++			goto requeue;
++		}
++
++		/**
++		 * We can re-check for sync object without taking
++		 * the bo::lock since setting the sync object requires
++		 * also bo::reserved. A busy object at this point may
++		 * be caused by another thread starting an accelerated
++		 * eviction.
++		 */
++
++		if (unlikely(bo->sync_obj)) {
++			atomic_set(&bo->reserved, 0);
++			wake_up_all(&bo->event_queue);
++			spin_unlock(&glob->lru_lock);
++			spin_lock(&bo->lock);
++			if (remove_all)
++				goto retry;
++			else
++				goto requeue;
++		}
++
++		put_count = ttm_bo_del_from_lru(bo);
+ 
+ 		if (!list_empty(&bo->ddestroy)) {
+ 			list_del_init(&bo->ddestroy);
+ 			++put_count;
+ 		}
+-		if (bo->mem.mm_node) {
+-			bo->mem.mm_node->private = NULL;
+-			drm_mm_put_block(bo->mem.mm_node);
+-			bo->mem.mm_node = NULL;
+-		}
+-		spin_unlock(&glob->lru_lock);
+ 
+-		atomic_set(&bo->reserved, 0);
++		ttm_bo_cleanup_memtype_use(bo);
+ 
+ 		while (put_count--)
+ 			kref_put(&bo->list_kref, ttm_bo_ref_bug);
+ 
+ 		return 0;
+ 	}
+-
++requeue:
+ 	spin_lock(&glob->lru_lock);
+ 	if (list_empty(&bo->ddestroy)) {
+ 		void *sync_obj = bo->sync_obj;
+diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
+index 267a86c..2040e6c 100644
+--- a/include/drm/ttm/ttm_bo_api.h
++++ b/include/drm/ttm/ttm_bo_api.h
+@@ -246,9 +246,11 @@ struct ttm_buffer_object {
+ 
+ 	atomic_t reserved;
+ 
+-
+ 	/**
+ 	 * Members protected by the bo::lock
++	 * In addition, setting sync_obj to anything else
++	 * than NULL requires bo::reserved to be held. This allows for
++	 * checking NULL while reserved but not holding bo::lock.
+ 	 */
+ 
+ 	void *sync_obj_arg;
+-- 
+1.7.2.3
+

Modified: dists/squeeze/linux-2.6/debian/patches/series/31
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/series/31	Thu Mar  3 00:56:01 2011	(r16973)
+++ dists/squeeze/linux-2.6/debian/patches/series/31	Thu Mar  3 10:43:33 2011	(r16974)
@@ -46,3 +46,4 @@
 + bugfix/all/netxen-fix-set-mac-addr.patch
 + bugfix/all/virtio-set-pci-bus-master-enable-bit.patch
 + bugfix/all/sctp-Fix-oops-when-sending-queued-ASCONF-chunks.patch
++ bugfix/all/drm-ttm-Fix-two-race-conditions-fix-busy-codepaths.patch



More information about the Kernel-svn-changes mailing list