drm/nouveau/core/mm: allow allocation to be confined to a specific slice of heap
authorBen Skeggs <bskeggs@redhat.com>
Tue, 12 Aug 2014 04:30:52 +0000 (14:30 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 15 Sep 2014 12:22:13 +0000 (22:22 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
16 files changed:
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/include/core/mm.h
drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv36.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
drivers/gpu/drm/nouveau/core/subdev/vm/base.c
drivers/gpu/drm/nouveau/nouveau_abi16.c

index 560b2214cf1cc6fefed5d21dd5e0ded550df7666..daee877025029d62b2023a5fe018d72cf6491d9a 100644 (file)
@@ -115,7 +115,7 @@ nouveau_gpuobj_create_(struct nouveau_object *parent,
        gpuobj->size = size;
 
        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);
                if (ret)
                        return ret;
index 02ce615687acd0d9b51282b6210b4aab0d224fa6..b4f5db66d5b545b58b351a5681f8509a5e7e71c1 100644 (file)
@@ -98,6 +98,7 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
 
        b->offset = a->offset;
        b->length = size;
+       b->heap   = a->heap;
        b->type   = a->type;
        a->offset += size;
        a->length -= size;
@@ -108,8 +109,8 @@ region_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
 }
 
 int
-nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
-               u32 align, struct nouveau_mm_node **pnode)
+nouveau_mm_head(struct nouveau_mm *mm, u8 heap, u8 type, u32 size_max,
+               u32 size_min, u32 align, struct nouveau_mm_node **pnode)
 {
        struct nouveau_mm_node *prev, *this, *next;
        u32 mask = align - 1;
@@ -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);
 
        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;
                s = this->offset;
 
@@ -167,6 +172,7 @@ region_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size)
        a->length -= size;
        b->offset  = a->offset + a->length;
        b->length  = size;
+       b->heap    = a->heap;
        b->type    = a->type;
 
        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)
 }
 
 int
-nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
-               u32 align, struct nouveau_mm_node **pnode)
+nouveau_mm_tail(struct nouveau_mm *mm, u8 heap, u8 type, u32 size_max,
+               u32 size_min, u32 align, struct nouveau_mm_node **pnode)
 {
        struct nouveau_mm_node *prev, *this, *next;
        u32 mask = align - 1;
@@ -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 s = this->offset;
                u32 c = 0, a;
+               if (unlikely(heap != NVKM_MM_HEAP_ANY)) {
+                       if (this->heap != heap)
+                               continue;
+               }
 
                prev = node(this, prev);
                if (prev && prev->type != type)
@@ -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->fl_entry, &mm->free);
-       mm->heap_nodes++;
+       node->heap = ++mm->heap_nodes;
        return 0;
 }
 
index d4ef40460e42bf587398c81919326b5dcd076b6b..bfe6931544fe646ab4bb205bf661c9bd6adaf205 100644 (file)
@@ -6,6 +6,8 @@ struct nouveau_mm_node {
        struct list_head fl_entry;
        struct list_head rl_entry;
 
+#define NVKM_MM_HEAP_ANY 0x00
+       u8  heap;
 #define NVKM_MM_TYPE_NONE 0x00
 #define NVKM_MM_TYPE_HOLE 0xff
        u8  type;
@@ -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_fini(struct nouveau_mm *);
-int  nouveau_mm_head(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min,
-                    u32 align, struct nouveau_mm_node **);
-int  nouveau_mm_tail(struct nouveau_mm *, u8 type, u32 size_max, u32 size_min,
-                    u32 align, struct nouveau_mm_node **);
+int  nouveau_mm_head(struct nouveau_mm *, u8 heap, u8 type, u32 size_max,
+                    u32 size_min, u32 align, struct nouveau_mm_node **);
+int  nouveau_mm_tail(struct nouveau_mm *, u8 heap, u8 type, u32 size_max,
+                    u32 size_min, u32 align, struct nouveau_mm_node **);
 void nouveau_mm_free(struct nouveau_mm *, struct nouveau_mm_node **);
 
 #endif
index f003c1b1893f48c1a115e55e835a749d98b41207..2209ade63339ed93645f600bc5d0eb3e7626e2ba 100644 (file)
@@ -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 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 */
                else              tile->zcomp = 0x04000000; /* Z24S8 */
                tile->zcomp |= tile->tag->offset;
index f34f4223210b8552bc143f096bd8117ca216e158..e2a66c355c50dff411098012dc808a085905dd1e 100644 (file)
@@ -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 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 */
                else              tile->zcomp = 0x00200000; /* Z24S8 */
                tile->zcomp |= tile->tag->offset;
index 69093f7151f01d168117098983a6812e9b3ff965..cbec402ba5b92861f0f75dc48e781aaacd2212ec 100644 (file)
@@ -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 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 */
                else           tile->zcomp |= 0x02000000; /* Z24S8 */
                tile->zcomp |= ((tile->tag->offset           ) >> 6);
index 161b06e8fc3f75f31567054c3f68117e0691e93e..b2cf8c69fb2ee67e9d50c973adf159fd6a16d431 100644 (file)
@@ -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 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 */
                else           tile->zcomp |= 0x08000000; /* Z24S8 */
                tile->zcomp |= ((tile->tag->offset           ) >> 6);
index 2dd3d0aab6bb6434fdb780c1152f71453aa22324..b4cdae2a3b2f192bcbd4ee13fa45bef459435311 100644 (file)
@@ -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 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 */
                else           tile->zcomp |= 0x20000000; /* Z24S8 */
                tile->zcomp |= ((tile->tag->offset           ) >> 6);
index 95a115ab0c860bc591f63033f6305c7f15fb0b59..52814258c21279f8fe88bd3b316dfac0fa4a95e3 100644 (file)
@@ -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 tags  = round_up(tiles / pfb->ram->parts, 0x100);
        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 |= ((tile->tag->offset           ) >> 8);
                tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13;
index e5d12c24cc43e132df49142ba23256c7e99599f5..514b0785a01982c2f78bd7c6b313fc012afe632f 100644 (file)
@@ -280,7 +280,7 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
                if (align == 16) {
                        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)
                                mem->tag = NULL;
                }
@@ -296,9 +296,9 @@ nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
        type = nv50_fb_memtype[type];
        do {
                if (back)
-                       ret = nouveau_mm_tail(heap, type, max, min, align, &r);
+                       ret = nouveau_mm_tail(heap, 0, type, max, min, align, &r);
                else
-                       ret = nouveau_mm_head(heap, type, max, min, align, &r);
+                       ret = nouveau_mm_head(heap, 0, type, max, min, align, &r);
                if (ret) {
                        mutex_unlock(&pfb->base.mutex);
                        pfb->ram->put(pfb, &mem);
index 8007f610df3943f3b9dbe8380348e142d6ef285a..fc9de888fa8193416e7cf6bbaaca4ecf16f084ef 100644 (file)
@@ -483,9 +483,9 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
 
        do {
                if (back)
-                       ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r);
+                       ret = nouveau_mm_tail(mm, 0, 1, size, ncmin, align, &r);
                else
-                       ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r);
+                       ret = nouveau_mm_head(mm, 0, 1, size, ncmin, align, &r);
                if (ret) {
                        mutex_unlock(&pfb->base.mutex);
                        pfb->ram->put(pfb, &mem);
index 7b64befee48fbb5b30b306c980ae53bd077c3368..e8b1401c59c0ef4c76fa9407eab862a8b8360dc3 100644 (file)
@@ -69,7 +69,7 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        if (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);
        if (ret)
                return ret;
index 32ed442c59130548f0deeb88fb735048a7e45a9a..7fa331516f84f22bf27b9795e8e181b1b899335a 100644 (file)
@@ -31,7 +31,7 @@ nvkm_ltc_tags_alloc(struct nouveau_ltc *ltc, u32 n,
        struct nvkm_ltc_priv *priv = (void *)ltc;
        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)
                *pnode = NULL;
 
index 7f9dd2b6fa90f1a9f5fcdb0b856326c25b41aa08..8857d41a131275b0433e9efaf4ac0252127f3fdb 100644 (file)
@@ -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_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);
        if (ret) {
                priv->num_tags = 0;
index 7dd680ff2f6f63683f34e39a1d7821f3c73c140c..f75a683bd47a6ddf38e3ec13260f657a8c525c65 100644 (file)
@@ -296,7 +296,7 @@ nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift,
        int ret;
 
        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);
        if (unlikely(ret != 0)) {
                mutex_unlock(&nv_subdev(vmm)->mutex);
index 615714c1727d6b6870b3ec2698bc204c74ab196a..a24faa5e2a2ae67a5075cb2f9506b9f93fa66083 100644 (file)
@@ -448,7 +448,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        list_add(&ntfy->head, &chan->notifiers);
        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);
        if (ret)
                goto done;