[prev in list] [next in list] [prev in thread] [next in thread] 

List:       dri-patches
Subject:    drm: Branch 'master' - 8 commits
From:       thomash () kemper ! freedesktop ! org (Thomas Hellstrom)
Date:       2008-03-12 9:29:47
Message-ID: 20080312092948.06C0810096 () kemper ! freedesktop ! org
[Download RAW message or body]

 linux-core/drmP.h        |    4 ++
 linux-core/drm_bo.c      |   70 ++++++++++++++++++++++++++++++++---------------
 linux-core/drm_bo_move.c |    3 --
 linux-core/drm_fence.c   |    4 ++
 linux-core/drm_memory.c  |   51 +++++++++++++++++++++++++++++-----
 linux-core/drm_proc.c    |   14 ++++++++-
 shared-core/i915_dma.c   |   28 +++++++++++-------
 shared-core/i915_drv.h   |    2 +
 8 files changed, 130 insertions(+), 46 deletions(-)

New commits:
commit 5bebcd7a0b548b29a9859b2949b06662968cc868
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:19:36 2008 +0100

    Dont allow !sysadmin clients to alter the memory type of
    NO_EVICT buffers.

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 2e21004..a94bd8a 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -979,6 +979,20 @@ static int drm_bo_modify_proposed_flags (struct drm_buffer_object *bo,
 		return -EPERM;
 	}
 
