mm.c revision 79456e1a10d5f4e708822287ed0e97af469bf49b
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 4079456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (prev && prev->type == NVKM_MM_TYPE_NONE) { 41496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev->length += this->length; 42496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 43496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = prev; 44496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 45496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 4679456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (next && next->type == NVKM_MM_TYPE_NONE) { 47496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->offset = this->offset; 48496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next->length += this->length; 4979456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (this->type == NVKM_MM_TYPE_NONE) 50496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 51496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->nl_entry); 52496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs kfree(this); this = NULL; 53496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 54496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 5579456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (this && this->type != NVKM_MM_TYPE_NONE) { 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); 6279456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs this->type = NVKM_MM_TYPE_NONE; 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); 8779456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (b->type == NVKM_MM_TYPE_NONE) 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 10179456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs BUG_ON(type == NVKM_MM_TYPE_NONE); 10218902bbf06a93ea497be2f177a6323ed9e5f30beMaarten Lankhorst 103987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs list_for_each_entry(this, &mm->free, fl_entry) { 1048b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs e = this->offset + this->length; 1058b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs s = this->offset; 1068b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1078b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs prev = node(this, prev); 1088b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (prev && prev->type != type) 109987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs s = roundup(s, mm->block_size); 1108b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 1118b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs next = node(this, next); 1128b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (next && next->type != type) 113987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs e = rounddown(e, mm->block_size); 1148b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs 115496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 116496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e &= ~mask; 117496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || e - s < size_min) 118573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs continue; 119573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 1208b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs splitoff = s - this->offset; 121496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (splitoff && !region_head(mm, this, splitoff)) 122496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 123496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 124496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_head(mm, this, min(size_max, e - s)); 125496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (!this) 126496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOMEM; 127496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 128496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this->type = type; 129496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_del(&this->fl_entry); 130496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs *pnode = this; 131496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return 0; 132496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 133496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 134496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return -ENOSPC; 135496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 136496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 137496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsstatic struct nouveau_mm_node * 138496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsregion_tail(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) 139496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 140496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *b; 141496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 142496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (a->length == size) 143496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return a; 144496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 145496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b = kmalloc(sizeof(*b), GFP_KERNEL); 146496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (unlikely(b == NULL)) 147496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return NULL; 148496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 149496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a->length -= size; 150496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->offset = a->offset + a->length; 151496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->length = size; 152496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs b->type = a->type; 153496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 154496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->nl_entry, &a->nl_entry); 15579456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs if (b->type == NVKM_MM_TYPE_NONE) 156496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_add(&b->fl_entry, &a->fl_entry); 157496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs return b; 158496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs} 159496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 160496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsint 161496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggsnouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, 162496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 align, struct nouveau_mm_node **pnode) 163496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs{ 164496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs struct nouveau_mm_node *prev, *this, *next; 165496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 mask = align - 1; 166496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 16779456e1a10d5f4e708822287ed0e97af469bf49bBen Skeggs BUG_ON(type == NVKM_MM_TYPE_NONE); 16818902bbf06a93ea497be2f177a6323ed9e5f30beMaarten Lankhorst 169496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs list_for_each_entry_reverse(this, &mm->free, fl_entry) { 170496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 e = this->offset + this->length; 171496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 s = this->offset; 172496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs u32 c = 0, a; 173496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 174496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs prev = node(this, prev); 175496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (prev && prev->type != type) 176496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = roundup(s, mm->block_size); 177496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 178496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs next = node(this, next); 179496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (next && next->type != type) { 180496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs e = rounddown(e, mm->block_size); 181496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c = next->offset - e; 182496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs } 183496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 184496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (s + mask) & ~mask; 185496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = e - s; 186496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (s > e || a < size_min) 187496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs continue; 188496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 189496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs a = min(a, size_max); 190496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs s = (e - a) & ~mask; 191496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs c += (e - s) - a; 192496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs 193496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs if (c && !region_tail(mm, this, c)) 1948b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs return -ENOMEM; 195573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 196496734bf0391f38c196e16dbbfaaeda8e6ec5845Ben Skeggs this = region_tail(mm, this, a); 1978b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs if (!this) 198573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 199573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 2008b464bfed674fc25d39d8a686010ebe509c8f62aBen Skeggs this->type = type; 201573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs list_del(&this->fl_entry); 202573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs *pnode = this; 203573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 204573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs } 205573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 206ef1b287169cd3d1e428c8ed8222e0bbf733d5dbbBen Skeggs return -ENOSPC; 207573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 208573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 209573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 210987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) 211573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 212a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs struct nouveau_mm_node *node; 213a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 214a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs if (block) { 215a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->nodes); 216a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs INIT_LIST_HEAD(&mm->free); 217a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->block_size = block; 218a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes = 0; 219a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs } 220573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 221a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs node = kzalloc(sizeof(*node), GFP_KERNEL); 222a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs if (!node) 223573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return -ENOMEM; 224a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs 225a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs if (length) { 226a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->offset = roundup(offset, mm->block_size); 227a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->length = rounddown(offset + length, mm->block_size); 228a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs node->length -= node->offset; 229a7dbf00433fa9dc6f4a3828a17d56a9df2bd06b1Ben Skeggs } 230987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggs 231a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->nl_entry, &mm->nodes); 232a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs list_add_tail(&node->fl_entry, &mm->free); 233a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs mm->heap_nodes++; 234573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 235573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 236573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 237573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggsint 238987eec10dd76624d0edacdc7ecc7e1a6fc877373Ben Skeggsnouveau_mm_fini(struct nouveau_mm *mm) 239573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs{ 2407e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs if (nouveau_mm_initialised(mm)) { 2417e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs struct nouveau_mm_node *node, *heap = 2427e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs list_first_entry(&mm->nodes, typeof(*heap), nl_entry); 2437e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs int nodes = 0; 2447e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs 2457e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs list_for_each_entry(node, &mm->nodes, nl_entry) { 2467e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs if (WARN_ON(nodes++ == mm->heap_nodes)) 2477e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs return -EBUSY; 2487e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs } 249a12036ba2c0a190c93e5238c5f32fdb8c023c068Ben Skeggs 2507e0f992b796e102d32b75392fba38be7cab1c5a9Ben Skeggs kfree(heap); 251ad9ac437a500f8c0822bd5fe139af8ee2c132e15Ben Skeggs } 252573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs 253573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs return 0; 254573a2a37e8648a3249426c816f51e7ef50f6f73eBen Skeggs} 255