[PORT FROM R2] atomisp: fix alloc pages block issue in drivers
authorziyux.jiang <ziyux.jiang@intel.com>
Tue, 13 Dec 2011 16:12:07 +0000 (00:12 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 21 Dec 2011 08:14:04 +0000 (00:14 -0800)
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 <ziyux.jiang@intel.com>
Reviewed-on: http://android.intel.com:8080/27152
Reviewed-by: Wang, Wen W <wen.w.wang@intel.com>
Reviewed-by: Cohen, David A <david.a.cohen@intel.com>
Reviewed-by: Hu, Gang A <gang.a.hu@intel.com>
Reviewed-by: Koskinen, Ilkka <ilkka.koskinen@intel.com>
Tested-by: Koski, Anttu <anttu.koski@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
Reviewed-on: http://android.intel.com:8080/29282
Reviewed-by: Lampila, KalleX <kallex.lampila@intel.com>
Reviewed-by: Koski, Anttu <anttu.koski@intel.com>
drivers/media/video/atomisp/hmm/hmm_bo.c

index e153b87..f4883a7 100644 (file)
@@ -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)