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