Commit 65270a65 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/core/mm: allow allocation to be confined to a specific slice of heap

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 13dfe128
...@@ -115,7 +115,7 @@ nouveau_gpuobj_create_(struct nouveau_object *parent, ...@@ -115,7 +115,7 @@ nouveau_gpuobj_create_(struct nouveau_object *parent,
gpuobj->size = size; gpuobj->size = size;
if (heap) { if (heap) {
ret = nouveau_mm_head(heap, 1, size, size, ret = nouveau_mm_head(heap, 0, 1, size, size,
max(align, (u32)1), &gpuobj->node); max(align, (u32)1), &gpuobj->node);
if (ret) if (ret)
return ret; return ret;
......
...@@ -98,6 +98,7 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) ...@@ -98,6 +98,7 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
b->offset = a->offset; b->offset = a->offset;
b->length = size; b->length = size;
b->heap = a->heap;
b->type = a->type; b->type = a->type;
a->offset += size; a->offset += size;
a->length -= size; a->length -= size;
...@@ -108,8 +109,8 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) ...@@ -108,8 +109,8 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
} }
int int
nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, nouveau_mm_head(struct nouveau_mm *mm, u8 heap, u8 type, u32 size_max,
u32 align, struct nouveau_mm_node **pnode) u32 size_min, u32 align, struct nouveau_mm_node **pnode)
{ {
struct nouveau_mm_node *prev, *this, *next; struct nouveau_mm_node *prev, *this, *next;
u32 mask = align - 1; u32 mask = align - 1;
...@@ -119,6 +120,10 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, ...@@ -119,6 +120,10 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
BUG_ON(type == NVKM_MM_TYPE_NONE || type == NVKM_MM_TYPE_HOLE); BUG_ON(type == NVKM_MM_TYPE_NONE || type == NVKM_MM_TYPE_HOLE);
list_for_each_entry(this, &mm->free, fl_entry) { list_for_each_entry(this, &mm->free, fl_entry) {
if (unlikely(heap != NVKM_MM_HEAP_ANY)) {
if (this->heap != heap)
continue;
}
e = this->offset + this->length; e = this->offset + this->length;
s = this->offset; s = this->offset;
...@@ -167,6 +172,7 @@ region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) ...@@ -167,6 +172,7 @@ region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
a->length -= size; a->length -= size;
b->offset = a->offset + a->length; b->offset = a->offset + a->length;
b->length = size; b->length = size;
b->heap = a->heap;
b->type = a->type; b->type = a->type;
list_add(&b->nl_entry, &a->nl_entry); list_add(&b->nl_entry, &a->nl_entry);
...@@ -176,8 +182,8 @@ region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) ...@@ -176,8 +182,8 @@ region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
} }
int int
nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, nouveau_mm_tail(struct nouveau_mm *mm, u8 heap, u8 type, u32 size_max,
u32 align, struct nouveau_mm_node **pnode) u32 size_min, u32 align, struct nouveau_mm_node **pnode)
{ {
struct nouveau_mm_node *prev, *this, *next; struct nouveau_mm_node *prev, *this, *next;
u32 mask = align - 1; u32 mask = align - 1;
...@@ -188,6 +194,10 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, ...@@ -188,6 +194,10 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
u32 e = this->offset + this->length; u32 e = this->offset + this->length;
u32 s = this->offset; u32 s = this->offset;
u32 c = 0, a; u32 c = 0, a;
if (unlikely(heap != NVKM_MM_HEAP_ANY)) {
if (this->heap != heap)
continue;
}
prev = node(this, prev); prev = node(this, prev);
if (prev && prev->type != type) if (prev && prev->type != type)
...@@ -262,7 +272,7 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) ...@@ -262,7 +272,7 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->nl_entry, &mm->nodes);
list_add_tail(&node->fl_entry, &mm->free); list_add_tail(&node->fl_entry, &mm->free);
mm->heap_nodes++; node->heap = ++mm->heap_nodes;
return 0; return 0;
} }
......
...@@ -6,6 +6,8 @@ struct nouveau_mm_node { ...@@ -6,6 +6,8 @@ struct nouveau_mm_node {
struct list_head fl_entry; struct list_head fl_entry;
struct list_head rl_entry; struct list_head rl_entry;
#define NVKM_MM_HEAP_ANY 0x00
u8 heap;
#define NVKM_MM_TYPE_NONE 0x00 #define NVKM_MM_TYPE_NONE 0x00
#define NVKM_MM_TYPE_HOLE 0xff #define NVKM_MM_TYPE_HOLE 0xff
u8 type; u8 type;
...@@ -29,10 +31,10 @@ nouveau_mm_initialised(struct nouveau_mm *mm) ...@@ -29,10 +31,10 @@ nouveau_mm_initialised(struct nouveau_mm *mm)
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
int nouveau_mm_fini(struct nouveau_mm *); int nouveau_mm_fini(struct nouveau_mm *);
int nouveau_mm_head(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min, int nouveau_mm_head(struct nouveau_mm *, u8 heap, u8 type, u32 size_max,
u32 align, struct nouveau_mm_node **); u32 size_min, u32 align, struct nouveau_mm_node **);
int nouveau_mm_tail(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min, int nouveau_mm_tail(struct nouveau_mm *, u8 heap, u8 type, u32 size_max,
u32 align, struct nouveau_mm_node **); u32 size_min, u32 align, struct nouveau_mm_node **);
void nouveau_mm_free(struct nouveau_mm *, struct nouveau_mm_node **); void nouveau_mm_free(struct nouveau_mm *, struct nouveau_mm_node **);
#endif #endif
...@@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / pfb->ram->parts, 0x40); u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { if (!nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */ if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */
else tile->zcomp = 0x04000000; /* Z24S8 */ else tile->zcomp = 0x04000000; /* Z24S8 */
tile->zcomp |= tile->tag->offset; tile->zcomp |= tile->tag->offset;
......
...@@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / pfb->ram->parts, 0x40); u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { if (!nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */ if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */
else tile->zcomp = 0x00200000; /* Z24S8 */ else tile->zcomp = 0x00200000; /* Z24S8 */
tile->zcomp |= tile->tag->offset; tile->zcomp |= tile->tag->offset;
......
...@@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / pfb->ram->parts, 0x40); u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { if (!nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */
else tile->zcomp |= 0x02000000; /* Z24S8 */ else tile->zcomp |= 0x02000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / pfb->ram->parts, 0x40); u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { if (!nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */
else tile->zcomp |= 0x08000000; /* Z24S8 */ else tile->zcomp |= 0x08000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
{ {
u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tiles = DIV_ROUND_UP(size, 0x40);
u32 tags = round_up(tiles / pfb->ram->parts, 0x40); u32 tags = round_up(tiles / pfb->ram->parts, 0x40);
if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { if (!nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */ if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */
else tile->zcomp |= 0x20000000; /* Z24S8 */ else tile->zcomp |= 0x20000000; /* Z24S8 */
tile->zcomp |= ((tile->tag->offset ) >> 6); tile->zcomp |= ((tile->tag->offset ) >> 6);
......
...@@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, ...@@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
u32 tiles = DIV_ROUND_UP(size, 0x80); u32 tiles = DIV_ROUND_UP(size, 0x80);
u32 tags = round_up(tiles / pfb->ram->parts, 0x100); u32 tags = round_up(tiles / pfb->ram->parts, 0x100);
if ( (flags & 2) && if ( (flags & 2) &&
!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) { !nouveau_mm_head(&pfb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */ tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */
tile->zcomp |= ((tile->tag->offset ) >> 8); tile->zcomp |= ((tile->tag->offset ) >> 8);
tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13; tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13;
......
...@@ -280,7 +280,7 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, ...@@ -280,7 +280,7 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
if (align == 16) { if (align == 16) {
int n = (max >> 4) * comp; int n = (max >> 4) * comp;
ret = nouveau_mm_head(tags, 1, n, n, 1, &mem->tag); ret = nouveau_mm_head(tags, 0, 1, n, n, 1, &mem->tag);
if (ret) if (ret)
mem->tag = NULL; mem->tag = NULL;
} }
...@@ -296,9 +296,9 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, ...@@ -296,9 +296,9 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
type = nv50_fb_memtype[type]; type = nv50_fb_memtype[type];
do { do {
if (back) if (back)
ret = nouveau_mm_tail(heap, type, max, min, align, &r); ret = nouveau_mm_tail(heap, 0, type, max, min, align, &r);
else else
ret = nouveau_mm_head(heap, type, max, min, align, &r); ret = nouveau_mm_head(heap, 0, type, max, min, align, &r);
if (ret) { if (ret) {
mutex_unlock(&pfb->base.mutex); mutex_unlock(&pfb->base.mutex);
pfb->ram->put(pfb, &mem); pfb->ram->put(pfb, &mem);
......
...@@ -483,9 +483,9 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, ...@@ -483,9 +483,9 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
do { do {
if (back) if (back)
ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); ret = nouveau_mm_tail(mm, 0, 1, size, ncmin, align, &r);
else else
ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); ret = nouveau_mm_head(mm, 0, 1, size, ncmin, align, &r);
if (ret) { if (ret) {
mutex_unlock(&pfb->base.mutex); mutex_unlock(&pfb->base.mutex);
pfb->ram->put(pfb, &mem); pfb->ram->put(pfb, &mem);
......
...@@ -69,7 +69,7 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ...@@ -69,7 +69,7 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret) if (ret)
return ret; return ret;
ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size, ret = nouveau_mm_head(&priv->heap, 0, 1, args->size, args->size,
args->align, &node->mem); args->align, &node->mem);
if (ret) if (ret)
return ret; return ret;
......
...@@ -31,7 +31,7 @@ nvkm_ltc_tags_alloc(struct nouveau_ltc *ltc, u32 n, ...@@ -31,7 +31,7 @@ nvkm_ltc_tags_alloc(struct nouveau_ltc *ltc, u32 n,
struct nvkm_ltc_priv *priv = (void *)ltc; struct nvkm_ltc_priv *priv = (void *)ltc;
int ret; int ret;
ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode); ret = nouveau_mm_head(&priv->tags, 0, 1, n, n, 1, pnode);
if (ret) if (ret)
*pnode = NULL; *pnode = NULL;
......
...@@ -168,7 +168,7 @@ gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv) ...@@ -168,7 +168,7 @@ gf100_ltc_init_tag_ram(struct nouveau_fb *pfb, struct nvkm_ltc_priv *priv)
tag_size += tag_align; tag_size += tag_align;
tag_size = (tag_size + 0xfff) >> 12; /* round up */ tag_size = (tag_size + 0xfff) >> 12; /* round up */
ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1, ret = nouveau_mm_tail(&pfb->vram, 0, 1, tag_size, tag_size, 1,
&priv->tag_ram); &priv->tag_ram);
if (ret) { if (ret) {
priv->num_tags = 0; priv->num_tags = 0;
......
...@@ -296,7 +296,7 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, ...@@ -296,7 +296,7 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
int ret; int ret;
mutex_lock(&nv_subdev(vmm)->mutex); mutex_lock(&nv_subdev(vmm)->mutex);
ret = nouveau_mm_head(&vm->mm, page_shift, msize, msize, align, ret = nouveau_mm_head(&vm->mm, 0, page_shift, msize, msize, align,
&vma->node); &vma->node);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
mutex_unlock(&nv_subdev(vmm)->mutex); mutex_unlock(&nv_subdev(vmm)->mutex);
......
...@@ -448,7 +448,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) ...@@ -448,7 +448,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
list_add(&ntfy->head, &chan->notifiers); list_add(&ntfy->head, &chan->notifiers);
ntfy->handle = info->handle; ntfy->handle = info->handle;
ret = nouveau_mm_head(&chan->heap, 1, info->size, info->size, 1, ret = nouveau_mm_head(&chan->heap, 0, 1, info->size, info->size, 1,
&ntfy->node); &ntfy->node);
if (ret) if (ret)
goto done; goto done;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment