On Tue Mar 10 13:18:26 2026 +0100, Hans de Goede wrote:
> 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 <[email protected]>
> Signed-off-by: Sakari Ailus <[email protected]>

Patch committed.

Thanks,
Sakari Ailus

 drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

---

diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c 
b/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c
index 856561e951a5..b91cbd0262d0 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);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to