+	if (likely(new_mask & DRM_BO_MASK_MEM) &&
+	    (bo->mem.flags & DRM_BO_FLAG_NO_EVICT) &&
+	    !DRM_SUSER(DRM_CURPROC)) {
+		if (likely(bo->mem.flags & new_flags & new_mask &
+			   DRM_BO_MASK_MEM))
+			new_flags = (new_flags & ~DRM_BO_MASK_MEM) |
+				(bo->mem.flags & DRM_BO_MASK_MEM);
+		else {
+			DRM_ERROR("Incompatible memory type specification "
+				  "for NO_EVICT buffer.\n");
+			return -EPERM;
+		}
+	}
+
 	if ((new_flags & DRM_BO_FLAG_NO_MOVE)) {
 		DRM_ERROR("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n");
 		return -EPERM;
commit 88be276a427124cc545a7d89b137e4ae6dd79acb
Author: Alan Hourihane <alanh@tungstengraphics.com>
Date:   Thu Jan 17 13:04:42 2008 +0000

    Fix for debug memory routines

diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c
index 1a6c48d..12e0141 100644
--- a/linux-core/drm_memory.c
+++ b/linux-core/drm_memory.c
@@ -326,7 +326,12 @@ static void *agp_remap(unsigned long offset, unsigned long size,
 	return NULL;
 }
 #endif				/* agp */
-
+#else
+static void *agp_remap(unsigned long offset, unsigned long size,
+		       struct drm_device * dev)
+{
+	return NULL;
+}
 #endif				/* debug_memory */
 
 void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
commit 32625774072f905d15024cc40ce7fd364d9ee4cd
Author: Alan Hourihane <alanh@tungstengraphics.com>
Date:   Thu Jan 17 13:04:23 2008 +0000

    Add error message

diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index 9d80327..0ca0c40 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -520,8 +520,10 @@ int drm_fence_object_create(struct drm_device *dev, uint32_t fence_class,
 	struct drm_fence_manager *fm = &dev->fm;
 
 	fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
-	if (!fence)
+	if (!fence) {
+		DRM_ERROR("Out of memory creating fence object\n");
 		return -ENOMEM;
+	}
 	ret = drm_fence_object_init(dev, fence_class, type, flags, fence);
 	if (ret) {
 		drm_fence_usage_deref_unlocked(&fence);
commit c0a1cd052ac44d1b342fa3f26afe1bd21d92b194
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Thu Jan 17 13:10:36 2008 +0100

    Add an emergency pinnable memory quota for root-only processes.

diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 1fea807..2f76f3d 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1001,8 +1001,10 @@ extern int drm_unbind_agp(DRM_AGP_MEM * handle);
 extern void drm_free_memctl(size_t size);
 extern int drm_alloc_memctl(size_t size);
 extern void drm_query_memctl(uint64_t *cur_used,
+			     uint64_t *emer_used,
 			     uint64_t *low_threshold,
-			     uint64_t *high_threshold);
+			     uint64_t *high_threshold,
+			     uint64_t *emer_threshold);
 extern void drm_init_memctl(size_t low_threshold,
 			    size_t high_threshold,
 			    size_t unit_size);
diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c
index 402a680..1a6c48d 100644
--- a/linux-core/drm_memory.c
+++ b/linux-core/drm_memory.c
@@ -39,8 +39,10 @@
 static struct {
 	spinlock_t lock;
 	uint64_t cur_used;
+	uint64_t emer_used;
 	uint64_t low_threshold;
 	uint64_t high_threshold;
+	uint64_t emer_threshold;
 } drm_memctl = {
 	.lock = SPIN_LOCK_UNLOCKED
 };
@@ -59,14 +61,30 @@ static inline size_t drm_size_align(size_t size)
 
 int drm_alloc_memctl(size_t size)
 {
-	int ret;
+	int ret = 0;
 	unsigned long a_size = drm_size_align(size);
+	unsigned long new_used = drm_memctl.cur_used + a_size;
 
 	spin_lock(&drm_memctl.lock);
-	ret = ((drm_memctl.cur_used + a_size) > drm_memctl.high_threshold) ?
-		-ENOMEM : 0;
-	if (!ret)
-		drm_memctl.cur_used += a_size;
+	if (unlikely(new_used > drm_memctl.high_threshold)) {
+		if (!DRM_SUSER(DRM_CURPROC) ||
+		    (new_used + drm_memctl.emer_used > drm_memctl.emer_threshold) ||
+		    (a_size > 2*PAGE_SIZE)) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		/*
+		 * Allow small root-only allocations, even if the
+		 * high threshold is exceeded.
+		 */
+
+		new_used -= drm_memctl.high_threshold;
+		drm_memctl.emer_used += new_used;
+		a_size -= new_used;
+	}
+	drm_memctl.cur_used += a_size;
+out:
 	spin_unlock(&drm_memctl.lock);
 	return ret;
 }
@@ -77,19 +95,30 @@ void drm_free_memctl(size_t size)
 	unsigned long a_size = drm_size_align(size);
 
 	spin_lock(&drm_memctl.lock);
+	if (likely(a_size >= drm_memctl.emer_used)) {
+		a_size -= drm_memctl.emer_used;
+		drm_memctl.emer_used = 0;
+	} else {
+		drm_memctl.emer_used -= a_size;
+		a_size = 0;
+	}
 	drm_memctl.cur_used -= a_size;
 	spin_unlock(&drm_memctl.lock);
 }
 EXPORT_SYMBOL(drm_free_memctl);
 
 void drm_query_memctl(uint64_t *cur_used,
+		      uint64_t *emer_used,
 		      uint64_t *low_threshold,
-		      uint64_t *high_threshold)
+		      uint64_t *high_threshold,
+		      uint64_t *emer_threshold)
 {
 	spin_lock(&drm_memctl.lock);
 	*cur_used = drm_memctl.cur_used;
+	*emer_used = drm_memctl.emer_used;
 	*low_threshold = drm_memctl.low_threshold;
 	*high_threshold = drm_memctl.high_threshold;
+	*emer_threshold = drm_memctl.emer_threshold;
 	spin_unlock(&drm_memctl.lock);
 }
 EXPORT_SYMBOL(drm_query_memctl);
