]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: atomisp: Fix alloc_pages_bulk() failed errors
authorHans de Goede <johannes.goede@oss.qualcomm.com>
Tue, 10 Mar 2026 12:18:26 +0000 (13:18 +0100)
committerSakari Ailus <sakari.ailus@linux.intel.com>
Wed, 20 May 2026 08:29:29 +0000 (11:29 +0300)
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 <johannes.goede@oss.qualcomm.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c

index 856561e951a5ebbf8bee51d46b61550cfa74f973..b91cbd0262d0e143d41bf6dc0027968a3a73d3f0 100644 (file)
@@ -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);