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