Subversion Repositories Kolibri OS

Rev

Rev 6104 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. /* simple list based uncached page pool
  29.  * - Pool collects resently freed pages for reuse
  30.  * - Use page->lru to keep a free list
  31.  * - doesn't track currently in use pages
  32.  */
  33.  
  34. #define pr_fmt(fmt) "[TTM] " fmt
  35.  
  36. #include <linux/list.h>
  37. #include <linux/spinlock.h>
  38. //#include <linux/highmem.h>
  39. //#include <linux/mm_types.h>
  40. #include <linux/module.h>
  41. #include <linux/mm.h>
  42. #include <linux/seq_file.h> /* for seq_printf */
  43. #include <linux/slab.h>
  44. #include <linux/dma-mapping.h>
  45.  
  46. #include <linux/atomic.h>
  47.  
  48. #include <drm/ttm/ttm_bo_driver.h>
  49. #include <drm/ttm/ttm_page_alloc.h>
  50.  
  51. #ifdef TTM_HAS_AGP
  52. #include <asm/agp.h>
  53. #endif
  54.  
  55. #define NUM_PAGES_TO_ALLOC              (PAGE_SIZE/sizeof(struct page *))
  56. #define SMALL_ALLOCATION                16
  57. #define FREE_ALL_PAGES                  (~0U)
  58. /* times are in msecs */
  59. #define PAGE_FREE_INTERVAL              1000
  60.  
  61. /**
  62.  * struct ttm_page_pool - Pool to reuse recently allocated uc/wc pages.
  63.  *
  64.  * @lock: Protects the shared pool from concurrnet access. Must be used with
  65.  * irqsave/irqrestore variants because pool allocator maybe called from
  66.  * delayed work.
  67.  * @fill_lock: Prevent concurrent calls to fill.
  68.  * @list: Pool of free uc/wc pages for fast reuse.
  69.  * @gfp_flags: Flags to pass for alloc_page.
  70.  * @npages: Number of pages in pool.
  71.  */
  72. struct ttm_page_pool {
  73.         spinlock_t              lock;
  74.         bool                    fill_lock;
  75.         struct list_head        list;
  76.         gfp_t                   gfp_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.         struct kobject          kobj;
  112.         struct ttm_pool_opts    options;
  113.  
  114.         union {
  115.                 struct ttm_page_pool    pools[NUM_POOLS];
  116.                 struct {
  117.                         struct ttm_page_pool    wc_pool;
  118.                         struct ttm_page_pool    uc_pool;
  119.                         struct ttm_page_pool    wc_pool_dma32;
  120.                         struct ttm_page_pool    uc_pool_dma32;
  121.                 } ;
  122.         };
  123. };
  124.  
  125. static void ttm_pool_kobj_release(struct kobject *kobj)
  126. {
  127.         struct ttm_pool_manager *m =
  128.                 container_of(kobj, struct ttm_pool_manager, kobj);
  129.         kfree(m);
  130. }
  131.  
  132. static struct ttm_pool_manager *_manager;
  133.  
  134.  
  135. /**
  136.  * Select the right pool or requested caching state and ttm flags. */
  137. static struct ttm_page_pool *ttm_get_pool(int flags,
  138.                 enum ttm_caching_state cstate)
  139. {
  140.         int pool_index;
  141.  
  142.         if (cstate == tt_cached)
  143.                 return NULL;
  144.  
  145.         if (cstate == tt_wc)
  146.                 pool_index = 0x0;
  147.         else
  148.                 pool_index = 0x1;
  149.  
  150.         if (flags & TTM_PAGE_FLAG_DMA32)
  151.                 pool_index |= 0x2;
  152.  
  153.         return &_manager->pools[pool_index];
  154. }
  155.  
  156. /* set memory back to wb and free the pages. */
  157. static void ttm_pages_put(struct page *pages[], unsigned npages)
  158. {
  159.         unsigned i;
  160.         for (i = 0; i < npages; ++i)
  161.                 __free_page(pages[i]);
  162. }
  163.  
  164. static void ttm_pool_update_free_locked(struct ttm_page_pool *pool,
  165.                 unsigned freed_pages)
  166. {
  167.         pool->npages -= freed_pages;
  168.         pool->nfrees += freed_pages;
  169. }
  170.  
  171.  
  172.  
  173.  
  174. /* Put all pages in pages list to correct pool to wait for reuse */
  175. static void ttm_put_pages(struct page **pages, unsigned npages, int flags,
  176.                           enum ttm_caching_state cstate)
  177. {
  178.         unsigned long irq_flags;
  179.         struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
  180.         unsigned i;
  181.  
  182.         if (1) {
  183.                 /* No pool for this memory type so free the pages */
  184.                 for (i = 0; i < npages; i++) {
  185.                         if (pages[i]) {
  186.                                 __free_page(pages[i]);
  187.                                 pages[i] = NULL;
  188.                         }
  189.                 }
  190.                 return;
  191.         }
  192.  
  193. }
  194.  
  195. /*
  196.  * On success pages list will hold count number of correctly
  197.  * cached pages.
  198.  */
  199. static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
  200.                          enum ttm_caching_state cstate)
  201. {
  202.         struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
  203.         struct list_head plist;
  204.         struct page *p = NULL;
  205.         gfp_t gfp_flags = 0;
  206.         unsigned count;
  207.         int r;
  208.  
  209.        
  210.         /* No pool for cached pages */
  211.         if (1) {
  212.  
  213.                 for (r = 0; r < npages; ++r) {
  214.                         p = alloc_page(gfp_flags);
  215.                         if (!p) {
  216.  
  217.                                 return -ENOMEM;
  218.                         }
  219.  
  220.                         pages[r] = p;
  221.                 }
  222.                 return 0;
  223.         }
  224.  
  225.  
  226.  
  227.         return 0;
  228. }
  229.  
  230. static void ttm_page_pool_init_locked(struct ttm_page_pool *pool, gfp_t flags,
  231.                 char *name)
  232. {
  233.         spin_lock_init(&pool->lock);
  234.         pool->fill_lock = false;
  235.         INIT_LIST_HEAD(&pool->list);
  236.         pool->npages = pool->nfrees = 0;
  237.         pool->gfp_flags = flags;
  238.         pool->name = name;
  239. }
  240.  
  241. int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
  242. {
  243.         int ret;
  244.  
  245.         WARN_ON(_manager);
  246.  
  247.         _manager = kzalloc(sizeof(*_manager), GFP_KERNEL);
  248.  
  249.         _manager->options.max_size = max_pages;
  250.         _manager->options.small = SMALL_ALLOCATION;
  251.         _manager->options.alloc_size = NUM_PAGES_TO_ALLOC;
  252.  
  253.         return 0;
  254. }
  255.  
  256. void ttm_page_alloc_fini(void)
  257. {
  258.         int i;
  259.  
  260.         _manager = NULL;
  261. }
  262.  
  263. int ttm_pool_populate(struct ttm_tt *ttm)
  264. {
  265.         struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
  266.         unsigned i;
  267.         int ret;
  268.  
  269.         if (ttm->state != tt_unpopulated)
  270.                 return 0;
  271.  
  272.         for (i = 0; i < ttm->num_pages; ++i) {
  273.                 ret = ttm_get_pages(&ttm->pages[i], 1,
  274.                                     ttm->page_flags,
  275.                                     ttm->caching_state);
  276.                 if (ret != 0) {
  277.                         ttm_pool_unpopulate(ttm);
  278.                         return -ENOMEM;
  279.                 }
  280.         }
  281.         ttm->state = tt_unbound;
  282.         return 0;
  283. }
  284. EXPORT_SYMBOL(ttm_pool_populate);
  285.  
  286. void ttm_pool_unpopulate(struct ttm_tt *ttm)
  287. {
  288.         unsigned i;
  289.  
  290.         for (i = 0; i < ttm->num_pages; ++i) {
  291.                 if (ttm->pages[i]) {
  292.                         ttm_put_pages(&ttm->pages[i], 1,
  293.                                       ttm->page_flags,
  294.                                       ttm->caching_state);
  295.                 }
  296.         }
  297.         ttm->state = tt_unpopulated;
  298. }
  299. EXPORT_SYMBOL(ttm_pool_unpopulate);
  300.  
  301.