panfrost: Evict the BO cache when allocation fails

If memory allocation fails, we look for a suitable sized BO in the BO cache and
wait until we can use its memory. That usually works, but there's a case when it
can fail despite sufficient memory in the system: BOs in the BO cache
contributing to memory pressure but none of them being of sufficient size. This
case is not just theoretical: it's seen in the OpenCL
test_non_uniform_work_group, which puts the system under considerable memory
pressure with an unusual allocation pattern.

To handle this case, try evicting *everything* from the BO cache and stalling
in order to allocate, if the above attempts failed. Fixes the following error:

   DRM_IOCTL_PANFROST_CREATE_BO failed: No space left on device

on the aforementioned OpenCL test.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Acked-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18579>
This commit is contained in:
Alyssa Rosenzweig 2022-07-07 12:02:03 -04:00 committed by Marge Bot
parent a1b55fde93
commit f06809cdca

View file

@ -379,23 +379,23 @@ panfrost_bo_create(struct panfrost_device *dev, size_t size,
if (flags & PAN_BO_GROWABLE)
assert(flags & PAN_BO_INVISIBLE);
/* Before creating a BO, we first want to check the cache but without
* waiting for BO readiness (BOs in the cache can still be referenced
* by jobs that are not finished yet).
* If the cached allocation fails we fall back on fresh BO allocation,
* and if that fails too, we try one more time to allocate from the
* cache, but this time we accept to wait.
/* Ideally, we get a BO that's ready in the cache, or allocate a fresh
* BO. If allocation fails, we can try waiting for something in the
* cache. But if there's no nothing suitable, we should flush the cache
* to make space for the new allocation.
*/
bo = panfrost_bo_cache_fetch(dev, size, flags, label, true);
if (!bo)
bo = panfrost_bo_alloc(dev, size, flags, label);
if (!bo)
bo = panfrost_bo_cache_fetch(dev, size, flags, label, false);
assert(bo);
if (!bo) {
panfrost_bo_cache_evict_all(dev);
bo = panfrost_bo_alloc(dev, size, flags, label);
}
if (!bo) {
fprintf(stderr, "BO creation failed\n");
unreachable("BO creation failed. We don't handle that yet.");
return NULL;
}