1f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 2d49525d0c52601f8c4abec82590ca4ffb896a614Christoph Bumiller#include <inttypes.h> 3d49525d0c52601f8c4abec82590ca4ffb896a614Christoph Bumiller 4f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#include "util/u_inlines.h" 5f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#include "util/u_memory.h" 6f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#include "util/u_double_list.h" 7f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 86d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller#include "nouveau_winsys.h" 92f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs#include "nouveau_screen.h" 102f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs#include "nouveau_mm.h" 112f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs 12f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#define MM_MIN_ORDER 7 13f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#define MM_MAX_ORDER 20 14f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 15f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1) 16f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 17f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#define MM_MIN_SIZE (1 << MM_MIN_ORDER) 18f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller#define MM_MAX_SIZE (1 << MM_MAX_ORDER) 19f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 20f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstruct mm_bucket { 21f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct list_head free; 22f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct list_head used; 23f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct list_head full; 24f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int num_free; 25f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller}; 26f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 272f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsstruct nouveau_mman { 28f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct nouveau_device *dev; 29f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_bucket bucket[MM_NUM_BUCKETS]; 30f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller uint32_t domain; 316d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller union nouveau_bo_config config; 32f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller uint64_t allocated; 33f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller}; 34f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 35f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstruct mm_slab { 36f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct list_head head; 37f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct nouveau_bo *bo; 382f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs struct nouveau_mman *cache; 39f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int order; 40f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int count; 41f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int free; 42f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller uint32_t bits[0]; 43f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller}; 44f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 45f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic int 46f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillermm_slab_alloc(struct mm_slab *slab) 47f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 48f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int i, n, b; 49f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 50f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (slab->free == 0) 51f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return -1; 52f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 53f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller for (i = 0; i < (slab->count + 31) / 32; ++i) { 54f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller b = ffs(slab->bits[i]) - 1; 55f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (b >= 0) { 56f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller n = i * 32 + b; 57f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller assert(n < slab->count); 58f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->free--; 59f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->bits[i] &= ~(1 << b); 60f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return n; 61f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 62f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 63f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return -1; 64f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 65f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 66f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic INLINE void 67f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillermm_slab_free(struct mm_slab *slab, int i) 68f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 69f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller assert(i < slab->count); 70f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->bits[i / 32] |= 1 << (i % 32); 71f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->free++; 72f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller assert(slab->free <= slab->count); 73f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 74f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 75f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic INLINE int 76f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillermm_get_order(uint32_t size) 77f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 78f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int s = __builtin_clz(size) ^ 31; 79f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 80f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (size > (1 << s)) 81f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller s += 1; 82f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return s; 83f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 84f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 85f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic struct mm_bucket * 862f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsmm_bucket_by_order(struct nouveau_mman *cache, int order) 87f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 88f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (order > MM_MAX_ORDER) 89f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return NULL; 90f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return &cache->bucket[MAX2(order, MM_MIN_ORDER) - MM_MIN_ORDER]; 91f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 92f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 93f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic struct mm_bucket * 942f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsmm_bucket_by_size(struct nouveau_mman *cache, unsigned size) 95f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 96f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return mm_bucket_by_order(cache, mm_get_order(size)); 97f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 98f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 99f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller/* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */ 100f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic INLINE uint32_t 101f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillermm_default_slab_size(unsigned chunk_order) 102f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 103f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = 104f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller { 105f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 106f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller }; 107f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 108f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); 109f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 110f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return 1 << slab_order[chunk_order - MM_MIN_ORDER]; 111f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 112f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 113f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic int 1142f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsmm_slab_new(struct nouveau_mman *cache, int chunk_order) 115f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 116f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_slab *slab; 117f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int words, ret; 118f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller const uint32_t size = mm_default_slab_size(chunk_order); 119f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 120f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller words = ((size >> chunk_order) + 31) / 32; 121f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller assert(words); 122f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 123f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab = MALLOC(sizeof(struct mm_slab) + words * 4); 124f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!slab) 125f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return PIPE_ERROR_OUT_OF_MEMORY; 126f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 127f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller memset(&slab->bits[0], ~0, words * 4); 128f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 129f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->bo = NULL; 1306d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller 1316d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, 1326d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller &slab->bo); 133f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (ret) { 134f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller FREE(slab); 135f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return PIPE_ERROR_OUT_OF_MEMORY; 136f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 137f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 138f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_INITHEAD(&slab->head); 139f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 140f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->cache = cache; 141f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->order = chunk_order; 142f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab->count = slab->free = size >> chunk_order; 143f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 144f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free); 145f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 146f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller cache->allocated += size; 147f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 14890dcd6c89ab4afa55ca19d572a1a695cf55cb1b2Marcin Slusarz if (nouveau_mesa_debug) 14990dcd6c89ab4afa55ca19d572a1a695cf55cb1b2Marcin Slusarz debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n", 15090dcd6c89ab4afa55ca19d572a1a695cf55cb1b2Marcin Slusarz cache->allocated / 1024); 151f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 152f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return PIPE_OK; 153f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 154f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 155f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller/* @return token to identify slab or NULL if we just allocated a new bo */ 1562f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsstruct nouveau_mm_allocation * 1572f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsnouveau_mm_allocate(struct nouveau_mman *cache, 1586d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller uint32_t size, struct nouveau_bo **bo, uint32_t *offset) 159f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 160f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_bucket *bucket; 161f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_slab *slab; 1622f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs struct nouveau_mm_allocation *alloc; 163f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int ret; 164f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 165f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller bucket = mm_bucket_by_size(cache, size); 166f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!bucket) { 1676d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, 1686d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller bo); 169f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (ret) 1706d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller debug_printf("bo_new(%x, %x): %i\n", 1716d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller size, cache->config.nv50.memtype, ret); 172f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 173f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller *offset = 0; 174f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return NULL; 175f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 176f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 177f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!LIST_IS_EMPTY(&bucket->used)) { 178f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head); 179f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } else { 180f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (LIST_IS_EMPTY(&bucket->free)) { 181f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER)); 182f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 183f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head); 184f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 185f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_DEL(&slab->head); 186f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_ADD(&slab->head, &bucket->used); 187f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 188f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 189f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller *offset = mm_slab_alloc(slab) << slab->order; 190f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 1912f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs alloc = MALLOC_STRUCT(nouveau_mm_allocation); 192f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!alloc) 193f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return NULL; 194f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 195f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller nouveau_bo_ref(slab->bo, bo); 196f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 197f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (slab->free == 0) { 198f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_DEL(&slab->head); 199f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_ADD(&slab->head, &bucket->full); 200f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 201f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 202f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller alloc->next = NULL; 203f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller alloc->offset = *offset; 204f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller alloc->priv = (void *)slab; 205f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 206f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return alloc; 207f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 208f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 209f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillervoid 2102f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsnouveau_mm_free(struct nouveau_mm_allocation *alloc) 211f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 212f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_slab *slab = (struct mm_slab *)alloc->priv; 213f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order); 214f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 215f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller mm_slab_free(slab, alloc->offset >> slab->order); 216f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 2178476232b080821b859b02add4cb7869fa4a4f2b3Christoph Bumiller if (slab->free == slab->count) { 2188476232b080821b859b02add4cb7869fa4a4f2b3Christoph Bumiller LIST_DEL(&slab->head); 2198476232b080821b859b02add4cb7869fa4a4f2b3Christoph Bumiller LIST_ADDTAIL(&slab->head, &bucket->free); 2208476232b080821b859b02add4cb7869fa4a4f2b3Christoph Bumiller } else 221f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (slab->free == 1) { 222f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_DEL(&slab->head); 2238476232b080821b859b02add4cb7869fa4a4f2b3Christoph Bumiller LIST_ADDTAIL(&slab->head, &bucket->used); 224f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 225f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 226f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller FREE(alloc); 227f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 228f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 229d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggsvoid 230d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggsnouveau_mm_free_work(void *data) 231d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggs{ 232d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggs nouveau_mm_free(data); 233d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggs} 234d6bdf1f6ae6f8d06db740ad75e9151ef275755b2Ben Skeggs 2352f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsstruct nouveau_mman * 2362f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsnouveau_mm_create(struct nouveau_device *dev, uint32_t domain, 2376d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller union nouveau_bo_config *config) 238f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 2392f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs struct nouveau_mman *cache = MALLOC_STRUCT(nouveau_mman); 240f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int i; 241f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 242f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!cache) 243f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return NULL; 244f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 245f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller cache->dev = dev; 246f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller cache->domain = domain; 2476d1cdec3ba151168bfc3aef222fba6265dfb41fbChristoph Bumiller cache->config = *config; 248f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller cache->allocated = 0; 249f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 250f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller for (i = 0; i < MM_NUM_BUCKETS; ++i) { 251f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_INITHEAD(&cache->bucket[i].free); 252f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_INITHEAD(&cache->bucket[i].used); 253f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_INITHEAD(&cache->bucket[i].full); 254f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 255f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 256f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return cache; 257f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 258f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 259f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillerstatic INLINE void 2602f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsnouveau_mm_free_slabs(struct list_head *head) 261f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 262f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller struct mm_slab *slab, *next; 263f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 264f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) { 265f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller LIST_DEL(&slab->head); 266f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller nouveau_bo_ref(NULL, &slab->bo); 267f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller FREE(slab); 268f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 269f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 270f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 271f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumillervoid 2722f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggsnouveau_mm_destroy(struct nouveau_mman *cache) 273f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller{ 274f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller int i; 275f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 276f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!cache) 277f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller return; 278f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 279f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller for (i = 0; i < MM_NUM_BUCKETS; ++i) { 280f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller if (!LIST_IS_EMPTY(&cache->bucket[i].used) || 281f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller !LIST_IS_EMPTY(&cache->bucket[i].full)) 282f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller debug_printf("WARNING: destroying GPU memory cache " 283f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller "with some buffers still in use\n"); 284f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 2852f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs nouveau_mm_free_slabs(&cache->bucket[i].free); 2862f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs nouveau_mm_free_slabs(&cache->bucket[i].used); 2872f30a5bdaad480118e23ac4243de3b4a11ba62a8Ben Skeggs nouveau_mm_free_slabs(&cache->bucket[i].full); 288f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller } 28996d57722fda62e7710eb5281bcf014ddfb824ef9Ben Skeggs 29096d57722fda62e7710eb5281bcf014ddfb824ef9Ben Skeggs FREE(cache); 291f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller} 292f80c03e1875fe96ff2f4c022e3cb76357828140dChristoph Bumiller 293