diff options
| -rw-r--r-- | drivers/gpu/msm/kgsl_pool.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index bd1e432d8c7d..bb92b8b79d93 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -299,6 +299,7 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, struct page *p = NULL; int order = get_order(*page_size); int pool_idx; + size_t size = 0; if ((pages == NULL) || pages_len < (*page_size >> PAGE_SHIFT)) return -EINVAL; @@ -311,11 +312,8 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, if (page == NULL) { /* Retry with lower order pages */ if (order > 0) { - size_t size = PAGE_SIZE << --order; - *page_size = kgsl_get_page_size(size, - ilog2(size)); - *align = ilog2(*page_size); - return -EAGAIN; + size = PAGE_SIZE << --order; + goto eagain; } else return -ENOMEM; @@ -325,8 +323,25 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, } pool = _kgsl_get_pool_from_order(order); - if (pool == NULL) - return -EINVAL; + if (pool == NULL) { + /* Retry with lower order pages */ + if (order > 0) { + size = PAGE_SIZE << --order; + goto eagain; + } else { + /* + * Fall back to direct allocation in case + * pool with zero order is not present + */ + gfp_t gfp_mask = kgsl_gfp_mask(order); + + page = alloc_pages(gfp_mask, order); + if (page == NULL) + return -ENOMEM; + _kgsl_pool_zero_page(page, order); + goto done; + } + } pool_idx = kgsl_pool_idx_lookup(order); page = _kgsl_pool_get_page(pool); @@ -337,10 +352,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, /* Only allocate non-reserved memory for certain pools */ if (!pool->allocation_allowed && pool_idx > 0) { - *page_size = PAGE_SIZE << + size = PAGE_SIZE << kgsl_pools[pool_idx-1].pool_order; - *align = ilog2(*page_size); - return -EAGAIN; + goto eagain; } page = alloc_pages(gfp_mask, order); @@ -348,10 +362,9 @@ int kgsl_pool_alloc_page(int *page_size, struct page **pages, if (!page) { if (pool_idx > 0) { /* Retry with lower order pages */ - *page_size = PAGE_SIZE << + size = PAGE_SIZE << kgsl_pools[pool_idx-1].pool_order; - *align = ilog2(*page_size); - return -EAGAIN; + goto eagain; } else return -ENOMEM; } @@ -367,6 +380,12 @@ done: } return pcount; + +eagain: + *page_size = kgsl_get_page_size(size, + ilog2(size)); + *align = ilog2(*page_size); + return -EAGAIN; } void kgsl_pool_free_page(struct page *page) |
