diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_pool.c')
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_pool.c | 157 | 
1 files changed, 101 insertions, 56 deletions
| diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 4eb6efb8b8c0..cb38b1a17b09 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -34,6 +34,7 @@  #include <linux/module.h>  #include <linux/dma-mapping.h>  #include <linux/highmem.h> +#include <linux/sched/mm.h>  #ifdef CONFIG_X86  #include <asm/set_memory.h> @@ -43,6 +44,8 @@  #include <drm/ttm/ttm_bo_driver.h>  #include <drm/ttm/ttm_tt.h> +#include "ttm_module.h" +  /**   * struct ttm_pool_dma - Helper object for coherent DMA mappings   * @@ -412,16 +415,10 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,  			caching = pages + (1 << order);  		} -		r = ttm_mem_global_alloc_page(&ttm_mem_glob, p, -					      (1 << order) * PAGE_SIZE, -					      ctx); -		if (r) -			goto error_free_page; -  		if (dma_addr) {  			r = ttm_pool_map(pool, order, p, &dma_addr);  			if (r) -				goto error_global_free; +				goto error_free_page;  		}  		num_pages -= 1 << order; @@ -435,9 +432,6 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,  	return 0; -error_global_free: -	ttm_mem_global_free_page(&ttm_mem_glob, p, (1 << order) * PAGE_SIZE); -  error_free_page:  	ttm_pool_free_page(pool, tt->caching, order, p); @@ -472,8 +466,6 @@ void ttm_pool_free(struct ttm_pool *pool, struct ttm_tt *tt)  		order = ttm_pool_page_order(pool, p);  		num_pages = 1ULL << order; -		ttm_mem_global_free_page(&ttm_mem_glob, p, -					 num_pages * PAGE_SIZE);  		if (tt->dma_address)  			ttm_pool_unmap(pool, tt->dma_address[i], num_pages); @@ -513,10 +505,12 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev,  	pool->use_dma_alloc = use_dma_alloc;  	pool->use_dma32 = use_dma32; -	for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) -		for (j = 0; j < MAX_ORDER; ++j) -			ttm_pool_type_init(&pool->caching[i].orders[j], -					   pool, i, j); +	if (use_dma_alloc) { +		for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) +			for (j = 0; j < MAX_ORDER; ++j) +				ttm_pool_type_init(&pool->caching[i].orders[j], +						   pool, i, j); +	}  }  /** @@ -531,9 +525,33 @@ void ttm_pool_fini(struct ttm_pool *pool)  {  	unsigned int i, j; -	for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) -		for (j = 0; j < MAX_ORDER; ++j) -			ttm_pool_type_fini(&pool->caching[i].orders[j]); +	if (pool->use_dma_alloc) { +		for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) +			for (j = 0; j < MAX_ORDER; ++j) +				ttm_pool_type_fini(&pool->caching[i].orders[j]); +	} +} + +/* As long as pages are available make sure to release at least one */ +static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink, +					    struct shrink_control *sc) +{ +	unsigned long num_freed = 0; + +	do +		num_freed += ttm_pool_shrink(); +	while (!num_freed && atomic_long_read(&allocated_pages)); + +	return num_freed; +} + +/* Return the number of pages available or SHRINK_EMPTY if we have none */ +static unsigned long ttm_pool_shrinker_count(struct shrinker *shrink, +					     struct shrink_control *sc) +{ +	unsigned long num_pages = atomic_long_read(&allocated_pages); + +	return num_pages ? num_pages : SHRINK_EMPTY;  }  #ifdef CONFIG_DEBUG_FS @@ -552,6 +570,17 @@ static unsigned int ttm_pool_type_count(struct ttm_pool_type *pt)  	return count;  } +/* Print a nice header for the order */ +static void ttm_pool_debugfs_header(struct seq_file *m) +{ +	unsigned int i; + +	seq_puts(m, "\t "); +	for (i = 0; i < MAX_ORDER; ++i) +		seq_printf(m, " ---%2u---", i); +	seq_puts(m, "\n"); +} +  /* Dump information about the different pool types */  static void ttm_pool_debugfs_orders(struct ttm_pool_type *pt,  				    struct seq_file *m) @@ -563,6 +592,35 @@ static void ttm_pool_debugfs_orders(struct ttm_pool_type *pt,  	seq_puts(m, "\n");  } +/* Dump the total amount of allocated pages */ +static void ttm_pool_debugfs_footer(struct seq_file *m) +{ +	seq_printf(m, "\ntotal\t: %8lu of %8lu\n", +		   atomic_long_read(&allocated_pages), page_pool_size); +} + +/* Dump the information for the global pools */ +static int ttm_pool_debugfs_globals_show(struct seq_file *m, void *data) +{ +	ttm_pool_debugfs_header(m); + +	mutex_lock(&shrinker_lock); +	seq_puts(m, "wc\t:"); +	ttm_pool_debugfs_orders(global_write_combined, m); +	seq_puts(m, "uc\t:"); +	ttm_pool_debugfs_orders(global_uncached, m); +	seq_puts(m, "wc 32\t:"); +	ttm_pool_debugfs_orders(global_dma32_write_combined, m); +	seq_puts(m, "uc 32\t:"); +	ttm_pool_debugfs_orders(global_dma32_uncached, m); +	mutex_unlock(&shrinker_lock); + +	ttm_pool_debugfs_footer(m); + +	return 0; +} +DEFINE_SHOW_ATTRIBUTE(ttm_pool_debugfs_globals); +  /**   * ttm_pool_debugfs - Debugfs dump function for a pool   * @@ -575,23 +633,14 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)  {  	unsigned int i; -	mutex_lock(&shrinker_lock); - -	seq_puts(m, "\t "); -	for (i = 0; i < MAX_ORDER; ++i) -		seq_printf(m, " ---%2u---", i); -	seq_puts(m, "\n"); - -	seq_puts(m, "wc\t:"); -	ttm_pool_debugfs_orders(global_write_combined, m); -	seq_puts(m, "uc\t:"); -	ttm_pool_debugfs_orders(global_uncached, m); +	if (!pool->use_dma_alloc) { +		seq_puts(m, "unused\n"); +		return 0; +	} -	seq_puts(m, "wc 32\t:"); -	ttm_pool_debugfs_orders(global_dma32_write_combined, m); -	seq_puts(m, "uc 32\t:"); -	ttm_pool_debugfs_orders(global_dma32_uncached, m); +	ttm_pool_debugfs_header(m); +	mutex_lock(&shrinker_lock);  	for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {  		seq_puts(m, "DMA ");  		switch (i) { @@ -607,39 +656,28 @@ int ttm_pool_debugfs(struct ttm_pool *pool, struct seq_file *m)  		}  		ttm_pool_debugfs_orders(pool->caching[i].orders, m);  	} - -	seq_printf(m, "\ntotal\t: %8lu of %8lu\n", -		   atomic_long_read(&allocated_pages), page_pool_size); -  	mutex_unlock(&shrinker_lock); +	ttm_pool_debugfs_footer(m);  	return 0;  }  EXPORT_SYMBOL(ttm_pool_debugfs); -#endif - -/* As long as pages are available make sure to release at least one */ -static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink, -					    struct shrink_control *sc) +/* Test the shrinker functions and dump the result */ +static int ttm_pool_debugfs_shrink_show(struct seq_file *m, void *data)  { -	unsigned long num_freed = 0; +	struct shrink_control sc = { .gfp_mask = GFP_NOFS }; -	do -		num_freed += ttm_pool_shrink(); -	while (!num_freed && atomic_long_read(&allocated_pages)); +	fs_reclaim_acquire(GFP_KERNEL); +	seq_printf(m, "%lu/%lu\n", ttm_pool_shrinker_count(&mm_shrinker, &sc), +		   ttm_pool_shrinker_scan(&mm_shrinker, &sc)); +	fs_reclaim_release(GFP_KERNEL); -	return num_freed; +	return 0;  } +DEFINE_SHOW_ATTRIBUTE(ttm_pool_debugfs_shrink); -/* Return the number of pages available or SHRINK_EMPTY if we have none */ -static unsigned long ttm_pool_shrinker_count(struct shrinker *shrink, -					     struct shrink_control *sc) -{ -	unsigned long num_pages = atomic_long_read(&allocated_pages); - -	return num_pages ? num_pages : SHRINK_EMPTY; -} +#endif  /**   * ttm_pool_mgr_init - Initialize globals @@ -669,6 +707,13 @@ int ttm_pool_mgr_init(unsigned long num_pages)  				   ttm_uncached, i);  	} +#ifdef CONFIG_DEBUG_FS +	debugfs_create_file("page_pool", 0444, ttm_debugfs_root, NULL, +			    &ttm_pool_debugfs_globals_fops); +	debugfs_create_file("page_pool_shrink", 0400, ttm_debugfs_root, NULL, +			    &ttm_pool_debugfs_shrink_fops); +#endif +  	mm_shrinker.count_objects = ttm_pool_shrinker_count;  	mm_shrinker.scan_objects = ttm_pool_shrinker_scan;  	mm_shrinker.seeks = 1; | 
