mm.c revision 496734bf0391f38c196e16dbbfaaeda8e6ec5845
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 31496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsvoid 32496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_free(struct nouveau_mm *mm, struct nouveau_mm_node **pthis) 33573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 34496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *this = *pthis; 35496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 36496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this) { 37496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *prev = node(this, prev); 38496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *next = node(this, next); 39496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 40496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (prev && prev->type == 0) { 41496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev->length += this->length; 42496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 43496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = prev; 44496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 45496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 46496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (next && next->type == 0) { 47496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->offset = this->offset; 48496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->length += this->length; 49496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this->type == 0) 50496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 51496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 52496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = NULL; 53496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 54496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 55496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this && this->type != 0) { 56496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_for_each_entry(prev, &mm->free, fl_entry) { 57496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (this->offset < prev->offset) 58496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs break; 59496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 60496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 61496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add_tail(&this->fl_entry, &prev->fl_entry); 62496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this->type = 0; 63496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 64496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 65496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 66496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs *pthis = NULL; 67573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 68573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 69573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsstatic struct nouveau_mm_node * 70496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsregion_head(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) 71573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 72573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs struct nouveau_mm_node *b; 73573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 74573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs if (a->length == size) 75573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return a; 76573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 77573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b = kmalloc(sizeof(*b), GFP_KERNEL); 78573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs if (unlikely(b == NULL)) 79573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return NULL; 80573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 81573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->offset = a->offset; 82573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->length = size; 83573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs b->type = a->type; 84573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs a->offset += size; 85573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs a->length -= size; 86573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_add_tail(&b->nl_entry, &a->nl_entry); 878b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (b->type == 0) 88573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_add_tail(&b->fl_entry, &a->fl_entry); 89573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return b; 90573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 91573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 92573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 93496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, 94496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 align, struct nouveau_mm_node **pnode) 95573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 968b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs struct nouveau_mm_node *prev, *this, *next; 97496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 mask = align - 1; 988b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs u32 splitoff; 998b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs u32 s, e; 1008b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 101987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs list_for_each_entry(this, &mm->free, fl_entry) { 1028b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs e = this->offset + this->length; 1038b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs s = this->offset; 1048b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1058b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs prev = node(this, prev); 1068b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (prev && prev->type != type) 107987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs s = roundup(s, mm->block_size); 1088b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1098b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs next = node(this, next); 1108b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (next && next->type != type) 111987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs e = rounddown(e, mm->block_size); 1128b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 113496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 114496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e &= ~mask; 115496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || e - s < size_min) 116573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs continue; 117573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 1188b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs splitoff = s - this->offset; 119496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (splitoff && !region_head(mm, this, splitoff)) 120496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 121496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 122496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_head(mm, this, min(size_max, e - s)); 123496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (!this) 124496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 125496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 126496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this->type = type; 127496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 128496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs *pnode = this; 129496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return 0; 130496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 131496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 132496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOSPC; 133496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 134496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 135496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsstatic struct nouveau_mm_node * 136496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsregion_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) 137496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 138496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *b; 139496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 140496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (a->length == size) 141496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return a; 142496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 143496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b = kmalloc(sizeof(*b), GFP_KERNEL); 144496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (unlikely(b == NULL)) 145496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return NULL; 146496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 147496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a->length -= size; 148496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->offset = a->offset + a->length; 149496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->length = size; 150496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->type = a->type; 151496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 152496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->nl_entry, &a->nl_entry); 153496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (b->type == 0) 154496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->fl_entry, &a->fl_entry); 155496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return b; 156496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 157496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 158496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsint 159496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, 160496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 align, struct nouveau_mm_node **pnode) 161496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 162496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *prev, *this, *next; 163496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 mask = align - 1; 164496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 165496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_for_each_entry_reverse(this, &mm->free, fl_entry) { 166496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 e = this->offset + this->length; 167496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 s = this->offset; 168496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 c = 0, a; 169496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 170496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev = node(this, prev); 171496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (prev && prev->type != type) 172496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = roundup(s, mm->block_size); 173496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 174496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next = node(this, next); 175496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (next && next->type != type) { 176496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e = rounddown(e, mm->block_size); 177496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c = next->offset - e; 178496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 179496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 180496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 181496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = e - s; 182496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || a < size_min) 183496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs continue; 184496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 185496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = min(a, size_max); 186496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (e - a) & ~mask; 187496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c += (e - s) - a; 188496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 189496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (c && !region_tail(mm, this, c)) 1908b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs return -ENOMEM; 191573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 192496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_tail(mm, this, a); 1938b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (!this) 194573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 195573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 1968b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs this->type = type; 197573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_del(&this->fl_entry); 198573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs *pnode = this; 199573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 200573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs } 201573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 202ef1b287169cd3d1e428c8ed8222e0bbf733d5dbbBen Skeggs return -ENOSPC; 203573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 204573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 205573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 206987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) 207573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 208a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs struct nouveau_mm_node *node; 209a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 210a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs if (block) { 211a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mutex_init(&mm->mutex); 212a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->nodes); 213a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->free); 214a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->block_size = block; 215a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes = 0; 216a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs } 217573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 218a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs node = kzalloc(sizeof(*node), GFP_KERNEL); 219a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs if (!node) 220573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 221a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs node->offset = roundup(offset, mm->block_size); 222a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs node->length = rounddown(offset + length, mm->block_size) - node->offset; 223987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs 224a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->nl_entry, &mm->nodes); 225a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->fl_entry, &mm->free); 226a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes++; 227496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs mm->heap_size += length; 228573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 229573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 230573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 231573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 232987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_fini(struct nouveau_mm *mm) 233573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 234ad9ac437a500f8c0822bd5fe139af8ee2c132e15Ben Skeggs struct nouveau_mm_node *node, *heap = 235987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); 236a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs int nodes = 0; 237a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 238a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_for_each_entry(node, &mm->nodes, nl_entry) { 239496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (nodes++ == mm->heap_nodes) 240a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs return -EBUSY; 241ad9ac437a500f8c0822bd5fe139af8ee2c132e15Ben Skeggs } 242573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 243573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs kfree(heap); 244573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 245573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 246