From c33a7cb6172e5cafbe2200f3e94cf5a4e2aa0ca2 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Thu, 20 May 2021 19:34:14 +0530 Subject: [PATCH] msm: kgsl: Fix num_pages calculation while shrinking pool Correct num_pages calculation to ensure shrinker is able to free pages from higher order pools and also make sure shrinker is not able to free pages from pool beyond reserved pages. Change-Id: Iedefe74caca7d04bf4b8e25915e8470929688424 Signed-off-by: Deepak Kumar --- drivers/gpu/msm/kgsl_pool.c | 43 +++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index 58f8d2caf2b7..94983f0a5705 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -150,6 +150,35 @@ static int kgsl_pool_size_total(void) return total; } +/* + * Returns a page from specified pool only if pool + * currently holds more number of pages than reserved + * pages. + */ +static struct page * +_kgsl_pool_get_nonreserved_page(struct kgsl_page_pool *pool) +{ + struct page *p = NULL; + + spin_lock(&pool->list_lock); + if (pool->page_count <= pool->reserved_pages) { + spin_unlock(&pool->list_lock); + return NULL; + } + + p = list_first_entry_or_null(&pool->page_list, struct page, lru); + if (p == NULL) { + spin_unlock(&pool->list_lock); + return NULL; + } + pool->page_count--; + list_del(&p->lru); + spin_unlock(&pool->list_lock); + mod_node_page_state(page_pgdat(p), NR_KERNEL_MISC_RECLAIMABLE, + -(1 << pool->pool_order)); + return p; +} + /* * This will shrink the specified pool by num_pages or by * (page_count - reserved_pages), whichever is smaller. @@ -160,19 +189,21 @@ _kgsl_pool_shrink(struct kgsl_page_pool *pool, { int j; unsigned int pcount = 0; + struct page *(*get_page)(struct kgsl_page_pool *) = + _kgsl_pool_get_nonreserved_page; if (pool == NULL || num_pages == 0) return pcount; - num_pages = num_pages >> pool->pool_order; + num_pages = (num_pages + (1 << pool->pool_order) - 1) >> + pool->pool_order; - /* This is to ensure that we don't free reserved pages */ - if (!exit) - num_pages = min(num_pages, (pool->page_count - - pool->reserved_pages)); + /* This is to ensure that we free reserved pages */ + if (exit) + get_page = _kgsl_pool_get_page; for (j = 0; j < num_pages; j++) { - struct page *page = _kgsl_pool_get_page(pool); + struct page *page = get_page(pool); if (!page) break;