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]>
---
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