1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <inttypes.h> 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_inlines.h" 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h" 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_double_list.h" 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nouveau_winsys.h" 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nouveau_screen.h" 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "nouveau_mm.h" 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MM_MIN_ORDER 7 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MM_MAX_ORDER 20 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1) 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MM_MIN_SIZE (1 << MM_MIN_ORDER) 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MM_MAX_SIZE (1 << MM_MAX_ORDER) 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct mm_bucket { 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct list_head free; 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct list_head used; 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct list_head full; 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int num_free; 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct nouveau_mman { 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct nouveau_device *dev; 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_bucket bucket[MM_NUM_BUCKETS]; 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint32_t domain; 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org union nouveau_bo_config config; 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint64_t allocated; 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct mm_slab { 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct list_head head; 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct nouveau_bo *bo; 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct nouveau_mman *cache; 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int order; 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int count; 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int free; 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint32_t bits[0]; 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_slab_alloc(struct mm_slab *slab) 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int i, n, b; 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (slab->free == 0) 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < (slab->count + 31) / 32; ++i) { 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org b = ffs(slab->bits[i]) - 1; 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (b >= 0) { 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org n = i * 32 + b; 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(n < slab->count); 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->free--; 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->bits[i] &= ~(1 << b); 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return n; 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return -1; 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_slab_free(struct mm_slab *slab, int i) 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(i < slab->count); 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->bits[i / 32] |= 1 << (i % 32); 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->free++; 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(slab->free <= slab->count); 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE int 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_get_order(uint32_t size) 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int s = __builtin_clz(size) ^ 31; 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (size > (1 << s)) 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org s += 1; 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return s; 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct mm_bucket * 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_bucket_by_order(struct nouveau_mman *cache, int order) 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (order > MM_MAX_ORDER) 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return &cache->bucket[MAX2(order, MM_MIN_ORDER) - MM_MIN_ORDER]; 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct mm_bucket * 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_bucket_by_size(struct nouveau_mman *cache, unsigned size) 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return mm_bucket_by_order(cache, mm_get_order(size)); 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */ 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE uint32_t 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_default_slab_size(unsigned chunk_order) 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return 1 << slab_order[chunk_order - MM_MIN_ORDER]; 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmm_slab_new(struct nouveau_mman *cache, int chunk_order) 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_slab *slab; 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int words, ret; 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const uint32_t size = mm_default_slab_size(chunk_order); 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org words = ((size >> chunk_order) + 31) / 32; 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(words); 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab = MALLOC(sizeof(struct mm_slab) + words * 4); 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!slab) 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return PIPE_ERROR_OUT_OF_MEMORY; 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org memset(&slab->bits[0], ~0, words * 4); 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->bo = NULL; 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &slab->bo); 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ret) { 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FREE(slab); 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return PIPE_ERROR_OUT_OF_MEMORY; 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_INITHEAD(&slab->head); 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->cache = cache; 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->order = chunk_order; 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab->count = slab->free = size >> chunk_order; 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free); 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->allocated += size; 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (nouveau_mesa_debug) 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n", 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->allocated / 1024); 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return PIPE_OK; 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* @return token to identify slab or NULL if we just allocated a new bo */ 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct nouveau_mm_allocation * 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_allocate(struct nouveau_mman *cache, 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org uint32_t size, struct nouveau_bo **bo, uint32_t *offset) 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_bucket *bucket; 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_slab *slab; 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct nouveau_mm_allocation *alloc; 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int ret; 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bucket = mm_bucket_by_size(cache, size); 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!bucket) { 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bo); 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ret) 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org debug_printf("bo_new(%x, %x): %i\n", 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org size, cache->config.nv50.memtype, ret); 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *offset = 0; 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!LIST_IS_EMPTY(&bucket->used)) { 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head); 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (LIST_IS_EMPTY(&bucket->free)) { 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER)); 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head); 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_DEL(&slab->head); 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_ADD(&slab->head, &bucket->used); 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *offset = mm_slab_alloc(slab) << slab->order; 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc = MALLOC_STRUCT(nouveau_mm_allocation); 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!alloc) 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_bo_ref(slab->bo, bo); 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (slab->free == 0) { 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_DEL(&slab->head); 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_ADD(&slab->head, &bucket->full); 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc->next = NULL; 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc->offset = *offset; 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org alloc->priv = (void *)slab; 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return alloc; 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_free(struct nouveau_mm_allocation *alloc) 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_slab *slab = (struct mm_slab *)alloc->priv; 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order); 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mm_slab_free(slab, alloc->offset >> slab->order); 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (slab->free == slab->count) { 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_DEL(&slab->head); 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_ADDTAIL(&slab->head, &bucket->free); 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (slab->free == 1) { 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_DEL(&slab->head); 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_ADDTAIL(&slab->head, &bucket->used); 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FREE(alloc); 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_free_work(void *data) 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_mm_free(data); 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct nouveau_mman * 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_create(struct nouveau_device *dev, uint32_t domain, 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org union nouveau_bo_config *config) 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct nouveau_mman *cache = MALLOC_STRUCT(nouveau_mman); 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int i; 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!cache) 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->dev = dev; 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->domain = domain; 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->config = *config; 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cache->allocated = 0; 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < MM_NUM_BUCKETS; ++i) { 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_INITHEAD(&cache->bucket[i].free); 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_INITHEAD(&cache->bucket[i].used); 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_INITHEAD(&cache->bucket[i].full); 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return cache; 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_free_slabs(struct list_head *head) 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct mm_slab *slab, *next; 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) { 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LIST_DEL(&slab->head); 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_bo_ref(NULL, &slab->bo); 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FREE(slab); 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnouveau_mm_destroy(struct nouveau_mman *cache) 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org int i; 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!cache) 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (i = 0; i < MM_NUM_BUCKETS; ++i) { 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!LIST_IS_EMPTY(&cache->bucket[i].used) || 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org !LIST_IS_EMPTY(&cache->bucket[i].full)) 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org debug_printf("WARNING: destroying GPU memory cache " 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "with some buffers still in use\n"); 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_mm_free_slabs(&cache->bucket[i].free); 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_mm_free_slabs(&cache->bucket[i].used); 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org nouveau_mm_free_slabs(&cache->bucket[i].full); 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FREE(cache); 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 293