accel/ivpu: Make BO free helper NULL-safe

Handle NULL buffers in ivpu_bo_free() so callers can use it as a
kfree-like cleanup helper.

Use the NULL-safe helper to simplify error paths and teardown code in
firmware, IPC, preemption buffer, and metric streamer cleanup. This
removes redundant conditional frees and collapses unwind labels that only
differed by which BOs had been allocated.

Signed-off-by: Andrzej Kacprowski <andrzej.kacprowski@linux.intel.com>
Reviewed-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Link: https://patch.msgid.link/20260924105906.489378-1-andrzej.kacprowski@linux.intel.com
This commit is contained in:
Andrzej Kacprowski 2026-09-24 12:59:06 +02:00 committed by Karol Wachowski
parent 6095cb1190
commit 139e3d9cb4
5 changed files with 44 additions and 58 deletions

View File

@ -364,6 +364,25 @@ static void ivpu_fw_release(struct ivpu_device *vdev)
}
static void ivpu_fw_mem_fini(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
ivpu_bo_free(fw->mem_shave_nn);
ivpu_bo_free(fw->mem_log_verb);
ivpu_bo_free(fw->mem_log_crit);
ivpu_bo_free(fw->mem);
ivpu_bo_free(fw->mem_fw_ver);
ivpu_bo_free(fw->mem_bp);
fw->mem_shave_nn = NULL;
fw->mem_log_verb = NULL;
fw->mem_log_crit = NULL;
fw->mem = NULL;
fw->mem_fw_ver = NULL;
fw->mem_bp = NULL;
}
static int ivpu_fw_mem_init(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
@ -382,7 +401,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (!fw->mem_fw_ver) {
ivpu_err(vdev, "Failed to create firmware version memory buffer\n");
ret = -ENOMEM;
goto err_free_bp;
goto err_free;
}
fw->mem = ivpu_bo_create_runtime(vdev, fw->runtime_addr, fw->runtime_size,
@ -390,14 +409,14 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (!fw->mem) {
ivpu_err(vdev, "Failed to create firmware runtime memory buffer\n");
ret = -ENOMEM;
goto err_free_fw_ver;
goto err_free;
}
ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx, fw->read_only_addr,
fw->read_only_size);
if (ret) {
ivpu_err(vdev, "Failed to set firmware image read-only\n");
goto err_free_fw_mem;
goto err_free;
}
fw->mem_log_crit = ivpu_bo_create_global(vdev, IVPU_FW_CRITICAL_BUFFER_SIZE,
@ -405,7 +424,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (!fw->mem_log_crit) {
ivpu_err(vdev, "Failed to create critical log buffer\n");
ret = -ENOMEM;
goto err_free_fw_mem;
goto err_free;
}
if (ivpu_fw_log_level <= IVPU_FW_LOG_INFO)
@ -418,7 +437,7 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (!fw->mem_log_verb) {
ivpu_err(vdev, "Failed to create verbose log buffer\n");
ret = -ENOMEM;
goto err_free_log_crit;
goto err_free;
}
if (fw->shave_nn_size) {
@ -427,47 +446,17 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
if (!fw->mem_shave_nn) {
ivpu_err(vdev, "Failed to create shavenn buffer\n");
ret = -ENOMEM;
goto err_free_log_verb;
goto err_free;
}
}
return 0;
err_free_log_verb:
ivpu_bo_free(fw->mem_log_verb);
err_free_log_crit:
ivpu_bo_free(fw->mem_log_crit);
err_free_fw_mem:
ivpu_bo_free(fw->mem);
err_free_fw_ver:
ivpu_bo_free(fw->mem_fw_ver);
err_free_bp:
ivpu_bo_free(fw->mem_bp);
err_free:
ivpu_fw_mem_fini(vdev);
return ret;
}
static void ivpu_fw_mem_fini(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
if (fw->mem_shave_nn) {
ivpu_bo_free(fw->mem_shave_nn);
fw->mem_shave_nn = NULL;
}
ivpu_bo_free(fw->mem_log_verb);
ivpu_bo_free(fw->mem_log_crit);
ivpu_bo_free(fw->mem);
ivpu_bo_free(fw->mem_fw_ver);
ivpu_bo_free(fw->mem_bp);
fw->mem_log_verb = NULL;
fw->mem_log_crit = NULL;
fw->mem = NULL;
fw->mem_fw_ver = NULL;
fw->mem_bp = NULL;
}
int ivpu_fw_init(struct ivpu_device *vdev)
{
int ret;

View File

@ -471,6 +471,9 @@ struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64 size, u32 fl
void ivpu_bo_free(struct ivpu_bo *bo)
{
if (!bo)
return;
struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->base.vaddr);
if (bo->flags & DRM_IVPU_BO_MAPPABLE) {

View File

@ -509,7 +509,7 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
if (!ipc->mem_rx) {
ivpu_err(vdev, "Failed to allocate mem_rx\n");
ret = -ENOMEM;
goto err_free_tx;
goto err_free_bo;
}
ipc->mm_tx = devm_gen_pool_create(vdev->drm.dev, __ffs(IVPU_IPC_ALIGNMENT),
@ -517,13 +517,13 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
if (IS_ERR(ipc->mm_tx)) {
ret = PTR_ERR(ipc->mm_tx);
ivpu_err(vdev, "Failed to create gen pool, %pe\n", ipc->mm_tx);
goto err_free_rx;
goto err_free_bo;
}
ret = gen_pool_add(ipc->mm_tx, ipc->mem_tx->vpu_addr, ivpu_bo_size(ipc->mem_tx), -1);
if (ret) {
ivpu_err(vdev, "gen_pool_add failed, ret %d\n", ret);
goto err_free_rx;
goto err_free_bo;
}
spin_lock_init(&ipc->cons_lock);
@ -532,14 +532,13 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
ret = drmm_mutex_init(&vdev->drm, &ipc->lock);
if (ret) {
ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret);
goto err_free_rx;
goto err_free_bo;
}
ivpu_ipc_reset(vdev);
return 0;
err_free_rx:
err_free_bo:
ivpu_bo_free(ipc->mem_rx);
err_free_tx:
ivpu_bo_free(ipc->mem_tx);
err_destroy_cache:
kmem_cache_destroy(ipc->rx_msg_cache);

View File

@ -64,10 +64,8 @@ static int ivpu_preemption_buffers_create(struct ivpu_device *vdev,
static void ivpu_preemption_buffers_free(struct ivpu_device *vdev,
struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
{
if (cmdq->primary_preempt_buf)
ivpu_bo_free(cmdq->primary_preempt_buf);
if (cmdq->secondary_preempt_buf)
ivpu_bo_free(cmdq->secondary_preempt_buf);
ivpu_bo_free(cmdq->primary_preempt_buf);
ivpu_bo_free(cmdq->secondary_preempt_buf);
}
static int ivpu_preemption_job_init(struct ivpu_device *vdev, struct ivpu_file_priv *file_priv,

View File

@ -69,7 +69,7 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
ret = ivpu_jsm_metric_streamer_info(vdev, ms->mask, 0, 0, &sample_size, NULL);
if (ret)
goto err_free_ms;
goto err_free;
buf_size = PAGE_ALIGN((u64)args->read_period_samples * sample_size *
MS_READ_PERIOD_MULTIPLIER * MS_NUM_BUFFERS);
@ -77,14 +77,14 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
ivpu_dbg(vdev, IOCTL, "Requested MS buffer size %llu exceeds range size %llu\n",
buf_size, ivpu_hw_range_size(&vdev->hw->ranges.global));
ret = -EINVAL;
goto err_free_ms;
goto err_free;
}
ms->bo = ivpu_bo_create_global(vdev, buf_size, DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
if (!ms->bo) {
ivpu_dbg(vdev, IOCTL, "Failed to allocate MS buffer (size %llu)\n", buf_size);
ret = -ENOMEM;
goto err_free_ms;
goto err_free;
}
ms->buff_size = ivpu_bo_size(ms->bo) / MS_NUM_BUFFERS;
@ -96,16 +96,15 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
ret = ivpu_jsm_metric_streamer_start(vdev, ms->mask, args->sampling_period_ns,
ms->active_buff_vpu_addr, ms->buff_size);
if (ret)
goto err_free_bo;
goto err_free;
args->sample_size = sample_size;
args->max_data_size = ivpu_bo_size(ms->bo);
list_add_tail(&ms->ms_instance_node, &file_priv->ms_instance_list);
goto unlock;
err_free_bo:
err_free:
ivpu_bo_free(ms->bo);
err_free_ms:
kfree(ms);
unlock:
mutex_unlock(&file_priv->ms_lock);
@ -322,10 +321,8 @@ void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv)
mutex_lock(&file_priv->ms_lock);
if (file_priv->ms_info_bo) {
ivpu_bo_free(file_priv->ms_info_bo);
file_priv->ms_info_bo = NULL;
}
ivpu_bo_free(file_priv->ms_info_bo);
file_priv->ms_info_bo = NULL;
list_for_each_entry_safe(ms, tmp, &file_priv->ms_instance_list, ms_instance_node)
free_instance(file_priv, ms);