[PATCH] drm/ttm: switch back to static allocation limits for now
Daniel Vetter
daniel at ffwll.ch
Wed Mar 24 19:29:22 UTC 2021
On Wed, Mar 24, 2021 at 02:48:45PM +0100, Christian König wrote:
> The shrinker based approach still has some flaws. Especially that we need
> temporary pages to free up the pages allocated to the driver is problematic
> in a shrinker.
>
> Signed-off-by: Christian König <christian.koenig at amd.com>
> ---
> drivers/gpu/drm/ttm/ttm_device.c | 14 ++--
> drivers/gpu/drm/ttm/ttm_tt.c | 112 ++++++++++++-------------------
> include/drm/ttm/ttm_tt.h | 3 +-
> 3 files changed, 53 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c
> index 95e1b7b1f2e6..388da2a7f0bb 100644
> --- a/drivers/gpu/drm/ttm/ttm_device.c
> +++ b/drivers/gpu/drm/ttm/ttm_device.c
> @@ -53,7 +53,6 @@ static void ttm_global_release(void)
> goto out;
>
> ttm_pool_mgr_fini();
> - ttm_tt_mgr_fini();
>
> __free_page(glob->dummy_read_page);
> memset(glob, 0, sizeof(*glob));
> @@ -64,7 +63,7 @@ static void ttm_global_release(void)
> static int ttm_global_init(void)
> {
> struct ttm_global *glob = &ttm_glob;
> - unsigned long num_pages;
> + unsigned long num_pages, num_dma32;
> struct sysinfo si;
> int ret = 0;
> unsigned i;
> @@ -79,8 +78,15 @@ static int ttm_global_init(void)
> * system memory.
> */
> num_pages = ((u64)si.totalram * si.mem_unit) >> PAGE_SHIFT;
> - ttm_pool_mgr_init(num_pages * 50 / 100);
> - ttm_tt_mgr_init();
> + num_pages /= 2;
> +
> + /* But for DMA32 we limit ourself to only use 2GiB maximum. */
> + num_dma32 = (u64)(si.totalram - si.totalhigh) * si.mem_unit
> + >> PAGE_SHIFT;
> + num_dma32 = min(num_dma32, 2UL << (30 - PAGE_SHIFT));
> +
> + ttm_pool_mgr_init(num_pages);
> + ttm_tt_mgr_init(num_pages, num_dma32);
>
> spin_lock_init(&glob->lru_lock);
> glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32);
> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
> index 2f0833c98d2c..5d8820725b75 100644
> --- a/drivers/gpu/drm/ttm/ttm_tt.c
> +++ b/drivers/gpu/drm/ttm/ttm_tt.c
> @@ -40,8 +40,18 @@
>
> #include "ttm_module.h"
>
> -static struct shrinker mm_shrinker;
> -static atomic_long_t swapable_pages;
> +static unsigned long ttm_pages_limit;
> +
> +MODULE_PARM_DESC(pages_limit, "Limit for the allocated pages");
> +module_param_named(pages_limit, ttm_pages_limit, ulong, 0644);
> +
> +static unsigned long ttm_dma32_pages_limit;
> +
> +MODULE_PARM_DESC(dma32_pages_limit, "Limit for the allocated DMA32 pages");
> +module_param_named(dma32_pages_limit, ttm_dma32_pages_limit, ulong, 0644);
> +
> +static atomic_long_t ttm_pages_allocated;
> +static atomic_long_t ttm_dma32_pages_allocated;
Making this configurable looks an awful lot like "job done, move on". Just
the revert to hardcoded 50% (or I guess just revert the shrinker patch at
that point) for -fixes is imo better.
Then I guess retry again for 5.14 or so.
-Daniel
>
> /*
> * Allocates a ttm structure for the given BO.
> @@ -294,8 +304,6 @@ static void ttm_tt_add_mapping(struct ttm_device *bdev, struct ttm_tt *ttm)
>
> for (i = 0; i < ttm->num_pages; ++i)
> ttm->pages[i]->mapping = bdev->dev_mapping;
> -
> - atomic_long_add(ttm->num_pages, &swapable_pages);
> }
>
> int ttm_tt_populate(struct ttm_device *bdev,
> @@ -309,12 +317,25 @@ int ttm_tt_populate(struct ttm_device *bdev,
> if (ttm_tt_is_populated(ttm))
> return 0;
>
> + atomic_long_add(ttm->num_pages, &ttm_pages_allocated);
> + if (bdev->pool.use_dma32)
> + atomic_long_add(ttm->num_pages, &ttm_dma32_pages_allocated);
> +
> + while (atomic_long_read(&ttm_pages_allocated) > ttm_pages_limit ||
> + atomic_long_read(&ttm_dma32_pages_allocated) >
> + ttm_dma32_pages_limit) {
> +
> + ret = ttm_bo_swapout(ctx, GFP_KERNEL);
> + if (ret)
> + goto error;
> + }
> +
> if (bdev->funcs->ttm_tt_populate)
> ret = bdev->funcs->ttm_tt_populate(bdev, ttm, ctx);
> else
> ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
> if (ret)
> - return ret;
> + goto error;
>
> ttm_tt_add_mapping(bdev, ttm);
> ttm->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED;
> @@ -327,6 +348,12 @@ int ttm_tt_populate(struct ttm_device *bdev,
> }
>
> return 0;
> +
> +error:
> + atomic_long_sub(ttm->num_pages, &ttm_pages_allocated);
> + if (bdev->pool.use_dma32)
> + atomic_long_sub(ttm->num_pages, &ttm_dma32_pages_allocated);
> + return ret;
> }
> EXPORT_SYMBOL(ttm_tt_populate);
>
> @@ -342,12 +369,9 @@ static void ttm_tt_clear_mapping(struct ttm_tt *ttm)
> (*page)->mapping = NULL;
> (*page++)->index = 0;
> }
> -
> - atomic_long_sub(ttm->num_pages, &swapable_pages);
> }
>
> -void ttm_tt_unpopulate(struct ttm_device *bdev,
> - struct ttm_tt *ttm)
> +void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm)
> {
> if (!ttm_tt_is_populated(ttm))
> return;
> @@ -357,76 +381,24 @@ void ttm_tt_unpopulate(struct ttm_device *bdev,
> bdev->funcs->ttm_tt_unpopulate(bdev, ttm);
> else
> ttm_pool_free(&bdev->pool, ttm);
> - ttm->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED;
> -}
> -
> -/* As long as pages are available make sure to release at least one */
> -static unsigned long ttm_tt_shrinker_scan(struct shrinker *shrink,
> - struct shrink_control *sc)
> -{
> - struct ttm_operation_ctx ctx = {
> - .no_wait_gpu = false
> - };
> - int ret;
> -
> - ret = ttm_bo_swapout(&ctx, GFP_NOFS);
> - return ret < 0 ? SHRINK_EMPTY : ret;
> -}
> -
> -/* Return the number of pages available or SHRINK_EMPTY if we have none */
> -static unsigned long ttm_tt_shrinker_count(struct shrinker *shrink,
> - struct shrink_control *sc)
> -{
> - unsigned long num_pages;
> -
> - num_pages = atomic_long_read(&swapable_pages);
> - return num_pages ? num_pages : SHRINK_EMPTY;
> -}
>
> -#ifdef CONFIG_DEBUG_FS
> + atomic_long_sub(ttm->num_pages, &ttm_pages_allocated);
> + if (bdev->pool.use_dma32)
> + atomic_long_sub(ttm->num_pages, &ttm_dma32_pages_allocated);
>
> -/* Test the shrinker functions and dump the result */
> -static int ttm_tt_debugfs_shrink_show(struct seq_file *m, void *data)
> -{
> - struct shrink_control sc = { .gfp_mask = GFP_KERNEL };
> -
> - fs_reclaim_acquire(GFP_KERNEL);
> - seq_printf(m, "%lu/%lu\n", ttm_tt_shrinker_count(&mm_shrinker, &sc),
> - ttm_tt_shrinker_scan(&mm_shrinker, &sc));
> - fs_reclaim_release(GFP_KERNEL);
> -
> - return 0;
> + ttm->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED;
> }
> -DEFINE_SHOW_ATTRIBUTE(ttm_tt_debugfs_shrink);
> -
> -#endif
> -
> -
>
> /**
> * ttm_tt_mgr_init - register with the MM shrinker
> *
> * Register with the MM shrinker for swapping out BOs.
> */
> -int ttm_tt_mgr_init(void)
> +void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages)
> {
> -#ifdef CONFIG_DEBUG_FS
> - debugfs_create_file("tt_shrink", 0400, ttm_debugfs_root, NULL,
> - &ttm_tt_debugfs_shrink_fops);
> -#endif
> -
> - mm_shrinker.count_objects = ttm_tt_shrinker_count;
> - mm_shrinker.scan_objects = ttm_tt_shrinker_scan;
> - mm_shrinker.seeks = 1;
> - return register_shrinker(&mm_shrinker);
> -}
> + if (!ttm_pages_limit)
> + ttm_pages_limit = num_pages;
>
> -/**
> - * ttm_tt_mgr_fini - unregister our MM shrinker
> - *
> - * Unregisters the MM shrinker.
> - */
> -void ttm_tt_mgr_fini(void)
> -{
> - unregister_shrinker(&mm_shrinker);
> + if (!ttm_dma32_pages_limit)
> + ttm_dma32_pages_limit = num_dma32_pages;
> }
> diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
> index 069f8130241a..134d09ef7766 100644
> --- a/include/drm/ttm/ttm_tt.h
> +++ b/include/drm/ttm/ttm_tt.h
> @@ -157,8 +157,7 @@ int ttm_tt_populate(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_oper
> */
> void ttm_tt_unpopulate(struct ttm_device *bdev, struct ttm_tt *ttm);
>
> -int ttm_tt_mgr_init(void);
> -void ttm_tt_mgr_fini(void);
> +void ttm_tt_mgr_init(unsigned long num_pages, unsigned long num_dma32_pages);
>
> #if IS_ENABLED(CONFIG_AGP)
> #include <linux/agp_backend.h>
> --
> 2.25.1
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list