summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/ttm/ttm_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_pool.c')
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c157
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;