From: Hans de Goede Date: Tue, 10 Mar 2026 12:18:26 +0000 (+0100) Subject: media: atomisp: Fix alloc_pages_bulk() failed errors X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a41dd4aabc852692e9bc480e4a789683acd4777;p=thirdparty%2Fkernel%2Flinux.git media: atomisp: Fix alloc_pages_bulk() failed errors Systems with the atomisp ISP do not have a lot of memory for modern standards, so these are often under memory pressure and alloc_pages_bulk() does not try very hard to free pages before returning an amount of pages which is less then requested. This leads to streaming from the camera often failing with a "alloc_pages_bulk() failed" error. vmalloc() also uses alloc_pages_bulk(), but falls back to allocating one page at a time when that fails. Do the same in alloc_private_pages() to avoid these errors. While at it also drop the weird custom GFP flags and just use GFP_KERNEL and drop the dev_err() as alloc_pages() already complaints loudly if it fails itself. Closes: https://github.com/jfwells/linux-asus-t100ta/issues/4 Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus --- diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c b/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c index 856561e951a5e..b91cbd0262d0e 100644 --- a/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +++ b/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c @@ -620,14 +620,23 @@ static void free_private_bo_pages(struct hmm_buffer_object *bo) /*Allocate pages which will be used only by ISP*/ static int alloc_private_pages(struct hmm_buffer_object *bo) { - const gfp_t gfp = __GFP_NOWARN | __GFP_RECLAIM | __GFP_FS; + unsigned int nr_allocated = 0; + struct page *page; int ret; - ret = alloc_pages_bulk(gfp, bo->pgnr, bo->pages); - if (ret != bo->pgnr) { - free_pages_bulk_array(ret, bo->pages); - dev_err(atomisp_dev, "alloc_pages_bulk() failed\n"); - return -ENOMEM; + nr_allocated = alloc_pages_bulk(GFP_KERNEL, bo->pgnr, bo->pages); + /* + * alloc_pages_bulk() does not try very hard to get pages under memory + * pressure. If necessary fall back to alloc_page(). + */ + while (nr_allocated < bo->pgnr) { + page = alloc_pages(GFP_KERNEL, 0); + if (!page) { + free_pages_bulk_array(nr_allocated, bo->pages); + return -ENOMEM; + } + bo->pages[nr_allocated] = page; + nr_allocated++; } ret = set_pages_array_uc(bo->pages, bo->pgnr);