diff options
| -rw-r--r-- | shared-core/nouveau_drm.h | 4 | ||||
| -rw-r--r-- | shared-core/nouveau_drv.h | 2 | ||||
| -rw-r--r-- | shared-core/nouveau_mem.c | 58 | ||||
| -rw-r--r-- | shared-core/nouveau_notifier.c | 2 | ||||
| -rw-r--r-- | shared-core/nouveau_object.c | 2 | 
5 files changed, 42 insertions, 26 deletions
diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index cf762052..bbb51bc4 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -88,9 +88,11 @@ struct drm_nouveau_gpuobj_free {  #define NOUVEAU_MEM_INSTANCE		0x00000200 /* internal */  #define NOUVEAU_MEM_NOTIFIER            0x00000400 /* internal */  #define NOUVEAU_MEM_NOVM		0x00000800 /* internal */ +#define NOUVEAU_MEM_USER		0x00001000 /* internal */  #define NOUVEAU_MEM_INTERNAL (NOUVEAU_MEM_INSTANCE | \  			      NOUVEAU_MEM_NOTIFIER | \ -			      NOUVEAU_MEM_NOVM) +			      NOUVEAU_MEM_NOVM | \ +			      NOUVEAU_MEM_USER)  struct drm_nouveau_mem_alloc {  	int flags; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 20aa6b86..33e2a5b6 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -375,7 +375,7 @@ extern int  nouveau_mem_init_heap(struct mem_block **, uint64_t start,  				 uint64_t size);  extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,  						 uint64_t size, int align2, -						 struct drm_file *); +						 struct drm_file *, int tail);  extern void nouveau_mem_takedown(struct mem_block **heap);  extern void nouveau_mem_free_block(struct mem_block *);  extern struct mem_block* find_block_by_handle(struct mem_block *heap, drm_handle_t handle); diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 810eaf9e..51ac48dd 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -35,8 +35,9 @@  #include "drm_sarea.h"  #include "nouveau_drv.h" -static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64_t size, -		struct drm_file *file_priv) +static struct mem_block * +split_block(struct mem_block *p, uint64_t start, uint64_t size, +	    struct drm_file *file_priv)  {  	/* Maybe cut off the start of an existing block */  	if (start > p->start) { @@ -77,10 +78,9 @@ out:  	return p;  } -struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap, -					  uint64_t size, -					  int align2, -					  struct drm_file *file_priv) +struct mem_block * +nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size, +			int align2, struct drm_file *file_priv, int tail)  {  	struct mem_block *p;  	uint64_t mask = (1 << align2) - 1; @@ -88,10 +88,22 @@ struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap,  	if (!heap)  		return NULL; -	list_for_each(p, heap) { -		uint64_t start = (p->start + mask) & ~mask; -		if (p->file_priv == 0 && start + size <= p->start + p->size) -			return split_block(p, start, size, file_priv); +	if (tail) { +		list_for_each_prev(p, heap) { +			uint64_t start = ((p->start + p->size) - size) & ~mask; + +			if (p->file_priv == 0 && start >= p->start && +			    start + size <= p->start + p->size) +				return split_block(p, start, size, file_priv); +		} +	} else { +		list_for_each(p, heap) { +			uint64_t start = (p->start + mask) & ~mask; + +			if (p->file_priv == 0 && +			    start + size <= p->start + p->size) +				return split_block(p, start, size, file_priv); +		}  	}  	return NULL; @@ -574,13 +586,13 @@ int nouveau_mem_init(struct drm_device *dev)  	return 0;  } -struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, -				    uint64_t size, int flags, -				    struct drm_file *file_priv) +struct mem_block * +nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, +		  int flags, struct drm_file *file_priv)  { -	struct mem_block *block; -	int type;  	struct drm_nouveau_private *dev_priv = dev->dev_private; +	struct mem_block *block; +	int type, tail = !(flags & NOUVEAU_MEM_USER);  	/*  	 * Make things easier on ourselves: all allocations are page-aligned. @@ -611,14 +623,14 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment,  #define NOUVEAU_MEM_ALLOC_AGP {\  		type=NOUVEAU_MEM_AGP;\                  block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,\ -                                                alignment, file_priv); \ +                                                alignment, file_priv, tail); \                  if (block) goto alloc_ok;\  	        }  #define NOUVEAU_MEM_ALLOC_PCI {\                  type = NOUVEAU_MEM_PCI;\                  block = nouveau_mem_alloc_block(dev_priv->pci_heap, size, \ -						alignment, file_priv); \ +						alignment, file_priv, tail); \                  if ( block ) goto alloc_ok;\  	        } @@ -627,11 +639,11 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment,                  if (!(flags&NOUVEAU_MEM_MAPPED)) {\                          block = nouveau_mem_alloc_block(dev_priv->fb_nomap_heap,\                                                          size, alignment, \ -							file_priv); \ +							file_priv, tail); \                          if (block) goto alloc_ok;\                  }\                  block = nouveau_mem_alloc_block(dev_priv->fb_heap, size,\ -                                                alignment, file_priv);\ +                                                alignment, file_priv, tail);\                  if (block) goto alloc_ok;\  	        } @@ -749,7 +761,9 @@ out_free:   * Ioctls   */ -int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +int +nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, +			struct drm_file *file_priv)  {  	struct drm_nouveau_mem_alloc *alloc = data;  	struct mem_block *block; @@ -759,8 +773,8 @@ int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file  	if (alloc->flags & NOUVEAU_MEM_INTERNAL)  		return -EINVAL; -	block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size, -				alloc->flags, file_priv); +	block = nouveau_mem_alloc(dev, alloc->alignment, alloc->size, +				  alloc->flags | NOUVEAU_MEM_USER, file_priv);  	if (!block)  		return -ENOMEM;  	alloc->map_handle=block->map_handle; diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 82c8ab7d..edece4da 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -94,7 +94,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,  	}  	mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0, -				      (struct drm_file *)-2); +				      (struct drm_file *)-2, 0);  	if (!mem) {  		DRM_ERROR("Channel %d notifier block full\n", chan->id);  		return -ENOMEM; diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 09f9027a..5664bfc8 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -248,7 +248,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,  	/* Allocate a chunk of the PRAMIN aperture */  	gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,  						    drm_order(align), -						    (struct drm_file *)-2); +						    (struct drm_file *)-2, 0);  	if (!gpuobj->im_pramin) {  		nouveau_gpuobj_del(dev, &gpuobj);  		return -ENOMEM;  | 
