From 248b0b47b74abf51fdda1ae10ca573cbab78c89a Mon Sep 17 00:00:00 2001 From: Xianzhong Li Date: Fri, 3 Apr 2026 14:17:07 +0800 Subject: [PATCH] panfrost: Fix GEM handle refcount leak in panfrost_bo_import panfrost_bo_import() calls drmPrimeFDToHandle() then pan_kmod_bo_import(), which also calls drmPrimeFDToHandle() internally. This double import causes GEM handle refcount leaks because each drmPrimeFDToHandle() increments the kernel's GEM handle refcount, but only one drmCloseBufferHandle() is called during cleanup by panfrost_kmod_bo_free(or panthor_kmod_bo_free). Fix by removing the redundant drmPrimeFDToHandle() and using pan_kmod_bo_import() directly. On re-import of existing buffers, properly release the extra pan_kmod_bo reference with pan_kmod_bo_put(). This ensures GEM handle refcount, pan_kmod_bo refcount, and panfrost_bo refcount are all properly balanced. Fixes: 5089a758dfb1 ("panfrost: Back panfrost_bo with pan_kmod_bo object") Signed-off-by: Xianzhong Li Reviewed-by: Boris Brezillon Reviewed-by: Eric R. Smith Part-of: --- src/gallium/drivers/panfrost/pan_bo.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_bo.c b/src/gallium/drivers/panfrost/pan_bo.c index 082cae1eaef..7ec9c54635b 100644 --- a/src/gallium/drivers/panfrost/pan_bo.c +++ b/src/gallium/drivers/panfrost/pan_bo.c @@ -474,18 +474,24 @@ panfrost_bo_import(struct panfrost_device *dev, int fd) PAN_TRACE_FUNC(PAN_TRACE_GL_BO); struct panfrost_bo *bo; - ASSERTED int ret; + struct pan_kmod_bo *kmod_bo; unsigned gem_handle; pthread_mutex_lock(&dev->bo_map_lock); - ret = drmPrimeFDToHandle(dev->kmod.dev->fd, fd, &gem_handle); - assert(!ret); + /* Import via pan_kmod_bo_import - it handles drmPrimeFDToHandle internally */ + kmod_bo = pan_kmod_bo_import(dev->kmod.dev, fd); + if (!kmod_bo) { + pthread_mutex_unlock(&dev->bo_map_lock); + return NULL; + } + /* Look up panfrost_bo by the GEM handle from kmod_bo */ + gem_handle = pan_kmod_bo_handle(kmod_bo); bo = pan_lookup_bo(dev, gem_handle); if (!bo->dev) { bo->dev = dev; - bo->kmod_bo = pan_kmod_bo_import(dev->kmod.dev, fd); + bo->kmod_bo = kmod_bo; /* Take ownership of kmod_bo reference */ struct pan_kmod_vm_op vm_op = { .type = PAN_KMOD_VM_OP_TYPE_MAP, @@ -513,6 +519,12 @@ panfrost_bo_import(struct panfrost_device *dev, int fd) if ((dev->debug & PAN_DBG_DUMP) && panfrost_bo_mmap(bo)) mesa_loge("failed to mmap"); } else { + /* pan_kmod_bo_import already incremented kmod_bo->refcnt, + * but we already have a reference in bo->kmod_bo, + * so release this extra kmod_bo reference. + */ + pan_kmod_bo_put(kmod_bo); + /* bo->refcnt == 0 can happen if the BO * was being released but panfrost_bo_import() acquired the * lock before panfrost_bo_unreference(). In that case, refcnt