mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 02:48:06 +02:00
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: 5089a758df ("panfrost: Back panfrost_bo with pan_kmod_bo object")
Signed-off-by: Xianzhong Li <xianzhong.li@nxp.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40778>
This commit is contained in:
parent
436acc321a
commit
248b0b47b7
1 changed files with 16 additions and 4 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue