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]