@@ -99,9 +128,12 @@ void drm_init_memctl(size_t p_low_threshold,
 		     size_t unit_size)
 {
 	spin_lock(&drm_memctl.lock);
+	drm_memctl.emer_used = 0;
 	drm_memctl.cur_used = 0;
 	drm_memctl.low_threshold = p_low_threshold * unit_size;
 	drm_memctl.high_threshold = p_high_threshold * unit_size;
+	drm_memctl.emer_threshold = (drm_memctl.high_threshold >> 4) +
+		drm_memctl.high_threshold;
 	spin_unlock(&drm_memctl.lock);
 }
 
diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c
index 67afee8..42da5c6 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -445,9 +445,10 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
 	struct drm_buffer_manager *bm = &dev->bm;
 	struct drm_fence_manager *fm = &dev->fm;
 	uint64_t used_mem;
+	uint64_t used_emer;
 	uint64_t low_mem;
 	uint64_t high_mem;
-
+	uint64_t emer_mem;
 
 	if (offset > DRM_PROC_LIMIT) {
 		*eof = 1;
@@ -476,7 +477,7 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
 		DRM_PROC_PRINT("Buffer objects are not supported by this driver.\n");
 	}
 
-	drm_query_memctl(&used_mem, &low_mem, &high_mem);
+	drm_query_memctl(&used_mem, &used_emer, &low_mem, &high_mem, &emer_mem);
 
 	if (used_mem > 16*PAGE_SIZE) {
 		DRM_PROC_PRINT("Used object memory is %lu pages.\n",
@@ -485,10 +486,19 @@ static int drm__objects_info(char *buf, char **start, off_t offset, int request,
 		DRM_PROC_PRINT("Used object memory is %lu bytes.\n",
 			       (unsigned long) used_mem);
 	}
+	if (used_emer > 16*PAGE_SIZE) {
+		DRM_PROC_PRINT("Used emergency memory is %lu pages.\n",
+			       (unsigned long) (used_emer >> PAGE_SHIFT));
+	} else {
+		DRM_PROC_PRINT("Used emergency memory is %lu bytes.\n\n",
+			       (unsigned long) used_emer);
+	}
 	DRM_PROC_PRINT("Soft object memory usage threshold is %lu pages.\n",
 		       (unsigned long) (low_mem >> PAGE_SHIFT));
 	DRM_PROC_PRINT("Hard object memory usage threshold is %lu pages.\n",
 		       (unsigned long) (high_mem >> PAGE_SHIFT));
+	DRM_PROC_PRINT("Emergency root only memory usage threshold is %lu pages.\n",
+		       (unsigned long) (emer_mem >> PAGE_SHIFT));
 
 	DRM_PROC_PRINT("\n");
 
commit 7bcce66a1d5c93ff9b9f20d45d5b2c33c8ca8da9
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:07:56 2008 +0100

    Fix kernel crash when we hit OOM conditions.
    (Alan Hourihane)

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 51cd175..2e21004 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -789,6 +789,11 @@ static int drm_bo_mem_force_space(struct drm_device *dev,
 	}
 
 	node = drm_mm_get_block(node, num_pages, mem->page_alignment);
+	if (unlikely(!node)) {
+		mutex_unlock(&dev->struct_mutex);
+		return -ENOMEM;
+	}
+
 	mutex_unlock(&dev->struct_mutex);
 	mem->mm_node = node;
 	mem->mem_type = mem_type;
@@ -1482,6 +1487,9 @@ static int drm_buffer_object_validate(struct drm_buffer_object *bo,
 		if (ret) {
 			if (ret != -EAGAIN)
 				DRM_ERROR("Failed moving buffer.\n");
+			if (ret == -ENOMEM)
+				DRM_ERROR("Out of aperture space or "
+					  "DRM memory quota.\n");
 			return ret;
 		}
 	}
@@ -2747,7 +2755,7 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
 	list->file_offset_node = drm_mm_search_free(&dev->offset_manager,
 						    bo->mem.num_pages, 0, 0);
 
-	if (!list->file_offset_node) {
+	if (unlikely(!list->file_offset_node)) {
 		drm_bo_takedown_vm_locked(bo);
 		return -ENOMEM;
 	}
@@ -2755,6 +2763,11 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo)
 	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
 						  bo->mem.num_pages, 0);
 
+	if (unlikely(!list->file_offset_node)) {
+		drm_bo_takedown_vm_locked(bo);
+		return -ENOMEM;
+	}
+		
 	list->hash.key = list->file_offset_node->start;
 	if (drm_ht_insert_item(&dev->map_hash, &list->hash)) {
 		drm_bo_takedown_vm_locked(bo);
commit f1a681ebe5573c2ec7806ba4cb754314baef6935
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 10:02:09 2008 +0100

    Avoid duplicate calls to drm_ttm_bind in some cases.

diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index fd3cf9d..51cd175 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -208,36 +208,35 @@ static int drm_bo_handle_move_mem(struct drm_buffer_object *bo,
 			if (ret)
 				goto out_err;
 		}
-	}
-
-	if ((bo->mem.mem_type == DRM_BO_MEM_LOCAL) && bo->ttm == NULL) {
-
-		struct drm_bo_mem_reg *old_mem = &bo->mem;
-		uint64_t save_flags = old_mem->flags;
-		uint64_t save_proposed_flags = old_mem->proposed_flags;
-
-		*old_mem = *mem;
-		mem->mm_node = NULL;
-		old_mem->proposed_flags = save_proposed_flags;
-		DRM_FLAG_MASKED(save_flags, mem->flags, DRM_BO_MASK_MEMTYPE);
 
-	} else if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
-		   !(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED)) {
+		if (bo->mem.mem_type == DRM_BO_MEM_LOCAL) {
+			
+			struct drm_bo_mem_reg *old_mem = &bo->mem;
+			uint64_t save_flags = old_mem->flags;
+			uint64_t save_proposed_flags = old_mem->proposed_flags;
+			
+			*old_mem = *mem;
+			mem->mm_node = NULL;
+			old_mem->proposed_flags = save_proposed_flags;
+			DRM_FLAG_MASKED(save_flags, mem->flags,
+					DRM_BO_MASK_MEMTYPE);
+			goto moved;
+		}
+		
+	}
 
