From ea23d4f04e5f9f43d702999f61c7af8d2e1bd0fa Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 27 Sep 2024 09:01:48 +0200 Subject: [PATCH] pan/kmod: Try to use local storage in panthor_kmod_vm_bind() panthor_kmod_vm_bind() is usually called with a single op and at most one sync, so let's optimize the low-number-of-ops-or-syncs case to avoid transient heap allocation. This also fixes some dEQP-VK.api.object_management.alloc_callback_fail.* crashes where panthor_kmod_vm_bind(UNBIND) is called and not expected to fail. Signed-off-by: Boris Brezillon Reviewed-by: Mary Guillemard Part-of: --- src/panfrost/lib/kmod/panthor_kmod.c | 29 ++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/panfrost/lib/kmod/panthor_kmod.c b/src/panfrost/lib/kmod/panthor_kmod.c index a9ffb82e96f..776b2d781ed 100644 --- a/src/panfrost/lib/kmod/panthor_kmod.c +++ b/src/panfrost/lib/kmod/panthor_kmod.c @@ -835,7 +835,9 @@ panthor_kmod_vm_bind(struct pan_kmod_vm *vm, enum pan_kmod_vm_op_mode mode, { struct panthor_kmod_vm *panthor_vm = container_of(vm, struct panthor_kmod_vm, base); + struct drm_panthor_vm_bind_op bind_ops_storage[16]; struct drm_panthor_vm_bind_op *bind_ops = NULL; + struct drm_panthor_sync_op sync_ops_storage[16]; struct drm_panthor_sync_op *sync_ops = NULL; uint32_t syncop_cnt = 0, syncop_ptr = 0; bool async = mode == PAN_KMOD_VM_OP_MODE_ASYNC || @@ -910,7 +912,7 @@ panthor_kmod_vm_bind(struct pan_kmod_vm *vm, enum pan_kmod_vm_op_mode mode, list_addtail(&va_collect->node, &va_collect_list); } - if (syncop_cnt) { + if (syncop_cnt && syncop_cnt > ARRAY_SIZE(sync_ops_storage)) { sync_ops = pan_kmod_dev_alloc_transient(vm->dev, sizeof(*sync_ops) * syncop_cnt); if (!sync_ops) { @@ -918,13 +920,22 @@ panthor_kmod_vm_bind(struct pan_kmod_vm *vm, enum pan_kmod_vm_op_mode mode, syncop_cnt); goto out_free_va_collect; } + } else if (syncop_cnt) { + sync_ops = sync_ops_storage; + memset(sync_ops, 0, sizeof(*sync_ops) * syncop_cnt); } - bind_ops = - pan_kmod_dev_alloc_transient(vm->dev, sizeof(*bind_ops) * op_count); - if (!bind_ops) { - mesa_loge("drm_panthor_vm_bind_op[%d] array allocation failed", op_count); - goto out_free_sync_ops; + if (op_count > ARRAY_SIZE(bind_ops_storage)) { + bind_ops = + pan_kmod_dev_alloc_transient(vm->dev, sizeof(*bind_ops) * op_count); + if (!bind_ops) { + mesa_loge("drm_panthor_vm_bind_op[%d] array allocation failed", + op_count); + goto out_free_sync_ops; + } + } else { + bind_ops = bind_ops_storage; + memset(bind_ops, 0, sizeof(*bind_ops) * op_count); } struct drm_panthor_vm_bind req = { @@ -1064,10 +1075,12 @@ out_update_vas: } } - pan_kmod_dev_free(vm->dev, bind_ops); + if (bind_ops != bind_ops_storage) + pan_kmod_dev_free(vm->dev, bind_ops); out_free_sync_ops: - pan_kmod_dev_free(vm->dev, sync_ops); + if (sync_ops != sync_ops_storage) + pan_kmod_dev_free(vm->dev, sync_ops); out_free_va_collect: list_for_each_entry_safe(struct panthor_kmod_va_collect, va_collect,