ttm_page_alloc_dma.c revision 2c05114d23c4fd2256eaf5645528c19fcefdb2c8
12334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 22334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Copyright 2011 (c) Oracle Corp. 32334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 42334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Permission is hereby granted, free of charge, to any person obtaining a 52334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * copy of this software and associated documentation files (the "Software"), 62334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * to deal in the Software without restriction, including without limitation 72334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * the rights to use, copy, modify, merge, publish, distribute, sub license, 82334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * and/or sell copies of the Software, and to permit persons to whom the 92334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Software is furnished to do so, subject to the following conditions: 102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The above copyright notice and this permission notice (including the 122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * next paragraph) shall be included in all copies or substantial portions 132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * of the Software. 142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * DEALINGS IN THE SOFTWARE. 222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Author: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> 242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * A simple DMA pool losely based on dmapool.c. It has certain advantages 282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * over the DMA pools: 292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - Pool collects resently freed pages for reuse (and hooks up to 302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * the shrinker). 312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - Tracks currently in use pages 322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - Tracks whether the page is UC, WB or cached (and reverts to WB 332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * when freed). 342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/dma-mapping.h> 372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/list.h> 382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/seq_file.h> /* for seq_printf */ 392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/slab.h> 402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/spinlock.h> 412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/highmem.h> 422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/mm_types.h> 432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/module.h> 442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/mm.h> 452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/atomic.h> 462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/device.h> 472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <linux/kthread.h> 482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include "ttm/ttm_bo_driver.h" 492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include "ttm/ttm_page_alloc.h" 502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifdef TTM_HAS_AGP 512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#include <asm/agp.h> 522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) 552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define SMALL_ALLOCATION 4 562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define FREE_ALL_PAGES (~0U) 572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* times are in msecs */ 582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define IS_UNDEFINED (0) 592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define IS_WC (1<<1) 602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define IS_UC (1<<2) 612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define IS_CACHED (1<<3) 622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#define IS_DMA32 (1<<4) 632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkenum pool_type { 652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_UNDEFINED, 662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_WC = IS_WC, 672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_UC = IS_UC, 682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_CACHED = IS_CACHED, 692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_WC_DMA32 = IS_WC | IS_DMA32, 702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_UC_DMA32 = IS_UC | IS_DMA32, 712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk POOL_IS_CACHED_DMA32 = IS_CACHED | IS_DMA32, 722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The pool structure. There are usually six pools: 752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - generic (not restricted to DMA32): 762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - write combined, uncached, cached. 772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - dma32 (up to 2^32 - so up 4GB): 782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - write combined, uncached, cached. 792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * for each 'struct device'. The 'cached' is for pages that are actively used. 802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The other ones can be shrunk by the shrinker API if neccessary. 812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @pools: The 'struct device->dma_pools' link. 822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @type: Type of the pool 832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @lock: Protects the inuse_list and free_list from concurrnet access. Must be 842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * used with irqsave/irqrestore variants because pool allocator maybe called 852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * from delayed work. 862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @inuse_list: Pool of pages that are in use. The order is very important and 872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * it is in the order that the TTM pages that are put back are in. 882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @free_list: Pool of pages that are free to be used. No order requirements. 892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @dev: The device that is associated with these pools. 902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @size: Size used during DMA allocation. 912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @npages_free: Count of available pages for re-use. 922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @npages_in_use: Count of pages that are in use. 932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @nfrees: Stats when pool is shrinking. 942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @nrefills: Stats when the pool is grown. 952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @gfp_flags: Flags to pass for alloc_page. 962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @name: Name of the pool. 972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @dev_name: Name derieved from dev - similar to how dev_info works. 982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Used during shutdown as the dev_info during release is unavailable. 992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 1002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstruct dma_pool { 1012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head pools; /* The 'struct device->dma_pools link */ 1022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type; 1032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spinlock_t lock; 1042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head inuse_list; 1052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head free_list; 1062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device *dev; 1072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned size; 1082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned npages_free; 1092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned npages_in_use; 1102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long nfrees; /* Stats when shrunk. */ 1112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long nrefills; /* Stats when grown. */ 1122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk gfp_t gfp_flags; 1132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char name[13]; /* "cached dma32" */ 1142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char dev_name[64]; /* Constructed from dev */ 1152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 1182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The accounting page keeping track of the allocated page along with 1192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * the DMA address. 1202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @page_list: The link to the 'page_list' in 'struct dma_pool'. 1212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @vaddr: The virtual address of the page 1222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @dma: The bus address of the page. If the page is not allocated 1232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * via the DMA API, it will be -1. 1242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 1252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstruct dma_page { 1262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head page_list; 1272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk void *vaddr; 1282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page *p; 1292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dma_addr_t dma; 1302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 1332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Limits for the pool. They are handled without locks because only place where 1342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * they may change is in sysfs store. They won't have immediate effect anyway 1352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * so forcing serialization to access them is pointless. 1362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 1372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstruct ttm_pool_opts { 1392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned alloc_size; 1402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned max_size; 1412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned small; 1422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 1452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Contains the list of all of the 'struct device' and their corresponding 1462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * DMA pools. Guarded by _mutex->lock. 1472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @pools: The link to 'struct ttm_pool_manager->pools' 1482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @dev: The 'struct device' associated with the 'pool' 1492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @pool: The 'struct dma_pool' associated with the 'dev' 1502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 1512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstruct device_pools { 1522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head pools; 1532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device *dev; 1542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool; 1552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 1582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * struct ttm_pool_manager - Holds memory pools for fast allocation 1592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 1602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @lock: Lock used when adding/removing from pools 1612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @pools: List of 'struct device' and 'struct dma_pool' tuples. 1622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @options: Limits for the pool. 1632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @npools: Total amount of pools in existence. 1642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @shrinker: The structure used by [un|]register_shrinker 1652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 1662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstruct ttm_pool_manager { 1672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct mutex lock; 1682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head pools; 1692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct ttm_pool_opts options; 1702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned npools; 1712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct shrinker mm_shrink; 1722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct kobject kobj; 1732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct ttm_pool_manager *_manager; 1762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct attribute ttm_page_pool_max = { 1782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .name = "pool_max_size", 1792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .mode = S_IRUGO | S_IWUSR 1802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct attribute ttm_page_pool_small = { 1822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .name = "pool_small_allocation", 1832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .mode = S_IRUGO | S_IWUSR 1842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct attribute ttm_page_pool_alloc_size = { 1862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .name = "pool_allocation_size", 1872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .mode = S_IRUGO | S_IWUSR 1882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct attribute *ttm_pool_attrs[] = { 1912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk &ttm_page_pool_max, 1922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk &ttm_page_pool_small, 1932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk &ttm_page_pool_alloc_size, 1942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk NULL 1952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 1962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 1972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_pool_kobj_release(struct kobject *kobj) 1982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 1992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct ttm_pool_manager *m = 2002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk container_of(kobj, struct ttm_pool_manager, kobj); 2012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(m); 2022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 2032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic ssize_t ttm_pool_store(struct kobject *kobj, struct attribute *attr, 2052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk const char *buffer, size_t size) 2062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 2072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct ttm_pool_manager *m = 2082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk container_of(kobj, struct ttm_pool_manager, kobj); 2092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int chars; 2102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned val; 2112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk chars = sscanf(buffer, "%u", &val); 2122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (chars == 0) 2132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return size; 2142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Convert kb to number of pages */ 2162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk val = val / (PAGE_SIZE >> 10); 2172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (attr == &ttm_page_pool_max) 2192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk m->options.max_size = val; 2202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else if (attr == &ttm_page_pool_small) 2212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk m->options.small = val; 2222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else if (attr == &ttm_page_pool_alloc_size) { 2232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (val > NUM_PAGES_TO_ALLOC*8) { 2242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk printk(KERN_ERR TTM_PFX 2252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "Setting allocation size to %lu " 2262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "is not allowed. Recommended size is " 2272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%lu\n", 2282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 7), 2292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); 2302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return size; 2312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } else if (val > NUM_PAGES_TO_ALLOC) { 2322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk printk(KERN_WARNING TTM_PFX 2332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "Setting allocation size to " 2342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "larger than %lu is not recommended.\n", 2352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk NUM_PAGES_TO_ALLOC*(PAGE_SIZE >> 10)); 2362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 2372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk m->options.alloc_size = val; 2382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 2392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return size; 2412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 2422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic ssize_t ttm_pool_show(struct kobject *kobj, struct attribute *attr, 2442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char *buffer) 2452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 2462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct ttm_pool_manager *m = 2472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk container_of(kobj, struct ttm_pool_manager, kobj); 2482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned val = 0; 2492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (attr == &ttm_page_pool_max) 2512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk val = m->options.max_size; 2522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else if (attr == &ttm_page_pool_small) 2532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk val = m->options.small; 2542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else if (attr == &ttm_page_pool_alloc_size) 2552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk val = m->options.alloc_size; 2562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk val = val * (PAGE_SIZE >> 10); 2582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return snprintf(buffer, PAGE_SIZE, "%u\n", val); 2602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 2612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic const struct sysfs_ops ttm_pool_sysfs_ops = { 2632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .show = &ttm_pool_show, 2642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .store = &ttm_pool_store, 2652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 2662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct kobj_type ttm_pool_kobj_type = { 2682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .release = &ttm_pool_kobj_release, 2692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .sysfs_ops = &ttm_pool_sysfs_ops, 2702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk .default_attrs = ttm_pool_attrs, 2712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk}; 2722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifndef CONFIG_X86 2742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int set_pages_array_wb(struct page **pages, int addrinarray) 2752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 2762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifdef TTM_HAS_AGP 2772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int i; 2782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < addrinarray; i++) 2802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unmap_page_from_agp(pages[i]); 2812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 2822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 2832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 2842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int set_pages_array_wc(struct page **pages, int addrinarray) 2862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 2872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifdef TTM_HAS_AGP 2882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int i; 2892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < addrinarray; i++) 2912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk map_page_into_agp(pages[i]); 2922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 2932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 2942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 2952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 2962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int set_pages_array_uc(struct page **pages, int addrinarray) 2972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 2982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifdef TTM_HAS_AGP 2992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int i; 3002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < addrinarray; i++) 3022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk map_page_into_agp(pages[i]); 3032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 3042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 3052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif /* for !CONFIG_X86 */ 3072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_set_pages_caching(struct dma_pool *pool, 3092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page **pages, unsigned cpages) 3102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int r = 0; 3122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Set page caching */ 3132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->type & IS_UC) { 3142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = set_pages_array_uc(pages, cpages); 3152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (r) 3162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX 3172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%s: Failed to set %d pages to uc!\n", 3182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, cpages); 3192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 3202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->type & IS_WC) { 3212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = set_pages_array_wc(pages, cpages); 3222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (r) 3232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX 3242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%s: Failed to set %d pages to wc!\n", 3252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, cpages); 3262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 3272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return r; 3282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page) 3312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dma_addr_t dma = d_page->dma; 3332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dma_free_coherent(pool->dev, pool->size, d_page->vaddr, dma); 3342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(d_page); 3362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page = NULL; 3372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct dma_page *__ttm_dma_alloc_page(struct dma_pool *pool) 3392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page; 3412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page = kmalloc(sizeof(struct dma_page), GFP_KERNEL); 3432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!d_page) 3442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return NULL; 3452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page->vaddr = dma_alloc_coherent(pool->dev, pool->size, 3472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk &d_page->dma, 3482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->gfp_flags); 3492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (d_page->vaddr) 3502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page->p = virt_to_page(d_page->vaddr); 3512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else { 3522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(d_page); 3532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page = NULL; 3542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 3552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return d_page; 3562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic enum pool_type ttm_to_type(int flags, enum ttm_caching_state cstate) 3582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type = IS_UNDEFINED; 3602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (flags & TTM_PAGE_FLAG_DMA32) 3622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type |= IS_DMA32; 3632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (cstate == tt_cached) 3642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type |= IS_CACHED; 3652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else if (cstate == tt_uncached) 3662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type |= IS_UC; 3672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else 3682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type |= IS_WC; 3692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return type; 3712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_pool_update_free_locked(struct dma_pool *pool, 3742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned freed_pages) 3752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free -= freed_pages; 3772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->nfrees += freed_pages; 3782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* set memory back to wb and free the pages. */ 3822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_pages_put(struct dma_pool *pool, struct list_head *d_pages, 3832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page *pages[], unsigned npages) 3842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 3852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page, *tmp; 3862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 38736d7c537c3082a492ff851fb0da40ae3d7c5565dKonrad Rzeszutek Wilk /* Don't set WB on WB page pool. */ 38836d7c537c3082a492ff851fb0da40ae3d7c5565dKonrad Rzeszutek Wilk if (npages && !(pool->type & IS_CACHED) && 38936d7c537c3082a492ff851fb0da40ae3d7c5565dKonrad Rzeszutek Wilk set_pages_array_wb(pages, npages)) 3902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX "%s: Failed to set %d pages to wb!\n", 3912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, npages); 3922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_safe(d_page, tmp, d_pages, page_list) { 3942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_del(&d_page->page_list); 3952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk __ttm_dma_free_page(pool, d_page); 3962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 3972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 3982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 3992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) 4002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 40136d7c537c3082a492ff851fb0da40ae3d7c5565dKonrad Rzeszutek Wilk /* Don't set WB on WB page pool. */ 40236d7c537c3082a492ff851fb0da40ae3d7c5565dKonrad Rzeszutek Wilk if (!(pool->type & IS_CACHED) && set_pages_array_wb(&d_page->p, 1)) 4032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX "%s: Failed to set %d pages to wb!\n", 4042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, 1); 4052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_del(&d_page->page_list); 4072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk __ttm_dma_free_page(pool, d_page); 4082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 4092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 4112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Free pages from pool. 4122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 4132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC 4142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * number of pages in one go. 4152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 4162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @pool: to free the pages from 4172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @nr_free: If set to true will free all pages in pool 4182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk **/ 4192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) 4202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 4212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long irq_flags; 4222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *dma_p, *tmp; 4232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page **pages_to_free; 4242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head d_pages; 4252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned freed_pages = 0, 4262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk npages_to_free = nr_free; 4272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (NUM_PAGES_TO_ALLOC < nr_free) 4292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk npages_to_free = NUM_PAGES_TO_ALLOC; 4302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#if 0 4312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (nr_free > 1) { 4322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_debug("%s: (%s:%d) Attempting to free %d (%d) pages\n", 4332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, pool->name, current->pid, 4342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk npages_to_free, nr_free); 4352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 4362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 4372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), 4382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk GFP_KERNEL); 4392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!pages_to_free) { 4412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX 4422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%s: Failed to allocate memory for pool free operation.\n", 4432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name); 4442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 4452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 4462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&d_pages); 4472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkrestart: 4482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_lock_irqsave(&pool->lock, irq_flags); 4492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* We picking the oldest ones off the list */ 4512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_safe_reverse(dma_p, tmp, &pool->free_list, 4522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk page_list) { 4532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (freed_pages >= npages_to_free) 4542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 4552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Move the dma_page from one list to another. */ 4572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_move(&dma_p->page_list, &d_pages); 4582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pages_to_free[freed_pages++] = dma_p->p; 4602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* We can only remove NUM_PAGES_TO_ALLOC at a time. */ 4612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (freed_pages >= NUM_PAGES_TO_ALLOC) { 4622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_pool_update_free_locked(pool, freed_pages); 4642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /** 4652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Because changing page caching is costly 4662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * we unlock the pool to prevent stalling. 4672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 4682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_unlock_irqrestore(&pool->lock, irq_flags); 4692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_pages_put(pool, &d_pages, pages_to_free, 4712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk freed_pages); 4722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&d_pages); 4742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (likely(nr_free != FREE_ALL_PAGES)) 4762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk nr_free -= freed_pages; 4772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (NUM_PAGES_TO_ALLOC >= nr_free) 4792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk npages_to_free = nr_free; 4802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else 4812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk npages_to_free = NUM_PAGES_TO_ALLOC; 4822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk freed_pages = 0; 4842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* free all so restart the processing */ 4862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (nr_free) 4872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto restart; 4882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Not allowed to fall through or break because 4902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * following context is inside spinlock while we are 4912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * outside here. 4922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 4932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto out; 4942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 4962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 4972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 4982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* remove range of pages from the pool */ 4992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (freed_pages) { 5002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_pool_update_free_locked(pool, freed_pages); 5012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk nr_free -= freed_pages; 5022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 5032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_unlock_irqrestore(&pool->lock, irq_flags); 5052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (freed_pages) 5072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_pages_put(pool, &d_pages, pages_to_free, freed_pages); 5082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkout: 5092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(pages_to_free); 5102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return nr_free; 5112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 5122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_free_pool(struct device *dev, enum pool_type type) 5142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 5152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *p; 5162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool; 5172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!dev) 5192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return; 5202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_lock(&_manager->lock); 5222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_reverse(p, &_manager->pools, pools) { 5232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (p->dev != dev) 5242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 5252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = p->pool; 5262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->type != type) 5272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 5282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_del(&p->pools); 5302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(p); 5312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager->npools--; 5322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 5332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 5342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_reverse(pool, &dev->dma_pools, pools) { 5352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->type != type) 5362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 5372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Takes a spinlock.. */ 5382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_page_pool_free(pool, FREE_ALL_PAGES); 5392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); 5402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* This code path is called after _all_ references to the 5412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * struct device has been dropped - so nobody should be 5422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * touching it. In case somebody is trying to _add_ we are 5432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * guarded by the mutex. */ 5442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_del(&pool->pools); 5452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(pool); 5462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 5472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 5482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_unlock(&_manager->lock); 5492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 5502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 5522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * On free-ing of the 'struct device' this deconstructor is run. 5532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Albeit the pool might have already been freed earlier. 5542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 5552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_pool_release(struct device *dev, void *res) 5562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 5572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool = *(struct dma_pool **)res; 5582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool) 5602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_free_pool(dev, pool->type); 5612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 5622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_pool_match(struct device *dev, void *res, void *match_data) 5642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 5652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return *(struct dma_pool **)res == match_data; 5662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 5672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags, 5692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type) 5702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 5712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char *n[] = {"wc", "uc", "cached", " dma32", "unknown",}; 5722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type t[] = {IS_WC, IS_UC, IS_CACHED, IS_DMA32, IS_UNDEFINED}; 5732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *sec_pool = NULL; 5742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool = NULL, **ptr; 5752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned i; 5762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int ret = -ENODEV; 5772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char *p; 5782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!dev) 5802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return NULL; 5812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ptr = devres_alloc(ttm_dma_pool_release, sizeof(*ptr), GFP_KERNEL); 5832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!ptr) 5842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return NULL; 5852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ret = -ENOMEM; 5872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = kmalloc_node(sizeof(struct dma_pool), GFP_KERNEL, 5892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dev_to_node(dev)); 5902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!pool) 5912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto err_mem; 5922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk sec_pool = kmalloc_node(sizeof(struct device_pools), GFP_KERNEL, 5942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dev_to_node(dev)); 5952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!sec_pool) 5962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto err_mem; 5972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 5982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&sec_pool->pools); 5992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk sec_pool->dev = dev; 6002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk sec_pool->pool = pool; 6012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&pool->free_list); 6032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&pool->inuse_list); 6042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&pool->pools); 6052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_lock_init(&pool->lock); 6062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev = dev; 6072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free = pool->npages_in_use = 0; 6082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->nfrees = 0; 6092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->gfp_flags = flags; 6102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->size = PAGE_SIZE; 6112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->type = type; 6122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->nrefills = 0; 6132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p = pool->name; 6142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < 5; i++) { 6152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (type & t[i]) { 6162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p += snprintf(p, sizeof(pool->name) - (p - pool->name), 6172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%s", n[i]); 6182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 6192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 6202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk *p = 0; 6212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* We copy the name for pr_ calls b/c when dma_pool_destroy is called 6222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * - the kobj->name has already been deallocated.*/ 6232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk snprintf(pool->dev_name, sizeof(pool->dev_name), "%s %s", 6242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dev_driver_string(dev), dev_name(dev)); 6252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_lock(&_manager->lock); 6262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* You can get the dma_pool from either the global: */ 6272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_add(&sec_pool->pools, &_manager->pools); 6282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager->npools++; 6292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* or from 'struct device': */ 6302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_add(&pool->pools, &dev->dma_pools); 6312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_unlock(&_manager->lock); 6322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk *ptr = pool; 6342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk devres_add(dev, ptr); 6352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return pool; 6372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkerr_mem: 6382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk devres_free(ptr); 6392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(sec_pool); 6402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(pool); 6412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return ERR_PTR(ret); 6422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 6432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic struct dma_pool *ttm_dma_find_pool(struct device *dev, 6452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type) 6462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 6472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool, *tmp, *found = NULL; 6482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (type == IS_UNDEFINED) 6502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return found; 6512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* NB: We iterate on the 'struct dev' which has no spinlock, but 6532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * it does have a kref which we have taken. The kref is taken during 6542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * graphic driver loading - in the drm_pci_init it calls either 6552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * pci_dev_get or pci_register_driver which both end up taking a kref 6562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * on 'struct device'. 6572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 6582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * On teardown, the graphic drivers end up quiescing the TTM (put_pages) 6592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * and calls the dev_res deconstructors: ttm_dma_pool_release. The nice 6602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * thing is at that point of time there are no pages associated with the 6612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * driver so this function will not be called. 6622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 6632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_safe(pool, tmp, &dev->dma_pools, pools) { 6642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->type != type) 6652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 6662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk found = pool; 6672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 6682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 6692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return found; 6702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 6712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 6732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Free pages the pages that failed to change the caching state. If there 6742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * are pages that have changed their caching state already put them to the 6752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * pool. 6762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 6772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_handle_caching_state_failure(struct dma_pool *pool, 6782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head *d_pages, 6792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page **failed_pages, 6802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned cpages) 6812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 6822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page, *tmp; 6832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page *p; 6842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned i = 0; 6852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 6862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p = failed_pages[0]; 6872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!p) 6882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return; 6892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Find the failed page. */ 6902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_safe(d_page, tmp, d_pages, page_list) { 6912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (d_page->p != p) 6922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 6932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* .. and then progress over the full list. */ 6942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_del(&d_page->page_list); 6952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk __ttm_dma_free_page(pool, d_page); 6962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (++i < cpages) 6972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p = failed_pages[i]; 6982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else 6992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 7002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 7032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 7052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Allocate 'count' pages, and put 'need' number of them on the 7062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * 'pages' and as well on the 'dma_address' starting at 'dma_offset' offset. 7072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The full list of pages should also be on 'd_pages'. 7082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * We return zero for success, and negative numbers as errors. 7092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 7102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, 7112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head *d_pages, 7122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned count) 7132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 7142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page **caching_array; 7152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *dma_p; 7162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct page *p; 7172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int r = 0; 7182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned i, cpages; 7192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned max_cpages = min(count, 7202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk (unsigned)(PAGE_SIZE/sizeof(struct page *))); 7212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* allocate array for page caching change */ 7232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); 7242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!caching_array) { 7262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX 7272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "%s: Unable to allocate table for new pages.", 7282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name); 7292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return -ENOMEM; 7302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (count > 1) { 7332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_debug("%s: (%s:%d) Getting %d pages\n", 7342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, pool->name, current->pid, 7352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk count); 7362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0, cpages = 0; i < count; ++i) { 7392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dma_p = __ttm_dma_alloc_page(pool); 7402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!dma_p) { 7412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX "%s: Unable to get page %u.\n", 7422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, i); 7432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* store already allocated pages in the pool after 7452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * setting the caching state */ 7462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (cpages) { 7472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = ttm_set_pages_caching(pool, caching_array, 7482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages); 7492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (r) 7502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_handle_caching_state_failure( 7512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool, d_pages, caching_array, 7522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages); 7532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = -ENOMEM; 7552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto out; 7562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p = dma_p->p; 7582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#ifdef CONFIG_HIGHMEM 7592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* gfp flags of highmem page should never be dma32 so we 7602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * we should be fine in such case 7612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 7622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!PageHighMem(p)) 7632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk#endif 7642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk { 7652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk caching_array[cpages++] = p; 7662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (cpages == max_cpages) { 7672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Note: Cannot hold the spinlock */ 7682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = ttm_set_pages_caching(pool, caching_array, 7692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages); 7702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (r) { 7712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_handle_caching_state_failure( 7722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool, d_pages, caching_array, 7732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages); 7742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto out; 7752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages = 0; 7772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_add(&dma_p->page_list, d_pages); 7802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (cpages) { 7832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = ttm_set_pages_caching(pool, caching_array, cpages); 7842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (r) 7852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_handle_caching_state_failure(pool, d_pages, 7862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk caching_array, cpages); 7872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 7882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkout: 7892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(caching_array); 7902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return r; 7912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 7922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 7932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 7942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @return count of pages still required to fulfill the request. 7958e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse */ 7962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_page_pool_fill_locked(struct dma_pool *pool, 7972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long *irq_flags) 7982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 7992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned count = _manager->options.small; 8002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int r = pool->npages_free; 8012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (count > pool->npages_free) { 8032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct list_head d_pages; 8042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&d_pages); 8062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_unlock_irqrestore(&pool->lock, *irq_flags); 8082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Returns how many more are neccessary to fulfill the 8102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * request. */ 8112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = ttm_dma_pool_alloc_new_pages(pool, &d_pages, count); 8122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_lock_irqsave(&pool->lock, *irq_flags); 8142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!r) { 8152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Add the fresh to the end.. */ 8162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_splice(&d_pages, &pool->free_list); 8172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ++pool->nrefills; 8182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free += count; 8192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = count; 8202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } else { 8212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page; 8222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned cpages = 0; 8232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_err(TTM_PFX "%s: Failed to fill %s pool (r:%d)!\n", 8252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name, pool->name, r); 8262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry(d_page, &d_pages, page_list) { 8282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk cpages++; 8292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_splice_tail(&d_pages, &pool->free_list); 8312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free += cpages; 8322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = cpages; 8332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return r; 8362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 8372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 8392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * @return count of pages still required to fulfill the request. 8402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * The populate list is actually a stack (not that is matters as TTM 8412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * allocates one page at a time. 8422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 8432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_pool_get_pages(struct dma_pool *pool, 8448e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse struct ttm_dma_tt *ttm_dma, 8452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned index) 8462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 8472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page; 8488e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse struct ttm_tt *ttm = &ttm_dma->ttm; 8492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long irq_flags; 8502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int count, r = -ENOMEM; 8512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_lock_irqsave(&pool->lock, irq_flags); 8532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk count = ttm_dma_page_pool_fill_locked(pool, &irq_flags); 8542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (count) { 8552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page = list_first_entry(&pool->free_list, struct dma_page, page_list); 8562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->pages[index] = d_page->p; 8578e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ttm_dma->dma_address[index] = d_page->dma; 8588e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse list_move_tail(&d_page->page_list, &ttm_dma->pages_list); 8592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk r = 0; 8602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_in_use += 1; 8612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free -= 1; 8622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_unlock_irqrestore(&pool->lock, irq_flags); 8642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return r; 8652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 8662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* 8682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * On success pages list will hold count number of correctly 8692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * cached pages. On failure will hold the negative return value (-ENOMEM, etc). 8702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 8718e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisseint ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) 8722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 8738e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse struct ttm_tt *ttm = &ttm_dma->ttm; 8742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; 8752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool; 8762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type; 8772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned i; 8782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk gfp_t gfp_flags; 8792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int ret; 8802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (ttm->state != tt_unpopulated) 8822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 8832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type = ttm_to_type(ttm->page_flags, ttm->caching_state); 8852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) 8862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk gfp_flags = GFP_USER | GFP_DMA32; 8872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk else 8882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk gfp_flags = GFP_HIGHUSER; 8892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) 8902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk gfp_flags |= __GFP_ZERO; 8912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 8922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = ttm_dma_find_pool(dev, type); 8932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!pool) { 8942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = ttm_dma_pool_init(dev, gfp_flags, type); 8952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (IS_ERR_OR_NULL(pool)) { 8962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return -ENOMEM; 8972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 8992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9008e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse INIT_LIST_HEAD(&ttm_dma->pages_list); 9012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < ttm->num_pages; ++i) { 9028e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); 9032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (ret != 0) { 9048e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ttm_dma_unpopulate(ttm_dma, dev); 9052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return -ENOMEM; 9062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], 9092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk false, false); 9102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (unlikely(ret != 0)) { 9118e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ttm_dma_unpopulate(ttm_dma, dev); 9122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return -ENOMEM; 9132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { 9172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ret = ttm_tt_swapin(ttm); 9182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (unlikely(ret != 0)) { 9198e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ttm_dma_unpopulate(ttm_dma, dev); 9202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return ret; 9212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->state = tt_unbound; 9252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 9262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 9272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek WilkEXPORT_SYMBOL_GPL(ttm_dma_populate); 9282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* Get good estimation how many pages are free in pools */ 9302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_pool_get_num_unused_pages(void) 9312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 9322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *p; 9332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned total = 0; 9342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_lock(&_manager->lock); 9362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry(p, &_manager->pools, pools) { 9372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (p) 9382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk total += p->pool->npages_free; 9392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_unlock(&_manager->lock); 9412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return total; 9422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 9432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/* Put all pages in pages list to correct pool to wait for reuse */ 9458e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glissevoid ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) 9462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 9478e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse struct ttm_tt *ttm = &ttm_dma->ttm; 9482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool; 9492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_page *d_page, *next; 9502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk enum pool_type type; 9512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk bool is_cached = false; 9522c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk unsigned count = 0, i, npages = 0; 9532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned long irq_flags; 9542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk type = ttm_to_type(ttm->page_flags, ttm->caching_state); 9562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = ttm_dma_find_pool(dev, type); 9572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!pool) { 9582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk WARN_ON(!pool); 9592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return; 9602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk is_cached = (ttm_dma_find_pool(pool->dev, 9622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_to_type(ttm->page_flags, tt_cached)) == pool); 9632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* make sure pages array match list and count number of pages */ 9658e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse list_for_each_entry(d_page, &ttm_dma->pages_list, page_list) { 9662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->pages[count] = d_page->p; 9672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk count++; 9682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_lock_irqsave(&pool->lock, irq_flags); 9712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_in_use -= count; 9722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (is_cached) { 9732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->nfrees += count; 9742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } else { 9752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free += count; 9768e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse list_splice(&ttm_dma->pages_list, &pool->free_list); 9772c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk npages = count; 9782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (pool->npages_free > _manager->options.max_size) { 9792c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk npages = pool->npages_free - _manager->options.max_size; 9802c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk /* free at least NUM_PAGES_TO_ALLOC number of pages 9812c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk * to reduce calls to set_memory_wb */ 9822c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk if (npages < NUM_PAGES_TO_ALLOC) 9832c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk npages = NUM_PAGES_TO_ALLOC; 9842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk spin_unlock_irqrestore(&pool->lock, irq_flags); 9872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 9882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (is_cached) { 9898e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list, page_list) { 9902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_mem_global_free_page(ttm->glob->mem_glob, 9912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk d_page->p); 9922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_page_put(pool, d_page); 9932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } else { 9952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < count; i++) { 9962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_mem_global_free_page(ttm->glob->mem_glob, 9972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->pages[i]); 9982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 9992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 10002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10018e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse INIT_LIST_HEAD(&ttm_dma->pages_list); 10022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk for (i = 0; i < ttm->num_pages; i++) { 10032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->pages[i] = NULL; 10048e7e70522d760c4ccd4cd370ebfa0ba69e006c6eJerome Glisse ttm_dma->dma_address[i] = 0; 10052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 10062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10072c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk /* shrink pool if necessary (only on !is_cached pools)*/ 10082c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk if (npages) 10092c05114d23c4fd2256eaf5645528c19fcefdb2c8Konrad Rzeszutek Wilk ttm_dma_page_pool_free(pool, npages); 10102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm->state = tt_unpopulated; 10112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 10122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek WilkEXPORT_SYMBOL_GPL(ttm_dma_unpopulate); 10132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk/** 10152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk * Callback for mm to request pool to reduce number of page held. 10162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk */ 10172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic int ttm_dma_pool_mm_shrink(struct shrinker *shrink, 10182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct shrink_control *sc) 10192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 10202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk static atomic_t start_pool = ATOMIC_INIT(0); 10212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned idx = 0; 10222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned pool_offset = atomic_add_return(1, &start_pool); 10232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned shrink_pages = sc->nr_to_scan; 10242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *p; 10252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (list_empty(&_manager->pools)) 10272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 10282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_lock(&_manager->lock); 10302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool_offset = pool_offset % _manager->npools; 10312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry(p, &_manager->pools, pools) { 10322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unsigned nr_free; 10332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!p && !p->dev) 10352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 10362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (shrink_pages == 0) 10372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk break; 10382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* Do it in round-robin fashion. */ 10392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (++idx < pool_offset) 10402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 10412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk nr_free = shrink_pages; 10422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free); 10432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n", 10442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk p->pool->dev_name, p->pool->name, current->pid, nr_free, 10452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk shrink_pages); 10462334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 10472334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_unlock(&_manager->lock); 10482334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* return estimated number of unused pages in pool */ 10492334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return ttm_dma_pool_get_num_unused_pages(); 10502334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 10512334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10522334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_pool_mm_shrink_init(struct ttm_pool_manager *manager) 10532334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 10542334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk manager->mm_shrink.shrink = &ttm_dma_pool_mm_shrink; 10552334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk manager->mm_shrink.seeks = 1; 10562334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk register_shrinker(&manager->mm_shrink); 10572334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 10582334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10592334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkstatic void ttm_dma_pool_mm_shrink_fini(struct ttm_pool_manager *manager) 10602334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 10612334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk unregister_shrinker(&manager->mm_shrink); 10622334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 10632334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10642334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkint ttm_dma_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) 10652334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 10662334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk int ret = -ENOMEM; 10672334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10682334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk WARN_ON(_manager); 10692334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10702334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk printk(KERN_INFO TTM_PFX "Initializing DMA pool allocator.\n"); 10712334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10722334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager = kzalloc(sizeof(*_manager), GFP_KERNEL); 10732334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!_manager) 10742334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto err_manager; 10752334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10762334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_init(&_manager->lock); 10772334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk INIT_LIST_HEAD(&_manager->pools); 10782334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10792334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager->options.max_size = max_pages; 10802334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager->options.small = SMALL_ALLOCATION; 10812334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager->options.alloc_size = NUM_PAGES_TO_ALLOC; 10822334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10832334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk /* This takes care of auto-freeing the _manager */ 10842334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ret = kobject_init_and_add(&_manager->kobj, &ttm_pool_kobj_type, 10852334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk &glob->kobj, "dma_pool"); 10862334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (unlikely(ret != 0)) { 10872334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kobject_put(&_manager->kobj); 10882334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk goto err; 10892334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 10902334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_pool_mm_shrink_init(_manager); 10912334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 10922334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkerr_manager: 10932334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kfree(_manager); 10942334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager = NULL; 10952334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkerr: 10962334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return ret; 10972334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 10982334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 10992334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkvoid ttm_dma_page_alloc_fini(void) 11002334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 11012334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *p, *t; 11022334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 11032334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk printk(KERN_INFO TTM_PFX "Finalizing DMA pool allocator.\n"); 11042334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_pool_mm_shrink_fini(_manager); 11052334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 11062334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry_safe_reverse(p, t, &_manager->pools, pools) { 11072334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk dev_dbg(p->dev, "(%s:%d) Freeing.\n", p->pool->name, 11082334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk current->pid); 11092334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk WARN_ON(devres_destroy(p->dev, ttm_dma_pool_release, 11102334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_pool_match, p->pool)); 11112334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk ttm_dma_free_pool(p->dev, p->pool->type); 11122334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 11132334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk kobject_put(&_manager->kobj); 11142334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk _manager = NULL; 11152334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 11162334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 11172334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilkint ttm_dma_page_alloc_debugfs(struct seq_file *m, void *data) 11182334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk{ 11192334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device_pools *p; 11202334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct dma_pool *pool = NULL; 11212334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk char *h[] = {"pool", "refills", "pages freed", "inuse", "available", 11222334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk "name", "virt", "busaddr"}; 11232334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk 11242334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!_manager) { 11252334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk seq_printf(m, "No pool allocator running.\n"); 11262334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 11272334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 11282334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk seq_printf(m, "%13s %12s %13s %8s %8s %8s\n", 11292334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk h[0], h[1], h[2], h[3], h[4], h[5]); 11302334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_lock(&_manager->lock); 11312334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk list_for_each_entry(p, &_manager->pools, pools) { 11322334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk struct device *dev = p->dev; 11332334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk if (!dev) 11342334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk continue; 11352334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool = p->pool; 11362334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk seq_printf(m, "%13s %12ld %13ld %8d %8d %8s\n", 11372334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->name, pool->nrefills, 11382334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->nfrees, pool->npages_in_use, 11392334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->npages_free, 11402334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk pool->dev_name); 11412334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk } 11422334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk mutex_unlock(&_manager->lock); 11432334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk return 0; 11442334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek Wilk} 11452334b75ffbef6b8932f09ec4418b65ddb764ae99Konrad Rzeszutek WilkEXPORT_SYMBOL_GPL(ttm_dma_page_alloc_debugfs); 1146