+	if (!(old_man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
+	    !(new_man->flags & _DRM_FLAG_MEMTYPE_FIXED))		
 		ret = drm_bo_move_ttm(bo, evict, no_wait, mem);
-
-	} else if (dev->driver->bo_driver->move) {
+	else if (dev->driver->bo_driver->move) 
 		ret = dev->driver->bo_driver->move(bo, evict, no_wait, mem);
-
-	} else {
-
+	else
 		ret = drm_bo_move_memcpy(bo, evict, no_wait, mem);
 
-	}
-
 	if (ret)
 		goto out_err;
 
+moved:
 	if (old_is_pci || new_is_pci)
 		drm_bo_vm_post_move(bo);
 
commit fa1d88e3b2de843f33c9d77c9d95db762a950a14
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Wed Mar 12 09:56:06 2008 +0100

    Make sure other TTM memory types than TT is really unbound when evicted.

diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index 30e0f43..21673da 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -42,7 +42,6 @@ static void drm_bo_free_old_node(struct drm_buffer_object *bo)
 	if (old_mem->mm_node && (old_mem->mm_node != bo->pinned_node)) {
 		mutex_lock(&bo->dev->struct_mutex);
 		drm_mm_put_block(old_mem->mm_node);
-		old_mem->mm_node = NULL;
 		mutex_unlock(&bo->dev->struct_mutex);
 	}
 	old_mem->mm_node = NULL;
