On Wed, Sep 30, 2026 at 04:06:51PM -0300, Maíra Canal wrote:
> The BO cache size list has one entry per BO page count, so its size
> scales with the largest BO ever freed. A 64 MiB BO already needs at
> least an order-6 allocation, which fails under fragmentation and
> triggers a warn_alloc() splat on BO close:
> 
>   page allocation failure: order:7, mode:0x40cc0(GFP_KERNEL|__GFP_COMP)
>   Call trace:
>    ...
>    warn_alloc+0x118/0x190
>    __alloc_pages_slowpath+0x4a8/0x520
>    ...
>    __kmalloc_noprof+0x3ac/0x5d8
>    vc4_free_object+0x128/0x370 [vc4]
>    drm_gem_object_handle_put_unlocked+0xb8/0x158 [drm]
>    drm_gem_object_release_handle+0x74/0xe8 [drm]
>    drm_gem_handle_delete+0x6c/0xa8 [drm]
>    drm_gem_close_ioctl+0x34/0x50 [drm]
> 
> The list doesn't need physically contiguous memory. Use kvmalloc_objs()
> so large lists can fall back to vmalloc(), avoiding the allocation
> failure.
> 
> Fixes: c826a6e10644 ("drm/vc4: Add a BO cache.")
> Signed-off-by: Maíra Canal <[email protected]>


Reviewed-by: Thadeu Lima de Souza Cascardo <[email protected]>

> ---
>  drivers/gpu/drm/vc4/vc4_bo.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
> index ea1be891ac78..7b8b3364000f 100644
> --- a/drivers/gpu/drm/vc4/vc4_bo.c
> +++ b/drivers/gpu/drm/vc4/vc4_bo.c
> @@ -204,7 +204,7 @@ static struct list_head 
> *vc4_get_cache_list_for_size(struct drm_device *dev,
>               struct list_head *new_list;
>               uint32_t i;
>  
> -             new_list = kmalloc_objs(struct list_head, new_size);
> +             new_list = kvmalloc_objs(struct list_head, new_size);
>               if (!new_list)
>                       return NULL;
>  
> @@ -224,7 +224,7 @@ static struct list_head 
> *vc4_get_cache_list_for_size(struct drm_device *dev,
>               for (i = vc4->bo_cache.size_list_size; i < new_size; i++)
>                       INIT_LIST_HEAD(&new_list[i]);
>  
> -             kfree(vc4->bo_cache.size_list);
> +             kvfree(vc4->bo_cache.size_list);
>               vc4->bo_cache.size_list = new_list;
>               vc4->bo_cache.size_list_size = new_size;
>       }
> @@ -1052,7 +1052,7 @@ static void vc4_bo_cache_destroy(struct drm_device 
> *dev, void *unused)
>       cancel_work_sync(&vc4->bo_cache.time_work);
>  
>       vc4_bo_cache_purge(dev);
> -     kfree(vc4->bo_cache.size_list);
> +     kvfree(vc4->bo_cache.size_list);
>  
>       for (i = 0; i < vc4->num_labels; i++) {
>               if (vc4->bo_labels[i].num_allocated) {
> -- 
> 2.55.0
> 

Reply via email to