diff --git a/mm/cma.c b/mm/cma.c index 6f81a895d44f..f2346bc8cfb3 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -454,6 +454,8 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, struct page *page = NULL; int ret = -ENOMEM; int retry_after_sleep = 0; + int max_retries = 2; + int available_regions = 0; if (!cma || !cma->count) return NULL; @@ -480,8 +482,15 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, bitmap_maxno, start, bitmap_count, mask, offset); if (bitmap_no >= bitmap_maxno) { - if (retry_after_sleep < 2) { + if (retry_after_sleep < max_retries) { start = 0; + /* + * update max retries if available free regions + * are less. + */ + if (available_regions < 3) + max_retries = 5; + available_regions = 0; /* * Page may be momentarily pinned by some other * process which has been scheduled out, eg. @@ -499,6 +508,8 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, break; } } + + available_regions++; bitmap_set(cma->bitmap, bitmap_no, bitmap_count); /* * It's safe to drop the lock here. We've marked this region for