@@ -57,7 +56,7 @@ int drm_bo_move_ttm(struct drm_buffer_object *bo,
 	uint64_t save_proposed_flags = old_mem->proposed_flags;
 	int ret;
 
-	if (old_mem->mem_type == DRM_BO_MEM_TT) {
+	if (old_mem->mem_type != DRM_BO_MEM_LOCAL) {
 		if (evict)
 			drm_ttm_evict(ttm);
 		else
commit 8a18d123f55a7fb11ce333f0b1095020918b8616
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Thu Feb 28 09:08:52 2008 +0100

    Avoid large kmallocs.

diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 7d247f9..f6df74a 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -1181,7 +1181,6 @@ static int i915_handle_copyback(struct drm_device *dev,
 			buffers++;
 		}
 	}
-
 	return err;
 }
 
@@ -1272,7 +1271,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	struct drm_fence_arg *fence_arg = &exec_buf->fence_arg;
 	int num_buffers;
 	int ret;
-	struct drm_i915_validate_buffer *buffers;
 
 	if (!dev_priv->allow_batchbuffer) {
 		DRM_ERROR("Batchbuffer ioctl disabled\n");
@@ -1288,7 +1286,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	if (exec_buf->num_buffers > dev_priv->max_validate_buffers)
 		return -EINVAL;
 
-
 	ret = drm_bo_read_lock(&dev->bm.bm_lock);
 	if (ret)
 		return ret;
@@ -1306,8 +1303,12 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 
 	num_buffers = exec_buf->num_buffers;
 
-	buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), DRM_MEM_DRIVER);
-	if (!buffers) {
+	if (!dev_priv->val_bufs) {
+		dev_priv->val_bufs =
+			vmalloc(sizeof(struct drm_i915_validate_buffer)*
+				dev_priv->max_validate_buffers);
+	}
+	if (!dev_priv->val_bufs) {
 		drm_bo_read_unlock(&dev->bm.bm_lock);
 		mutex_unlock(&dev_priv->cmdbuf_mutex);
 		return -ENOMEM;
@@ -1315,7 +1316,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 
 	/* validate buffer list + fixup relocations */
 	ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list,
-					buffers, &num_buffers);
+					dev_priv->val_bufs, &num_buffers);
 	if (ret)
 		goto out_err0;
 
@@ -1324,7 +1325,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 	drm_agp_chipset_flush(dev);
 
 	/* submit buffer */
-	batch->start = buffers[num_buffers-1].buffer->offset;
+	batch->start = dev_priv->val_bufs[num_buffers-1].buffer->offset;
 
 	DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n",
 		  batch->start, batch->used, batch->num_cliprects);
@@ -1341,13 +1342,11 @@ static int i915_execbuffer(struct drm_device *dev, void *data,
 out_err0:
 
 	/* handle errors */
-	ret = i915_handle_copyback(dev, buffers, num_buffers, ret);
+	ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret);
 	mutex_lock(&dev->struct_mutex);
-	i915_dereference_buffers_locked(buffers, num_buffers);
+	i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers);
 	mutex_unlock(&dev->struct_mutex);
 
-	drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER);
-
 	mutex_unlock(&dev_priv->cmdbuf_mutex);
 	drm_bo_read_unlock(&dev->bm.bm_lock);
 	return ret;
@@ -1618,6 +1617,13 @@ void i915_driver_lastclose(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
+#ifdef I915_HAVE_BUFFER
+	if (dev_priv->val_bufs) {
+		vfree(dev_priv->val_bufs);
+		dev_priv->val_bufs = NULL;
+	}
+#endif
+
 	if (drm_getsarea(dev) && dev_priv->sarea_priv)
 		i915_do_cleanup_pageflip(dev);
 	if (dev_priv->agp_heap)
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 570fc4d..3bc39e2 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -69,6 +69,7 @@
 
 #ifdef I915_HAVE_BUFFER
 #define I915_MAX_VALIDATE_BUFFERS 4096
+struct drm_i915_validate_buffer;
 #endif
 
 typedef struct _drm_i915_ring_buffer {
@@ -141,6 +142,7 @@ typedef struct drm_i915_private {
 	void *agp_iomap;
 	unsigned int max_validate_buffers;
 	struct mutex cmdbuf_mutex;
+	struct drm_i915_validate_buffer *val_bufs;
 #endif
 
 	DRM_SPINTYPE swaps_lock;

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
--
_______________________________________________
Dri-patches mailing list
Dri-patches@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-patches
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic