From f965b1764b65fc0e9d6acba0f035a302cdc6df84 Mon Sep 17 00:00:00 2001 From: "ziyux.jiang" Date: Wed, 14 Dec 2011 00:12:07 +0800 Subject: [PATCH] [PORT FROM R2] atomisp: fix alloc pages block issue in drivers BZ: 17919 when there is not enough memory in kernel, allocation pages may fails and then sleep, so system will block in kernel and can not exit. To avoid this case, we modify allocation pages flag to GFP_NOWAIT(not will sleep when allocation) | __GFP_NOWARN on allocating private pages, and modify memory allocation mechanism. Change-Id: Ia60ee672920ecc6d5ef308903a8b51b241c10625 Orig-Change-Id: I7e8dd2f6fcacadb307eac925028d27934197c67c Signed-off-by: ziyux.jiang Reviewed-on: http://android.intel.com:8080/27152 Reviewed-by: Wang, Wen W Reviewed-by: Cohen, David A Reviewed-by: Hu, Gang A Reviewed-by: Koskinen, Ilkka Tested-by: Koski, Anttu Reviewed-by: buildbot Tested-by: buildbot Reviewed-on: http://android.intel.com:8080/29282 Reviewed-by: Lampila, KalleX Reviewed-by: Koski, Anttu --- drivers/media/video/atomisp/hmm/hmm_bo.c | 35 +++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/atomisp/hmm/hmm_bo.c b/drivers/media/video/atomisp/hmm/hmm_bo.c index e153b87..f4883a7 100644 --- a/drivers/media/video/atomisp/hmm/hmm_bo.c +++ b/drivers/media/video/atomisp/hmm/hmm_bo.c @@ -343,10 +343,12 @@ static int alloc_private_pages(struct hmm_buffer_object *bo, int from_highmem, unsigned int pgnr, order, blk_pgnr; struct page *pages; struct page_block *pgblk; - gfp_t gfp; + gfp_t gfp = GFP_NOWAIT | __GFP_NOWARN; int i, j; + int failure_number = 0; + bool reduce_order = false; + bool lack_mem = false; - gfp = GFP_KERNEL; if (from_highmem) gfp |= __GFP_HIGHMEM; @@ -361,7 +363,13 @@ static int alloc_private_pages(struct hmm_buffer_object *bo, int from_highmem, i = 0; while (pgnr) { order = nr_to_order_bottom(pgnr); - if (order > HMM_MAX_ORDER) + /* + * if be short of memory, we will set order to 0 + * everytime. + */ + if (lack_mem) + order = HMM_MIN_ORDER; + else if (order > HMM_MAX_ORDER) order = HMM_MAX_ORDER; retry: pages = alloc_pages(gfp, order); @@ -382,6 +390,16 @@ retry: "reduing page order to %d.\n", order, HMM_MIN_ORDER); order = HMM_MIN_ORDER; + failure_number++; + reduce_order = true; + /* + * if fail two times continuously, we think be short + * of memory now. + */ + if (failure_number == 2) { + lack_mem = true; + failure_number = 0; + } goto retry; } else { blk_pgnr = order_to_nr(order); @@ -416,6 +434,14 @@ retry: goto cleanup; } } + /* + * if order is not reduced this time, clear + * failure_number. + */ + if (reduce_order) + reduce_order = false; + else + failure_number = 0; } } @@ -423,7 +449,6 @@ retry: out_of_mem: __free_pages(pages, order); cleanup: - ret = -ENOMEM; while (!list_empty(&bo->pgblocks)) { pgblk = list_first_entry(&bo->pgblocks, struct page_block, list); @@ -440,7 +465,7 @@ cleanup: } kfree(bo->pages); - return ret; + return -ENOMEM; } static void free_private_pages(struct hmm_buffer_object *bo) -- 2.7.4