drm: Import the ttm memory manager from FreeBSD
[dragonfly.git] / sys / dev / drm2 / ttm / ttm_page_alloc.c
1 /*
2  * Copyright (c) Red Hat Inc.
3
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sub license,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: Dave Airlie <airlied@redhat.com>
24  *          Jerome Glisse <jglisse@redhat.com>
25  *          Pauli Nieminen <suokkos@gmail.com>
26  */
27 /*
28  * Copyright (c) 2013 The FreeBSD Foundation
29  * All rights reserved.
30  *
31  * Portions of this software were developed by Konstantin Belousov
32  * <kib@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
33  *
34  * $FreeBSD: head/sys/dev/drm2/ttm/ttm_page_alloc.c 247849 2013-03-05 16:15:34Z kib $
35  */
36
37 /* simple list based uncached page pool
38  * - Pool collects resently freed pages for reuse
39  * - Use page->lru to keep a free list
40  * - doesn't track currently in use pages
41  */
42
43
44 #include <dev/drm2/drmP.h>
45 #include <dev/drm2/ttm/ttm_bo_driver.h>
46 #include <dev/drm2/ttm/ttm_page_alloc.h>
47
48 #ifdef TTM_HAS_AGP
49 #include <asm/agp.h>
50 #endif
51
52 #define VM_ALLOC_DMA32  VM_ALLOC_RESERVED1
53
54 #define NUM_PAGES_TO_ALLOC              (PAGE_SIZE/sizeof(vm_page_t))
55 #define SMALL_ALLOCATION                16
56 #define FREE_ALL_PAGES                  (~0U)
57 /* times are in msecs */
58 #define PAGE_FREE_INTERVAL              1000
59
60 /**
61  * struct ttm_page_pool - Pool to reuse recently allocated uc/wc pages.
62  *
63  * @lock: Protects the shared pool from concurrnet access. Must be used with
64  * irqsave/irqrestore variants because pool allocator maybe called from
65  * delayed work.
66  * @fill_lock: Prevent concurrent calls to fill.
67  * @list: Pool of free uc/wc pages for fast reuse.
68  * @gfp_flags: Flags to pass for alloc_page.
69  * @npages: Number of pages in pool.
70  */
71 struct ttm_page_pool {
72         struct mtx              lock;
73         bool                    fill_lock;
74         bool                    dma32;
75         struct pglist           list;
76         int                     ttm_page_alloc_flags;
77         unsigned                npages;
78         char                    *name;
79         unsigned long           nfrees;
80         unsigned long           nrefills;
81 };
82
83 /**
84  * Limits for the pool. They are handled without locks because only place where
85  * they may change is in sysfs store. They won't have immediate effect anyway
86  * so forcing serialization to access them is pointless.
87  */
88
89 struct ttm_pool_opts {
90         unsigned        alloc_size;
91         unsigned        max_size;
92         unsigned        small;
93 };
94
95 #define NUM_POOLS 4
96
97 /**
98  * struct ttm_pool_manager - Holds memory pools for fst allocation
99  *
100  * Manager is read only object for pool code so it doesn't need locking.
101  *
102  * @free_interval: minimum number of jiffies between freeing pages from pool.
103  * @page_alloc_inited: reference counting for pool allocation.
104  * @work: Work that is used to shrink the pool. Work is only run when there is
105  * some pages to free.
106  * @small_allocation: Limit in number of pages what is small allocation.
107  *
108  * @pools: All pool objects in use.
109  **/
110 struct ttm_pool_manager {
111         unsigned int kobj_ref;
112         eventhandler_tag lowmem_handler;
113         struct ttm_pool_opts    options;
114
115         union {
116                 struct ttm_page_pool    u_pools[NUM_POOLS];
117                 struct _utag {
118                         struct ttm_page_pool    u_wc_pool;
119                         struct ttm_page_pool    u_uc_pool;
120                         struct ttm_page_pool    u_wc_pool_dma32;
121                         struct ttm_page_pool    u_uc_pool_dma32;
122                 } _ut;
123         } _u;
124 };
125
126 #define pools _u.u_pools
127 #define wc_pool _u._ut.u_wc_pool
128 #define uc_pool _u._ut.u_uc_pool
129 #define wc_pool_dma32 _u._ut.u_wc_pool_dma32
130 #define uc_pool_dma32 _u._ut.u_uc_pool_dma32
131
132 MALLOC_DEFINE(M_TTM_POOLMGR, "ttm_poolmgr", "TTM Pool Manager");
133
134 static void
135 ttm_vm_page_free(vm_page_t m)
136 {
137
138         KASSERT(m->object == NULL, ("ttm page %p is owned", m));
139         KASSERT(m->wire_count == 1, ("ttm lost wire %p", m));
140         KASSERT((m->flags & PG_FICTITIOUS) != 0, ("ttm lost fictitious %p", m));
141         KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("ttm got unmanaged %p", m));
142         m->flags &= ~PG_FICTITIOUS;
143         m->oflags |= VPO_UNMANAGED;
144         vm_page_unwire(m, 0);
145         vm_page_free(m);
146 }
147
148 static vm_memattr_t
149 ttm_caching_state_to_vm(enum ttm_caching_state cstate)
150 {
151
152         switch (cstate) {
153         case tt_uncached:
154                 return (VM_MEMATTR_UNCACHEABLE);
155         case tt_wc:
156                 return (VM_MEMATTR_WRITE_COMBINING);
157         case tt_cached:
158                 return (VM_MEMATTR_WRITE_BACK);
159         }
160         panic("caching state %d\n", cstate);
161 }
162
163 static void ttm_pool_kobj_release(struct ttm_pool_manager *m)
164 {
165
166         free(m, M_TTM_POOLMGR);
167 }
168
169 #if 0
170 /* XXXKIB sysctl */
171 static ssize_t ttm_pool_store(struct ttm_pool_manager *m,
172                 struct attribute *attr, const char *buffer, size_t size)
173 {
174         int chars;
175         unsigned val;
176         chars = sscanf(buffer, "%u", &val);
177         if (chars == 0)
178                 return size;
179
180         /* Convert kb to number of pages */
181         val = val / (PAGE_SIZE >> 10);
182
183         if (attr == &ttm_page_pool_max)
184                 m->options.max_size = val;
185         else if (attr == &ttm_page_pool_small)
186                 m->options.small = val;
187         else if (attr == &ttm_page_pool_alloc_size) {
188                 if (val > NUM_PAGES_TO_ALLOC*8) {
189                         pr_err("Setting allocation size to %lu is not allowed. Recommended size is %lu\n",
190                                NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7),
191                                NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
192                         return size;
193                 } else if (val > NUM_PAGES_TO_ALLOC) {
194                         pr_warn("Setting allocation size to larger than %lu is not recommended\n",
195                                 NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10));
196                 }
197                 m->options.alloc_size = val;
198         }
199
200         return size;
201 }
202
203 static ssize_t ttm_pool_show(struct ttm_pool_manager *m,
204                 struct attribute *attr, char *buffer)
205 {
206         unsigned val = 0;
207
208         if (attr == &ttm_page_pool_max)
209                 val = m->options.max_size;
210         else if (attr == &ttm_page_pool_small)
211                 val = m->options.small;
212         else if (attr == &ttm_page_pool_alloc_size)
213                 val = m->options.alloc_size;
214
215         val = val * (PAGE_SIZE >> 10);
216
217         return snprintf(buffer, PAGE_SIZE, "%u\n", val);
218 }
219 #endif
220
221 static struct ttm_pool_manager *_manager;
222
223 static int set_pages_array_wb(vm_page_t *pages, int addrinarray)
224 {
225         vm_page_t m;
226         int i;
227
228         for (i = 0; i < addrinarray; i++) {
229                 m = pages[i];
230 #ifdef TTM_HAS_AGP
231                 unmap_page_from_agp(m);
232 #endif
233                 pmap_page_set_memattr(m, VM_MEMATTR_WRITE_BACK);
234         }
235         return 0;
236 }
237
238 static int set_pages_array_wc(vm_page_t *pages, int addrinarray)
239 {
240         vm_page_t m;
241         int i;
242
243         for (i = 0; i < addrinarray; i++) {
244                 m = pages[i];
245 #ifdef TTM_HAS_AGP
246                 map_page_into_agp(pages[i]);
247 #endif
248                 pmap_page_set_memattr(m, VM_MEMATTR_WRITE_COMBINING);
249         }
250         return 0;
251 }
252
253 static int set_pages_array_uc(vm_page_t *pages, int addrinarray)
254 {
255         vm_page_t m;
256         int i;
257
258         for (i = 0; i < addrinarray; i++) {
259                 m = pages[i];
260 #ifdef TTM_HAS_AGP
261                 map_page_into_agp(pages[i]);
262 #endif
263                 pmap_page_set_memattr(m, VM_MEMATTR_UNCACHEABLE);
264         }
265         return 0;
266 }
267
268 /**
269  * Select the right pool or requested caching state and ttm flags. */
270 static struct ttm_page_pool *ttm_get_pool(int flags,
271                 enum ttm_caching_state cstate)
272 {
273         int pool_index;
274
275         if (cstate == tt_cached)
276                 return NULL;
277
278         if (cstate == tt_wc)
279                 pool_index = 0x0;
280         else
281                 pool_index = 0x1;
282
283         if (flags & TTM_PAGE_FLAG_DMA32)
284                 pool_index |= 0x2;
285
286         return &_manager->pools[pool_index];
287 }
288
289 /* set memory back to wb and free the pages. */
290 static void ttm_pages_put(vm_page_t *pages, unsigned npages)
291 {
292         unsigned i;
293
294         /* Our VM handles vm memattr automatically on the page free. */
295         if (set_pages_array_wb(pages, npages))
296                 printf("[TTM] Failed to set %d pages to wb!\n", npages);
297         for (i = 0; i < npages; ++i)
298                 ttm_vm_page_free(pages[i]);
299 }
300
301 static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
302                 unsigned freed_pages)
303 {
304         pool->npages -= freed_pages;
305         pool->nfrees += freed_pages;
306 }
307
308 /**
309  * Free pages from pool.
310  *
311  * To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC
312  * number of pages in one go.
313  *
314  * @pool: to free the pages from
315  * @free_all: If set to true will free all pages in pool
316  **/
317 static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
318 {
319         vm_page_t p, p1;
320         vm_page_t *pages_to_free;
321         unsigned freed_pages = 0,
322                  npages_to_free = nr_free;
323
324         if (NUM_PAGES_TO_ALLOC < nr_free)
325                 npages_to_free = NUM_PAGES_TO_ALLOC;
326
327         pages_to_free = malloc(npages_to_free * sizeof(vm_page_t),
328             M_TEMP, M_WAITOK | M_ZERO);
329
330 restart:
331         mtx_lock(&pool->lock);
332
333         TAILQ_FOREACH_REVERSE_SAFE(p, &pool->list, pglist, pageq, p1) {
334                 if (freed_pages >= npages_to_free)
335                         break;
336
337                 pages_to_free[freed_pages++] = p;
338                 /* We can only remove NUM_PAGES_TO_ALLOC at a time. */
339                 if (freed_pages >= NUM_PAGES_TO_ALLOC) {
340                         /* remove range of pages from the pool */
341                         TAILQ_REMOVE(&pool->list, p, pageq);
342
343                         ttm_pool_update_free_locked(pool, freed_pages);
344                         /**
345                          * Because changing page caching is costly
346                          * we unlock the pool to prevent stalling.
347                          */
348                         mtx_unlock(&pool->lock);
349
350                         ttm_pages_put(pages_to_free, freed_pages);
351                         if (likely(nr_free != FREE_ALL_PAGES))
352                                 nr_free -= freed_pages;
353
354                         if (NUM_PAGES_TO_ALLOC >= nr_free)
355                                 npages_to_free = nr_free;
356                         else
357                                 npages_to_free = NUM_PAGES_TO_ALLOC;
358
359                         freed_pages = 0;
360
361                         /* free all so restart the processing */
362                         if (nr_free)
363                                 goto restart;
364
365                         /* Not allowed to fall through or break because
366                          * following context is inside spinlock while we are
367                          * outside here.
368                          */
369                         goto out;
370
371                 }
372         }
373
374         /* remove range of pages from the pool */
375         if (freed_pages) {
376                 TAILQ_REMOVE(&pool->list, p, pageq);
377
378                 ttm_pool_update_free_locked(pool, freed_pages);
379                 nr_free -= freed_pages;
380         }
381
382         mtx_unlock(&pool->lock);
383
384         if (freed_pages)
385                 ttm_pages_put(pages_to_free, freed_pages);
386 out:
387         free(pages_to_free, M_TEMP);
388         return nr_free;
389 }
390
391 /* Get good estimation how many pages are free in pools */
392 static int ttm_pool_get_num_unused_pages(void)
393 {
394         unsigned i;
395         int total = 0;
396         for (i = 0; i < NUM_POOLS; ++i)
397                 total += _manager->pools[i].npages;
398
399         return total;
400 }
401
402 /**
403  * Callback for mm to request pool to reduce number of page held.
404  */
405 static int ttm_pool_mm_shrink(void *arg)
406 {
407         static unsigned int start_pool = 0;
408         unsigned i;
409         unsigned pool_offset = atomic_fetchadd_int(&start_pool, 1);
410         struct ttm_page_pool *pool;
411         int shrink_pages = 100; /* XXXKIB */
412
413         pool_offset = pool_offset % NUM_POOLS;
414         /* select start pool in round robin fashion */
415         for (i = 0; i < NUM_POOLS; ++i) {
416                 unsigned nr_free = shrink_pages;
417                 if (shrink_pages == 0)
418                         break;
419                 pool = &_manager->pools[(i + pool_offset)%NUM_POOLS];
420                 shrink_pages = ttm_page_pool_free(pool, nr_free);
421         }
422         /* return estimated number of unused pages in pool */
423         return ttm_pool_get_num_unused_pages();
424 }
425
426 static void ttm_pool_mm_shrink_init(struct ttm_pool_manager *manager)
427 {
428
429         manager->lowmem_handler = EVENTHANDLER_REGISTER(vm_lowmem,
430             ttm_pool_mm_shrink, manager, EVENTHANDLER_PRI_ANY);
431 }
432
433 static void ttm_pool_mm_shrink_fini(struct ttm_pool_manager *manager)
434 {
435
436         EVENTHANDLER_DEREGISTER(vm_lowmem, manager->lowmem_handler);
437 }
438
439 static int ttm_set_pages_caching(vm_page_t *pages,
440                 enum ttm_caching_state cstate, unsigned cpages)
441 {
442         int r = 0;
443         /* Set page caching */
444         switch (cstate) {
445         case tt_uncached:
446                 r = set_pages_array_uc(pages, cpages);
447                 if (r)
448                         printf("[TTM] Failed to set %d pages to uc!\n", cpages);
449                 break;
450         case tt_wc:
451                 r = set_pages_array_wc(pages, cpages);
452                 if (r)
453                         printf("[TTM] Failed to set %d pages to wc!\n", cpages);
454                 break;
455         default:
456                 break;
457         }
458         return r;
459 }
460
461 /**
462  * Free pages the pages that failed to change the caching state. If there is
463  * any pages that have changed their caching state already put them to the
464  * pool.
465  */
466 static void ttm_handle_caching_state_failure(struct pglist *pages,
467                 int ttm_flags, enum ttm_caching_state cstate,
468                 vm_page_t *failed_pages, unsigned cpages)
469 {
470         unsigned i;
471         /* Failed pages have to be freed */
472         for (i = 0; i < cpages; ++i) {
473                 TAILQ_REMOVE(pages, failed_pages[i], pageq);
474                 ttm_vm_page_free(failed_pages[i]);
475         }
476 }
477
478 /**
479  * Allocate new pages with correct caching.
480  *
481  * This function is reentrant if caller updates count depending on number of
482  * pages returned in pages array.
483  */
484 static int ttm_alloc_new_pages(struct pglist *pages, int ttm_alloc_flags,
485                 int ttm_flags, enum ttm_caching_state cstate, unsigned count)
486 {
487         vm_page_t *caching_array;
488         vm_page_t p;
489         int r = 0;
490         unsigned i, cpages, aflags;
491         unsigned max_cpages = min(count,
492                         (unsigned)(PAGE_SIZE/sizeof(vm_page_t)));
493
494         aflags = VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ |
495             ((ttm_alloc_flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ?
496             VM_ALLOC_ZERO : 0);
497         
498         /* allocate array for page caching change */
499         caching_array = malloc(max_cpages * sizeof(vm_page_t), M_TEMP,
500             M_WAITOK | M_ZERO);
501
502         for (i = 0, cpages = 0; i < count; ++i) {
503                 p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0,
504                     (ttm_alloc_flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff :
505                     VM_MAX_ADDRESS, PAGE_SIZE, 0,
506                     ttm_caching_state_to_vm(cstate));
507                 if (!p) {
508                         printf("[TTM] Unable to get page %u\n", i);
509
510                         /* store already allocated pages in the pool after
511                          * setting the caching state */
512                         if (cpages) {
513                                 r = ttm_set_pages_caching(caching_array,
514                                                           cstate, cpages);
515                                 if (r)
516                                         ttm_handle_caching_state_failure(pages,
517                                                 ttm_flags, cstate,
518                                                 caching_array, cpages);
519                         }
520                         r = -ENOMEM;
521                         goto out;
522                 }
523                 p->oflags &= ~VPO_UNMANAGED;
524                 p->flags |= PG_FICTITIOUS;
525
526 #ifdef CONFIG_HIGHMEM /* KIB: nop */
527                 /* gfp flags of highmem page should never be dma32 so we
528                  * we should be fine in such case
529                  */
530                 if (!PageHighMem(p))
531 #endif
532                 {
533                         caching_array[cpages++] = p;
534                         if (cpages == max_cpages) {
535
536                                 r = ttm_set_pages_caching(caching_array,
537                                                 cstate, cpages);
538                                 if (r) {
539                                         ttm_handle_caching_state_failure(pages,
540                                                 ttm_flags, cstate,
541                                                 caching_array, cpages);
542                                         goto out;
543                                 }
544                                 cpages = 0;
545                         }
546                 }
547
548                 TAILQ_INSERT_HEAD(pages, p, pageq);
549         }
550
551         if (cpages) {
552                 r = ttm_set_pages_caching(caching_array, cstate, cpages);
553                 if (r)
554                         ttm_handle_caching_state_failure(pages,
555                                         ttm_flags, cstate,
556                                         caching_array, cpages);
557         }
558 out:
559         free(caching_array, M_TEMP);
560
561         return r;
562 }
563
564 /**
565  * Fill the given pool if there aren't enough pages and the requested number of
566  * pages is small.
567  */
568 static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool,
569     int ttm_flags, enum ttm_caching_state cstate, unsigned count)
570 {
571         vm_page_t p;
572         int r;
573         unsigned cpages = 0;
574         /**
575          * Only allow one pool fill operation at a time.
576          * If pool doesn't have enough pages for the allocation new pages are
577          * allocated from outside of pool.
578          */
579         if (pool->fill_lock)
580                 return;
581
582         pool->fill_lock = true;
583
584         /* If allocation request is small and there are not enough
585          * pages in a pool we fill the pool up first. */
586         if (count < _manager->options.small
587                 && count > pool->npages) {
588                 struct pglist new_pages;
589                 unsigned alloc_size = _manager->options.alloc_size;
590
591                 /**
592                  * Can't change page caching if in irqsave context. We have to
593                  * drop the pool->lock.
594                  */
595                 mtx_unlock(&pool->lock);
596
597                 TAILQ_INIT(&new_pages);
598                 r = ttm_alloc_new_pages(&new_pages, pool->ttm_page_alloc_flags,
599                     ttm_flags, cstate, alloc_size);
600                 mtx_lock(&pool->lock);
601
602                 if (!r) {
603                         TAILQ_CONCAT(&pool->list, &new_pages, pageq);
604                         ++pool->nrefills;
605                         pool->npages += alloc_size;
606                 } else {
607                         printf("[TTM] Failed to fill pool (%p)\n", pool);
608                         /* If we have any pages left put them to the pool. */
609                         TAILQ_FOREACH(p, &pool->list, pageq) {
610                                 ++cpages;
611                         }
612                         TAILQ_CONCAT(&pool->list, &new_pages, pageq);
613                         pool->npages += cpages;
614                 }
615
616         }
617         pool->fill_lock = false;
618 }
619
620 /**
621  * Cut 'count' number of pages from the pool and put them on the return list.
622  *
623  * @return count of pages still required to fulfill the request.
624  */
625 static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool,
626                                         struct pglist *pages,
627                                         int ttm_flags,
628                                         enum ttm_caching_state cstate,
629                                         unsigned count)
630 {
631         vm_page_t p;
632         unsigned i;
633
634         mtx_lock(&pool->lock);
635         ttm_page_pool_fill_locked(pool, ttm_flags, cstate, count);
636
637         if (count >= pool->npages) {
638                 /* take all pages from the pool */
639                 TAILQ_CONCAT(pages, &pool->list, pageq);
640                 count -= pool->npages;
641                 pool->npages = 0;
642                 goto out;
643         }
644         for (i = 0; i < count; i++) {
645                 p = TAILQ_FIRST(&pool->list);
646                 TAILQ_REMOVE(&pool->list, p, pageq);
647                 TAILQ_INSERT_TAIL(pages, p, pageq);
648         }
649         pool->npages -= count;
650         count = 0;
651 out:
652         mtx_unlock(&pool->lock);
653         return count;
654 }
655
656 /* Put all pages in pages list to correct pool to wait for reuse */
657 static void ttm_put_pages(vm_page_t *pages, unsigned npages, int flags,
658                           enum ttm_caching_state cstate)
659 {
660         struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
661         unsigned i;
662
663         if (pool == NULL) {
664                 /* No pool for this memory type so free the pages */
665                 for (i = 0; i < npages; i++) {
666                         if (pages[i]) {
667                                 ttm_vm_page_free(pages[i]);
668                                 pages[i] = NULL;
669                         }
670                 }
671                 return;
672         }
673
674         mtx_lock(&pool->lock);
675         for (i = 0; i < npages; i++) {
676                 if (pages[i]) {
677                         TAILQ_INSERT_TAIL(&pool->list, pages[i], pageq);
678                         pages[i] = NULL;
679                         pool->npages++;
680                 }
681         }
682         /* Check that we don't go over the pool limit */
683         npages = 0;
684         if (pool->npages > _manager->options.max_size) {
685                 npages = pool->npages - _manager->options.max_size;
686                 /* free at least NUM_PAGES_TO_ALLOC number of pages
687                  * to reduce calls to set_memory_wb */
688                 if (npages < NUM_PAGES_TO_ALLOC)
689                         npages = NUM_PAGES_TO_ALLOC;
690         }
691         mtx_unlock(&pool->lock);
692         if (npages)
693                 ttm_page_pool_free(pool, npages);
694 }
695
696 /*
697  * On success pages list will hold count number of correctly
698  * cached pages.
699  */
700 static int ttm_get_pages(vm_page_t *pages, unsigned npages, int flags,
701                          enum ttm_caching_state cstate)
702 {
703         struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
704         struct pglist plist;
705         vm_page_t p = NULL;
706         int gfp_flags, aflags;
707         unsigned count;
708         int r;
709
710         aflags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
711             ((flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ? VM_ALLOC_ZERO : 0);
712
713         /* No pool for cached pages */
714         if (pool == NULL) {
715                 for (r = 0; r < npages; ++r) {
716                         p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0,
717                             (flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff :
718                             VM_MAX_ADDRESS, PAGE_SIZE,
719                             0, ttm_caching_state_to_vm(cstate));
720                         if (!p) {
721                                 printf("[TTM] Unable to allocate page\n");
722                                 return -ENOMEM;
723                         }
724                         p->oflags &= ~VPO_UNMANAGED;
725                         p->flags |= PG_FICTITIOUS;
726                         pages[r] = p;
727                 }
728                 return 0;
729         }
730
731         /* combine zero flag to pool flags */
732         gfp_flags = flags | pool->ttm_page_alloc_flags;
733
734         /* First we take pages from the pool */
735         TAILQ_INIT(&plist);
736         npages = ttm_page_pool_get_pages(pool, &plist, flags, cstate, npages);
737         count = 0;
738         TAILQ_FOREACH(p, &plist, pageq) {
739                 pages[count++] = p;
740         }
741
742         /* clear the pages coming from the pool if requested */
743         if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
744                 TAILQ_FOREACH(p, &plist, pageq) {
745                         pmap_zero_page(p);
746                 }
747         }
748
749         /* If pool didn't have enough pages allocate new one. */
750         if (npages > 0) {
751                 /* ttm_alloc_new_pages doesn't reference pool so we can run
752                  * multiple requests in parallel.
753                  **/
754                 TAILQ_INIT(&plist);
755                 r = ttm_alloc_new_pages(&plist, gfp_flags, flags, cstate,
756                     npages);
757                 TAILQ_FOREACH(p, &plist, pageq) {
758                         pages[count++] = p;
759                 }
760                 if (r) {
761                         /* If there is any pages in the list put them back to
762                          * the pool. */
763                         printf("[TTM] Failed to allocate extra pages for large request\n");
764                         ttm_put_pages(pages, count, flags, cstate);
765                         return r;
766                 }
767         }
768
769         return 0;
770 }
771
772 static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, int flags,
773                                       char *name)
774 {
775         mtx_init(&pool->lock, "ttmpool", NULL, MTX_DEF);
776         pool->fill_lock = false;
777         TAILQ_INIT(&pool->list);
778         pool->npages = pool->nfrees = 0;
779         pool->ttm_page_alloc_flags = flags;
780         pool->name = name;
781 }
782
783 int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
784 {
785
786         if (_manager != NULL)
787                 printf("[TTM] manager != NULL\n");
788         printf("[TTM] Initializing pool allocator\n");
789
790         _manager = malloc(sizeof(*_manager), M_TTM_POOLMGR, M_WAITOK | M_ZERO);
791
792         ttm_page_pool_init_locked(&_manager->wc_pool, 0, "wc");
793         ttm_page_pool_init_locked(&_manager->uc_pool, 0, "uc");
794         ttm_page_pool_init_locked(&_manager->wc_pool_dma32,
795             TTM_PAGE_FLAG_DMA32, "wc dma");
796         ttm_page_pool_init_locked(&_manager->uc_pool_dma32,
797             TTM_PAGE_FLAG_DMA32, "uc dma");
798
799         _manager->options.max_size = max_pages;
800         _manager->options.small = SMALL_ALLOCATION;
801         _manager->options.alloc_size = NUM_PAGES_TO_ALLOC;
802
803         refcount_init(&_manager->kobj_ref, 1);
804         ttm_pool_mm_shrink_init(_manager);
805
806         return 0;
807 }
808
809 void ttm_page_alloc_fini(void)
810 {
811         int i;
812
813         printf("[TTM] Finalizing pool allocator\n");
814         ttm_pool_mm_shrink_fini(_manager);
815
816         for (i = 0; i < NUM_POOLS; ++i)
817                 ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES);
818
819         if (refcount_release(&_manager->kobj_ref))
820                 ttm_pool_kobj_release(_manager);
821         _manager = NULL;
822 }
823
824 int ttm_pool_populate(struct ttm_tt *ttm)
825 {
826         struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
827         unsigned i;
828         int ret;
829
830         if (ttm->state != tt_unpopulated)
831                 return 0;
832
833         for (i = 0; i < ttm->num_pages; ++i) {
834                 ret = ttm_get_pages(&ttm->pages[i], 1,
835                                     ttm->page_flags,
836                                     ttm->caching_state);
837                 if (ret != 0) {
838                         ttm_pool_unpopulate(ttm);
839                         return -ENOMEM;
840                 }
841
842                 ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
843                                                 false, false);
844                 if (unlikely(ret != 0)) {
845                         ttm_pool_unpopulate(ttm);
846                         return -ENOMEM;
847                 }
848         }
849
850         if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) {
851                 ret = ttm_tt_swapin(ttm);
852                 if (unlikely(ret != 0)) {
853                         ttm_pool_unpopulate(ttm);
854                         return ret;
855                 }
856         }
857
858         ttm->state = tt_unbound;
859         return 0;
860 }
861
862 void ttm_pool_unpopulate(struct ttm_tt *ttm)
863 {
864         unsigned i;
865
866         for (i = 0; i < ttm->num_pages; ++i) {
867                 if (ttm->pages[i]) {
868                         ttm_mem_global_free_page(ttm->glob->mem_glob,
869                                                  ttm->pages[i]);
870                         ttm_put_pages(&ttm->pages[i], 1,
871                                       ttm->page_flags,
872                                       ttm->caching_state);
873                 }
874         }
875         ttm->state = tt_unpopulated;
876 }
877
878 #if 0
879 /* XXXKIB sysctl */
880 int ttm_page_alloc_debugfs(struct seq_file *m, void *data)
881 {
882         struct ttm_page_pool *p;
883         unsigned i;
884         char *h[] = {"pool", "refills", "pages freed", "size"};
885         if (!_manager) {
886                 seq_printf(m, "No pool allocator running.\n");
887                 return 0;
888         }
889         seq_printf(m, "%6s %12s %13s %8s\n",
890                         h[0], h[1], h[2], h[3]);
891         for (i = 0; i < NUM_POOLS; ++i) {
892                 p = &_manager->pools[i];
893
894                 seq_printf(m, "%6s %12ld %13ld %8d\n",
895                                 p->name, p->nrefills,
896                                 p->nfrees, p->npages);
897         }
898         return 0;
899 }
900 #endif