summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-05-15 12:33:00 -0700
committerEric Anholt <eric@anholt.net>2015-06-04 14:15:35 -0700
commit006708c9879d3951edcec2a74021afc41ac65084 (patch)
tree10b9dfd950cbb06cfc8955d8b9fb9e83a36d2dd3
parent660b630f8de24d4c73f5f2982b65ed2537735c1d (diff)
downloadlinux-006708c9879d3951edcec2a74021afc41ac65084.tar.gz
drm/vc4: Purge BO cache when we've failed an allocation, and retry.
This gets us a bit farther when running low on CMA memory. Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index c39413f6bcbc..aa063eb4889f 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -63,6 +63,20 @@ vc4_get_cache_list_for_size(struct drm_device *dev, size_t size)
return &vc4->bo_cache.size_list[page_index];
}
+static void
+vc4_bo_cache_purge(struct drm_device *dev)
+{
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+ while (!list_empty(&vc4->bo_cache.time_list)) {
+ struct vc4_bo *bo = list_last_entry(&vc4->bo_cache.time_list,
+ struct vc4_bo, unref_head);
+ list_del(&bo->unref_head);
+ list_del(&bo->size_head);
+ drm_gem_cma_free_object(&bo->base.base);
+ }
+}
+
struct vc4_bo *
vc4_bo_create(struct drm_device *dev, size_t size)
{
@@ -87,10 +101,17 @@ vc4_bo_create(struct drm_device *dev, size_t size)
/* Otherwise, make a new BO. */
cma_obj = drm_gem_cma_create(dev, size);
- if (IS_ERR(cma_obj))
- return NULL;
- else
- return to_vc4_bo(&cma_obj->base);
+ if (IS_ERR(cma_obj)) {
+ /* If we've run out of CMA memory, kill the cache of
+ * CMA allocations we've got laying around and try again.
+ */
+ vc4_bo_cache_purge(dev);
+ cma_obj = drm_gem_cma_create(dev, size);
+ if (IS_ERR(cma_obj))
+ return NULL;
+ }
+
+ return to_vc4_bo(&cma_obj->base);
}
int