Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c33a7cb6 authored by Deepak Kumar's avatar Deepak Kumar
Browse files

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: default avatarDeepak Kumar <dkumar@codeaurora.org>
parent 610e9488
Loading
Loading
Loading
Loading
+37 −6
Original line number Diff line number Diff line
@@ -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;