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
parent
11f2a2ed6f
commit
b9ed0f9950
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue