From bd7e653e1ee009e225b0bbf60dcaebc9b0fa2788 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Aug 2013 22:03:16 +0100 Subject: [PATCH] sna: Avoid leaking stolen framebuffer bo Framebuffers created from stolen bo were not being released and so the kernel would keep the fb and bo alive, causing the memory to be remain unreusable whilst X lived and us to leak all available stolen memory. Signed-off-by: Chris Wilson --- src/sna/kgem.c | 51 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 498c2000..ed905889 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -1795,30 +1795,6 @@ static void _kgem_bo_delete_buffer(struct kgem *kgem, struct kgem_bo *bo) io->used = bo->delta; } -static void kgem_bo_clear_scanout(struct kgem *kgem, struct kgem_bo *bo) -{ - assert(bo->scanout); - assert(!bo->refcnt); - assert(bo->exec == NULL); - assert(bo->proxy == NULL); - - DBG(("%s: handle=%d, fb=%d (reusable=%d)\n", - __FUNCTION__, bo->handle, bo->delta, bo->reusable)); - if (bo->delta) { - /* XXX will leak if we are not DRM_MASTER. *shrug* */ - drmIoctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta); - bo->delta = 0; - } - - bo->scanout = false; - bo->flush = false; - bo->reusable = true; - - if (kgem->has_llc && - !gem_set_cacheing(kgem->fd, bo->handle, SNOOPED)) - bo->reusable = false; -} - static bool check_scanout_size(struct kgem *kgem, struct kgem_bo *bo, int width, int height) @@ -3029,15 +3005,34 @@ void kgem_clean_scanout_cache(struct kgem *kgem) struct kgem_bo *bo; bo = list_first_entry(&kgem->scanout, struct kgem_bo, list); + + assert(bo->scanout); + assert(bo->delta); + assert(!bo->refcnt); + assert(bo->exec == NULL); + assert(bo->proxy == NULL); + if (bo->exec || __kgem_busy(kgem, bo->handle)) break; + DBG(("%s: handle=%d, fb=%d (reusable=%d)\n", + __FUNCTION__, bo->handle, bo->delta, bo->reusable)); list_del(&bo->list); + + /* XXX will leak if we are not DRM_MASTER. *shrug* */ + drmIoctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta); + bo->delta = 0; + bo->scanout = false; + if (!bo->purged) { - kgem_bo_clear_scanout(kgem, bo); - __kgem_bo_destroy(kgem, bo); - } else - kgem_bo_free(kgem, bo); + bo->reusable = true; + if (kgem->has_llc && + !gem_set_cacheing(kgem->fd, bo->handle, SNOOPED)) + bo->reusable = false; + + } + + __kgem_bo_destroy(kgem, bo); } }