diff options
author | Eric Anholt <eric@anholt.net> | 2015-05-15 12:33:00 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2015-06-04 14:15:35 -0700 |
commit | 006708c9879d3951edcec2a74021afc41ac65084 (patch) | |
tree | 10b9dfd950cbb06cfc8955d8b9fb9e83a36d2dd3 | |
parent | 660b630f8de24d4c73f5f2982b65ed2537735c1d (diff) | |
download | linux-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.c | 29 |
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 |