From 71a24a0c5e600c6991049c20eaa45da52810a263 Mon Sep 17 00:00:00 2001 From: Mary Guillemard Date: Mon, 8 Jul 2024 12:38:54 +0200 Subject: [PATCH] panfrost: Handle context_init errors correctly This fix OpenCL CTS "multiple_device_context/test_multiples" failures. Also improve create_context/destroy error management a bit. Signed-off-by: Mary Guillemard Reviewed-by: Eric R. Smith Part-of: --- src/gallium/drivers/panfrost/pan_context.c | 45 ++++++++++++----- src/gallium/drivers/panfrost/pan_csf.c | 59 ++++++++++++++++++---- src/gallium/drivers/panfrost/pan_csf.h | 3 +- src/gallium/drivers/panfrost/pan_jm.h | 3 +- src/gallium/drivers/panfrost/pan_screen.h | 2 +- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index f6d84fc950c..b03de8a7e42 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -551,21 +551,25 @@ panfrost_destroy(struct pipe_context *pipe) pan_screen(pipe->screen)->vtbl.context_cleanup(panfrost); - _mesa_hash_table_destroy(panfrost->writers, NULL); + if (panfrost->writers) + _mesa_hash_table_destroy(panfrost->writers, NULL); if (panfrost->blitter) util_blitter_destroy(panfrost->blitter); util_unreference_framebuffer_state(&panfrost->pipe_framebuffer); - u_upload_destroy(pipe->stream_uploader); + if (pipe->stream_uploader) + u_upload_destroy(pipe->stream_uploader); panfrost_pool_cleanup(&panfrost->descs); panfrost_pool_cleanup(&panfrost->shaders); panfrost_afbc_context_destroy(panfrost); drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->in_sync_obj); - if (panfrost->in_sync_fd != -1) + if (panfrost->in_sync_fd != -1) { close(panfrost->in_sync_fd); + panfrost->in_sync_fd = -1; + } drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->syncobj); ralloc_free(pipe); @@ -872,9 +876,25 @@ struct pipe_context * panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) { struct panfrost_context *ctx = rzalloc(NULL, struct panfrost_context); + + if (!ctx) + return NULL; + struct pipe_context *gallium = (struct pipe_context *)ctx; struct panfrost_device *dev = pan_device(screen); + int ret; + + /* Create a syncobj in a signaled state. Will be updated to point to the + * last queued job out_sync every time we submit a new job. + */ + ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED, + &ctx->syncobj); + if (ret) { + ralloc_free(ctx); + return NULL; + } + gallium->screen = screen; gallium->destroy = panfrost_destroy; @@ -969,21 +989,17 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) ctx->sample_mask = ~0; ctx->active_queries = true; - int ASSERTED ret; - - /* Create a syncobj in a signaled state. Will be updated to point to the - * last queued job out_sync every time we submit a new job. - */ - ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED, - &ctx->syncobj); - assert(!ret && ctx->syncobj); - /* Sync object/FD used for NATIVE_FENCE_FD. */ ctx->in_sync_fd = -1; ret = drmSyncobjCreate(panfrost_device_fd(dev), 0, &ctx->in_sync_obj); assert(!ret); - pan_screen(screen)->vtbl.context_init(ctx); + ret = pan_screen(screen)->vtbl.context_init(ctx); + + if (ret) { + gallium->destroy(gallium); + return NULL; + } return gallium; } @@ -992,5 +1008,6 @@ void panfrost_context_reinit(struct panfrost_context *ctx) { pan_screen(ctx->base.screen)->vtbl.context_cleanup(ctx); - pan_screen(ctx->base.screen)->vtbl.context_init(ctx); + ASSERTED int ret = pan_screen(ctx->base.screen)->vtbl.context_init(ctx); + assert(!ret); } diff --git a/src/gallium/drivers/panfrost/pan_csf.c b/src/gallium/drivers/panfrost/pan_csf.c index dc93f722d50..36a1ecf6f05 100644 --- a/src/gallium/drivers/panfrost/pan_csf.c +++ b/src/gallium/drivers/panfrost/pan_csf.c @@ -945,7 +945,7 @@ GENX(csf_launch_draw)(struct panfrost_batch *batch, #define POSITION_FIFO_SIZE (64 * 1024) -void +int GENX(csf_init_context)(struct panfrost_context *ctx) { struct panfrost_device *dev = pan_device(ctx->base.screen); @@ -969,27 +969,42 @@ GENX(csf_init_context)(struct panfrost_context *ctx) int ret = drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_GROUP_CREATE, &gc); - assert(!ret); + if (ret) + goto err_group_create; ctx->csf.group_handle = gc.group_handle; + struct drm_panthor_group_destroy gd = { + .group_handle = ctx->csf.group_handle, + }; + /* Get tiler heap */ struct drm_panthor_tiler_heap_create thc = { .vm_id = pan_kmod_vm_handle(dev->kmod.vm), .chunk_size = pan_screen(ctx->base.screen)->csf_tiler_heap.chunk_size, - .initial_chunk_count = pan_screen(ctx->base.screen)->csf_tiler_heap.initial_chunks, + .initial_chunk_count = + pan_screen(ctx->base.screen)->csf_tiler_heap.initial_chunks, .max_chunks = pan_screen(ctx->base.screen)->csf_tiler_heap.max_chunks, .target_in_flight = 65535, }; ret = drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE, &thc); - assert(!ret); + if (ret) + goto err_tiler_heap; ctx->csf.heap.handle = thc.handle; + struct drm_panthor_tiler_heap_destroy thd = { + .handle = ctx->csf.heap.handle, + }; + ctx->csf.heap.desc_bo = panfrost_bo_create(dev, pan_size(TILER_HEAP), 0, "Tiler Heap"); + + if (ctx->csf.heap.desc_bo == NULL) + goto err_tiler_heap_desc_bo; + pan_pack(ctx->csf.heap.desc_bo->ptr.cpu, TILER_HEAP, heap) { heap.size = pan_screen(ctx->base.screen)->csf_tiler_heap.chunk_size; heap.base = thc.first_heap_chunk_gpu_va; @@ -999,12 +1014,16 @@ GENX(csf_init_context)(struct panfrost_context *ctx) ctx->csf.tmp_geom_bo = panfrost_bo_create( dev, POSITION_FIFO_SIZE, PAN_BO_INVISIBLE, "Temporary Geometry buffer"); - assert(ctx->csf.tmp_geom_bo); + + if (ctx->csf.tmp_geom_bo == NULL) + goto err_tiler_heap_tmp_geom_bo; /* Setup the tiler heap */ struct panfrost_bo *cs_bo = panfrost_bo_create(dev, 4096, 0, "Temporary CS buffer"); - assert(cs_bo); + + if (cs_bo == NULL) + goto err_tiler_heap_cs_bo; struct cs_buffer init_buffer = { .cpu = cs_bo->ptr.cpu, @@ -1039,19 +1058,40 @@ GENX(csf_init_context)(struct panfrost_context *ctx) csf_prepare_qsubmit(ctx, &qsubmit, 0, cs_start, cs_size, &sync, 1); csf_prepare_gsubmit(ctx, &gsubmit, &qsubmit, 1); ret = csf_submit_gsubmit(ctx, &gsubmit); - assert(!ret); + + if (ret) + goto err_g_submit; /* Wait before freeing the buffer. */ - ret = drmSyncobjWait(panfrost_device_fd(dev), &ctx->syncobj, 1, INT64_MAX, - 0, NULL); + ret = drmSyncobjWait(panfrost_device_fd(dev), &ctx->syncobj, 1, INT64_MAX, 0, + NULL); assert(!ret); panfrost_bo_unreference(cs_bo); + + ctx->csf.is_init = true; + return 0; +err_g_submit: + panfrost_bo_unreference(cs_bo); +err_tiler_heap_cs_bo: + panfrost_bo_unreference(ctx->csf.tmp_geom_bo); +err_tiler_heap_tmp_geom_bo: + panfrost_bo_unreference(ctx->csf.heap.desc_bo); +err_tiler_heap_desc_bo: + drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY, + &thd); +err_tiler_heap: + drmIoctl(panfrost_device_fd(dev), DRM_IOCTL_PANTHOR_GROUP_DESTROY, &gd); +err_group_create: + return -1; } void GENX(csf_cleanup_context)(struct panfrost_context *ctx) { + if (!ctx->csf.is_init) + return; + struct panfrost_device *dev = pan_device(ctx->base.screen); struct drm_panthor_tiler_heap_destroy thd = { .handle = ctx->csf.heap.handle, @@ -1076,4 +1116,5 @@ GENX(csf_cleanup_context)(struct panfrost_context *ctx) assert(!ret); panfrost_bo_unreference(ctx->csf.heap.desc_bo); + ctx->csf.is_init = false; } diff --git a/src/gallium/drivers/panfrost/pan_csf.h b/src/gallium/drivers/panfrost/pan_csf.h index ee03219ddc7..e429770d672 100644 --- a/src/gallium/drivers/panfrost/pan_csf.h +++ b/src/gallium/drivers/panfrost/pan_csf.h @@ -48,6 +48,7 @@ struct panfrost_csf_batch { }; struct panfrost_csf_context { + bool is_init; uint32_t group_handle; struct { @@ -70,7 +71,7 @@ struct pipe_draw_info; struct pipe_grid_info; struct pipe_draw_start_count_bias; -void GENX(csf_init_context)(struct panfrost_context *ctx); +int GENX(csf_init_context)(struct panfrost_context *ctx); void GENX(csf_cleanup_context)(struct panfrost_context *ctx); void GENX(csf_init_batch)(struct panfrost_batch *batch); diff --git a/src/gallium/drivers/panfrost/pan_jm.h b/src/gallium/drivers/panfrost/pan_jm.h index 47d99cf3eda..ae4bb69249e 100644 --- a/src/gallium/drivers/panfrost/pan_jm.h +++ b/src/gallium/drivers/panfrost/pan_jm.h @@ -49,9 +49,10 @@ struct pipe_draw_info; struct pipe_grid_info; struct pipe_draw_start_count_bias; -static inline void +static inline int GENX(jm_init_context)(struct panfrost_context *ctx) { + return 0; } static inline void diff --git a/src/gallium/drivers/panfrost/pan_screen.h b/src/gallium/drivers/panfrost/pan_screen.h index 134c92c9d26..ba780193bf5 100644 --- a/src/gallium/drivers/panfrost/pan_screen.h +++ b/src/gallium/drivers/panfrost/pan_screen.h @@ -71,7 +71,7 @@ struct panfrost_vtable { void (*context_populate_vtbl)(struct pipe_context *pipe); /* Initialize/cleanup a Gallium context */ - void (*context_init)(struct panfrost_context *ctx); + int (*context_init)(struct panfrost_context *ctx); void (*context_cleanup)(struct panfrost_context *ctx); /* Device-dependent initialization/cleanup of a panfrost_batch */