nouveau: allocate drm-use vram buffers from end of vram.

This avoids seeing garbage from engine setup etc before X gets around
to pointing the CRTCs at a new scanout buffer.  Not actually a noticable
problem before G80 as PRAMIN is forced to the end of VRAM by the hardware
already.
main
Ben Skeggs 2008-06-23 01:00:42 +10:00
parent 11f2a2ed6f
commit b9ed0f9950
5 changed files with 42 additions and 26 deletions

View File

@ -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;

View File

@ -350,7 +350,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 uint64_t nouveau_mem_fb_amount(struct drm_device *);

View File

@ -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;
@ -563,13 +575,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.
@ -600,14 +612,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;\
}
@ -616,11 +628,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;\
}
@ -738,7 +750,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;
@ -748,8 +762,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;

View File

@ -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;

View File

@ -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;