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