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