panfrost: Fix Panfrost BO leak in error handling path

When panfrost_resource_init_afbc_headers() fails, freeing the newly
created resource is not enough, because we need to unreference its BOs.
This will also take care of freeing its resource label.

Also replace instances of FREE() in error-handling paths with
panfrost_resource_destroy(), as it is capable of handling partially
initialised resources.

Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com>
Fixes: e3f2bc7963 ("panfrost: handle mmap failures")
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34224>
This commit is contained in:
Adrián Larumbe 2025-06-13 01:39:29 +01:00 committed by Marge Bot
parent 28c43385d1
commit 32b128be01

View file

@ -180,6 +180,31 @@ adjust_mtk_tiled_props(struct panfrost_resource *rsc,
return true;
}
static void
panfrost_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pt)
{
MESA_TRACE_FUNC();
struct panfrost_device *dev = pan_device(screen);
struct panfrost_resource *rsrc = (struct panfrost_resource *)pt;
if (rsrc->scanout)
renderonly_scanout_destroy(rsrc->scanout, dev->ro);
if (rsrc->shadow_image)
pipe_resource_reference(
(struct pipe_resource **)&rsrc->shadow_image, NULL);
if (rsrc->bo)
panfrost_bo_unreference(rsrc->bo);
free(rsrc->index_cache);
free(rsrc->damage.tile_map.data);
util_range_destroy(&rsrc->valid_buffer_range);
free(rsrc);
}
static struct pipe_resource *
panfrost_resource_from_handle(struct pipe_screen *pscreen,
const struct pipe_resource *templat,
@ -242,7 +267,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
if (drm_is_mtk_tiled(mod) &&
!adjust_mtk_tiled_props(rsc, &iprops, whandle->plane,
&explicit_layout)) {
FREE(rsc);
panfrost_resource_destroy(pscreen, &rsc->base);
return NULL;
}
@ -253,7 +278,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
&explicit_layout, &rsc->plane.layout);
if (!valid) {
FREE(rsc);
panfrost_resource_destroy(pscreen, &rsc->base);
return NULL;
}
@ -264,7 +289,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
* memory space to mmap it etc.
*/
if (!rsc->bo) {
FREE(rsc);
panfrost_resource_destroy(pscreen, &rsc->base);
return NULL;
}
@ -932,7 +957,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
if (!so->scanout) {
mesa_loge("Failed to create scanout resource\n");
FREE(so);
panfrost_resource_destroy(screen, &so->base);
return NULL;
}
assert(handle.type == WINSYS_HANDLE_TYPE_FD);
@ -940,7 +965,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
close(handle.handle);
if (!so->bo) {
FREE(so);
panfrost_resource_destroy(screen, &so->base);
return NULL;
}
@ -958,7 +983,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
panfrost_bo_create(dev, so->plane.layout.data_size_B, flags, label);
if (!so->bo) {
FREE(so);
panfrost_resource_destroy(screen, &so->base);
return NULL;
}
@ -969,7 +994,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
if (drm_is_afbc(so->modifier)) {
if (panfrost_resource_init_afbc_headers(so)) {
FREE(so);
panfrost_resource_destroy(screen, &so->base);
return NULL;
}
}
@ -1088,31 +1113,6 @@ panfrost_resource_restore_format(struct panfrost_resource *rsrc,
rsrc->image.props.extent_px.height = saved->image.props.extent_px.height;
}
static void
panfrost_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pt)
{
MESA_TRACE_FUNC();
struct panfrost_device *dev = pan_device(screen);
struct panfrost_resource *rsrc = (struct panfrost_resource *)pt;
if (rsrc->scanout)
renderonly_scanout_destroy(rsrc->scanout, dev->ro);
if (rsrc->shadow_image)
pipe_resource_reference(
(struct pipe_resource **)&rsrc->shadow_image, NULL);
if (rsrc->bo)
panfrost_bo_unreference(rsrc->bo);
free(rsrc->index_cache);
free(rsrc->damage.tile_map.data);
util_range_destroy(&rsrc->valid_buffer_range);
free(rsrc);
}
/* Most of the time we can do CPU-side transfers, but sometimes we need to use
* the 3D pipe for this. Let's wrap u_blitter to blit to/from staging textures.
* Code adapted from freedreno */