mm.c revision 13dfe1286d1ea1af4c9330b039c2316d0d92c484
1573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs/* 2496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs * Copyright 2012 Red Hat Inc. 3573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * 4573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * copy of this software and associated documentation files (the "Software"), 6573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * to deal in the Software without restriction, including without limitation 7573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * Software is furnished to do so, subject to the following conditions: 10573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * 11573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * The above copyright notice and this permission notice shall be included in 12573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * all copies or substantial portions of the Software. 13573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * 14573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * 22573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs * Authors: Ben Skeggs 23573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs */ 24573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 25496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs#include "core/os.h" 26496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs#include "core/mm.h" 27573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 28496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ 29496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) 30496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 31d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggsstatic void 32d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggsnouveau_mm_dump(struct nouveau_mm *mm, const char *header) 33d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs{ 34d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs struct nouveau_mm_node *node; 35d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs 36d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs printk(KERN_ERR "nouveau: %s\n", header); 37d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs printk(KERN_ERR "nouveau: node list:\n"); 38d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs list_for_each_entry(node, &mm->nodes, nl_entry) { 39d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs printk(KERN_ERR "nouveau: \t%08x %08x %d\n", 40d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs node->offset, node->length, node->type); 41d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs } 42d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs printk(KERN_ERR "nouveau: free list:\n"); 43d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs list_for_each_entry(node, &mm->free, fl_entry) { 44d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs printk(KERN_ERR "nouveau: \t%08x %08x %d\n", 45d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs node->offset, node->length, node->type); 46d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs } 47d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs} 48d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs 49496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsvoid 50496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_free(struct nouveau_mm *mm, struct nouveau_mm_node **pthis) 51573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 52496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *this = *pthis; 53496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 54496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this) { 55496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *prev = node(this, prev); 56496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *next = node(this, next); 57496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 5879456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (prev && prev->type == NVKM_MM_TYPE_NONE) { 59496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev->length += this->length; 60496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 61496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = prev; 62496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 63496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 6479456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (next && next->type == NVKM_MM_TYPE_NONE) { 65496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->offset = this->offset; 66496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->length += this->length; 6779456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (this->type == NVKM_MM_TYPE_NONE) 68496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 69496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 70496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = NULL; 71496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 72496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 7379456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (this && this->type != NVKM_MM_TYPE_NONE) { 74496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_for_each_entry(prev, &mm->free, fl_entry) { 75496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this->offset < prev->offset) 76496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs break; 77496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 78496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 79496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add_tail(&this->fl_entry, &prev->fl_entry); 8079456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs this->type = NVKM_MM_TYPE_NONE; 81496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 82496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 83496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 84496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs *pthis = NULL; 85573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 86573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 87573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsstatic struct nouveau_mm_node * 88496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsregion_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) 89573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 90573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs struct nouveau_mm_node *b; 91573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 92573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs if (a->length == size) 93573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return a; 94573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 95573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b = kmalloc(sizeof(*b), GFP_KERNEL); 96573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs if (unlikely(b == NULL)) 97573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return NULL; 98573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 99573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->offset = a->offset; 100573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->length = size; 101573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->type = a->type; 102573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs a->offset += size; 103573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs a->length -= size; 104573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_add_tail(&b->nl_entry, &a->nl_entry); 10579456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (b->type == NVKM_MM_TYPE_NONE) 106573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_add_tail(&b->fl_entry, &a->fl_entry); 107573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return b; 108573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 109573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 110573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 111496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, 112496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 align, struct nouveau_mm_node **pnode) 113573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 1148b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs struct nouveau_mm_node *prev, *this, *next; 115496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 mask = align - 1; 1168b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs u32 splitoff; 1178b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs u32 s, e; 1188b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 11913dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs BUG_ON(type == NVKM_MM_TYPE_NONE || type == NVKM_MM_TYPE_HOLE); 12018902bbf06a93ea497be2f177a6323ed9e5f30beMaarten Lankhorst 121987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs list_for_each_entry(this, &mm->free, fl_entry) { 1228b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs e = this->offset + this->length; 1238b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs s = this->offset; 1248b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1258b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs prev = node(this, prev); 1268b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (prev && prev->type != type) 127987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs s = roundup(s, mm->block_size); 1288b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1298b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs next = node(this, next); 1308b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (next && next->type != type) 131987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs e = rounddown(e, mm->block_size); 1328b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 133496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 134496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e &= ~mask; 135496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || e - s < size_min) 136573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs continue; 137573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 1388b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs splitoff = s - this->offset; 139496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (splitoff && !region_head(mm, this, splitoff)) 140496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 141496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 142496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_head(mm, this, min(size_max, e - s)); 143496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (!this) 144496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 145496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 146496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this->type = type; 147496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 148496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs *pnode = this; 149496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return 0; 150496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 151496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 152496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOSPC; 153496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 154496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 155496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsstatic struct nouveau_mm_node * 156496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsregion_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) 157496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 158496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *b; 159496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 160496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (a->length == size) 161496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return a; 162496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 163496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b = kmalloc(sizeof(*b), GFP_KERNEL); 164496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (unlikely(b == NULL)) 165496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return NULL; 166496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 167496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a->length -= size; 168496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->offset = a->offset + a->length; 169496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->length = size; 170496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->type = a->type; 171496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 172496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->nl_entry, &a->nl_entry); 17379456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (b->type == NVKM_MM_TYPE_NONE) 174496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->fl_entry, &a->fl_entry); 175496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return b; 176496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 177496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 178496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsint 179496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, 180496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 align, struct nouveau_mm_node **pnode) 181496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 182496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *prev, *this, *next; 183496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 mask = align - 1; 184496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 18513dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs BUG_ON(type == NVKM_MM_TYPE_NONE || type == NVKM_MM_TYPE_HOLE); 18618902bbf06a93ea497be2f177a6323ed9e5f30beMaarten Lankhorst 187496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_for_each_entry_reverse(this, &mm->free, fl_entry) { 188496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 e = this->offset + this->length; 189496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 s = this->offset; 190496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 c = 0, a; 191496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 192496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev = node(this, prev); 193496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (prev && prev->type != type) 194496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = roundup(s, mm->block_size); 195496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 196496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next = node(this, next); 197496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (next && next->type != type) { 198496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e = rounddown(e, mm->block_size); 199496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c = next->offset - e; 200496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 201496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 202496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 203496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = e - s; 204496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || a < size_min) 205496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs continue; 206496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 207496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = min(a, size_max); 208496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (e - a) & ~mask; 209496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c += (e - s) - a; 210496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 211496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (c && !region_tail(mm, this, c)) 2128b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs return -ENOMEM; 213573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 214496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_tail(mm, this, a); 2158b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (!this) 216573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 217573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 2188b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs this->type = type; 219573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_del(&this->fl_entry); 220573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs *pnode = this; 221573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 222573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs } 223573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 224ef1b287169cd3d1e428c8ed8222e0bbf733d5dbbBen Skeggs return -ENOSPC; 225573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 226573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 227573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 228987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) 229573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 23013dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs struct nouveau_mm_node *node, *prev; 23113dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs u32 next; 232a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 233d979ab975ecdb336ed4da77a808be813a293b59eBen Skeggs if (nouveau_mm_initialised(mm)) { 23413dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs prev = list_last_entry(&mm->nodes, typeof(*node), nl_entry); 23513dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs next = prev->offset + prev->length; 23613dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs if (next != offset) { 23713dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs BUG_ON(next > offset); 23813dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs if (!(node = kzalloc(sizeof(*node), GFP_KERNEL))) 23913dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs return -ENOMEM; 24013dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs node->type = NVKM_MM_TYPE_HOLE; 24113dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs node->offset = next; 24213dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs node->length = offset - next; 24313dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs list_add_tail(&node->nl_entry, &mm->nodes); 24413dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs } 245d979ab975ecdb336ed4da77a808be813a293b59eBen Skeggs BUG_ON(block != mm->block_size); 246d979ab975ecdb336ed4da77a808be813a293b59eBen Skeggs } else { 247a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->nodes); 248a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->free); 249a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->block_size = block; 250a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes = 0; 251a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs } 252573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 253a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs node = kzalloc(sizeof(*node), GFP_KERNEL); 254a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs if (!node) 255573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 256a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs 257a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs if (length) { 258a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->offset = roundup(offset, mm->block_size); 259a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->length = rounddown(offset + length, mm->block_size); 260a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->length -= node->offset; 261a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs } 262987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs 263a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->nl_entry, &mm->nodes); 264a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->fl_entry, &mm->free); 265a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes++; 266573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 267573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 268573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 269573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 270987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_fini(struct nouveau_mm *mm) 271573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 272d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs struct nouveau_mm_node *node, *temp; 273d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs int nodes = 0; 2747e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs 275d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs if (!nouveau_mm_initialised(mm)) 276d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs return 0; 277a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 278d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs list_for_each_entry(node, &mm->nodes, nl_entry) { 27913dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs if (node->type != NVKM_MM_TYPE_HOLE) { 28013dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs if (++nodes > mm->heap_nodes) { 28113dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs nouveau_mm_dump(mm, "mm not clean!"); 28213dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs return -EBUSY; 28313dfe1286d1ea1af4c9330b039c2316d0d92c484Ben Skeggs } 284d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs } 285ad9ac437a500f8c0822bd5fe139af8ee2c132e15Ben Skeggs } 286573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 287d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs list_for_each_entry_safe(node, temp, &mm->nodes, nl_entry) { 288d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs list_del(&node->nl_entry); 289d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs kfree(node); 290d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs } 291d7bda18c9102b65078c132fd7d7ffd835058f021Ben Skeggs mm->heap_nodes = 0; 292573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 293573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 294