From a2dba7e53ba3aef8b439dd490cd67656495250cc Mon Sep 17 00:00:00 2001 From: amitabhd Date: Thu, 12 Dec 2024 18:03:55 +0000 Subject: [PATCH] host1x_emu: SyncpointIncre per-improvement 1. Add mechanism(s) to trigger syncpoint fence scan when syncpoint increment UMD called. Following methods are added. - METHOD-1: Check fence expire in user context when syncpoint increment UMD API is called. - METHOD-2: Add tasklet based mechanism that schedule tasklet to scan for syncpoint fence expiry. This also improve signaling latency. METHOD-1 is enabled by default, to enable METHOD-2 define MACRO "HOST1X_EMU_SYNC_INC_TASKLET". 2. Add interface "host1x_syncpt_fence_scan()" that can be called from client interrupt handler to initiate syncpoint fence scan. Jira HOSTX-5527 Change-Id: I4d5a0ba9fd67042d824a1df2794b316831001dc4 Signed-off-by: amitabhd Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3267144 Reviewed-by: Raghavendra Vishnu Kumar Reviewed-by: Sanif Veeras GVS: buildbot_gerritrpt Reviewed-by: Leslin Varghese --- drivers/gpu/host1x-emu/Makefile | 5 +- drivers/gpu/host1x-emu/fence.c | 12 +++-- .../gpu/host1x-emu/include/linux/host1x-emu.h | 8 +-- .../gpu/host1x-emu/include/linux/symbol-emu.h | 11 ++-- drivers/gpu/host1x-emu/poll.c | 53 ++++++++++--------- drivers/gpu/host1x-emu/poll.h | 11 ++-- drivers/gpu/host1x-emu/syncpt.c | 36 +++++++++++-- 7 files changed, 88 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/host1x-emu/Makefile b/drivers/gpu/host1x-emu/Makefile index 54d472eb..351df0db 100644 --- a/drivers/gpu/host1x-emu/Makefile +++ b/drivers/gpu/host1x-emu/Makefile @@ -1,11 +1,14 @@ # SPDX-License-Identifier: GPL-2.0-only -# Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2024-2025 NVIDIA CORPORATION. All rights reserved. # Enable below flag for hypervisor build configuration ifeq ($(NV_BUILD_CONFIGURATION_EMU_SYNCPT),1) ccflags-y += -DHOST1X_EMU_HYPERVISOR endif +#Enable Tasklet based fence scanning in SyncpointIncr +#ccflags-y += -DHOST1X_EMU_SYNC_INC_TASKLET + ifeq ($(NV_BUILD_CONFIGURATION_EXPOSING_T26X), 1) LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-emu/include # Enable for verification in VDK. Below allow Emulated Syncpoint driver diff --git a/drivers/gpu/host1x-emu/fence.c b/drivers/gpu/host1x-emu/fence.c index f77809c3..3094b147 100644 --- a/drivers/gpu/host1x-emu/fence.c +++ b/drivers/gpu/host1x-emu/fence.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include #include #include @@ -188,3 +186,9 @@ HOST1X_EMU_EXPORT_DECL(void, host1x_fence_cancel(struct dma_fence *dfence)) flush_delayed_work(&sf->timeout_work); } HOST1X_EMU_EXPORT_SYMBOL(host1x_fence_cancel); + +HOST1X_EMU_EXPORT_DECL(void, host1x_syncpt_fence_scan(struct host1x_syncpt *sp)) +{ + host1x_poll_irq_check_syncpt_fence(sp); +} +HOST1X_EMU_EXPORT_SYMBOL(host1x_syncpt_fence_scan); diff --git a/drivers/gpu/host1x-emu/include/linux/host1x-emu.h b/drivers/gpu/host1x-emu/include/linux/host1x-emu.h index 76388b75..c55dbcb2 100644 --- a/drivers/gpu/host1x-emu/include/linux/host1x-emu.h +++ b/drivers/gpu/host1x-emu/include/linux/host1x-emu.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #ifndef __LINUX_HOST1X_H #define __LINUX_HOST1X_H @@ -61,6 +59,8 @@ HOST1X_EMU_EXPORT_DECL(int, host1x_syncpt_incr(struct host1x_syncpt *sp)); HOST1X_EMU_EXPORT_DECL(u32, host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs)); +HOST1X_EMU_EXPORT_DECL(void, host1x_syncpt_fence_scan(struct host1x_syncpt *sp)); + HOST1X_EMU_EXPORT_DECL(int, host1x_syncpt_wait_ts(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value, ktime_t *ts)); diff --git a/drivers/gpu/host1x-emu/include/linux/symbol-emu.h b/drivers/gpu/host1x-emu/include/linux/symbol-emu.h index 23362bfe..0f1547ed 100644 --- a/drivers/gpu/host1x-emu/include/linux/symbol-emu.h +++ b/drivers/gpu/host1x-emu/include/linux/symbol-emu.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #ifndef __HOST1X_EMU_SYMMBOL_H #define __HOST1X_EMU_SYMMBOL_H @@ -14,4 +12,9 @@ #define HOST1X_EMU_EXPORT_DECL(ret, ...) ret __VA_ARGS__ #define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(f) #endif + +#ifndef CONFIG_TEGRA_HOST1X_EMU_DBG_SYMBL +HOST1X_EMU_EXPORT_DECL(void, host1x_syncpt_fence_scan(struct host1x_syncpt *sp)); +#endif /*CONFIG_TEGRA_HOST1X_EMU_DBG_SYMBL*/ + #endif /*__HOST1X_EMU_SYMMBOL_H*/ diff --git a/drivers/gpu/host1x-emu/poll.c b/drivers/gpu/host1x-emu/poll.c index fcdf9967..13519cf5 100644 --- a/drivers/gpu/host1x-emu/poll.c +++ b/drivers/gpu/host1x-emu/poll.c @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include "dev.h" #include "fence.h" #include "poll.h" @@ -56,28 +54,10 @@ static void host1x_pool_timeout_handler(struct work_struct *work) struct host1x_syncpt *sp; struct host1x_syncpt *tmp_spt; struct host1x *host = pool->host; - ktime_t ts = ktime_get(); - spin_lock(&pool->syncpt_list.lock); - list_for_each_entry_safe(sp, tmp_spt, &pool->syncpt_list.list, list) { - struct host1x_syncpt_fence *fence, *tmp; - unsigned int value; - - value = host1x_syncpt_load(sp); - - spin_lock(&sp->fences.lock); - list_for_each_entry_safe(fence, tmp, &sp->fences.list, list) { - if (((value - fence->threshold) & 0x80000000U) != 0U) { - /* Fence is not yet expired, we are done */ - break; - } - - list_del_init(&fence->list); - host1x_fence_signal(fence ,ts); - } - spin_unlock(&sp->fences.lock); - } - spin_unlock(&pool->syncpt_list.lock); + list_for_each_entry_safe(sp, tmp_spt, &pool->syncpt_list.list, list) { + host1x_poll_irq_check_syncpt_fence(sp); + } /** * TODO: Optimize pool polling mechanism @@ -116,12 +96,33 @@ int host1x_poll_init(struct host1x *host) INIT_LIST_HEAD(&syncpt->list); /* Add syncpoint to pool list*/ - list_add(&syncpt->list, &pool->syncpt_list.list); + list_add_tail(&syncpt->list, &pool->syncpt_list.list); } return 0; } +void host1x_poll_irq_check_syncpt_fence(struct host1x_syncpt *sp) +{ + unsigned int value; + unsigned long irqflags; + struct host1x_syncpt_fence *fence, *tmp; + ktime_t ts = ktime_get(); + + value = host1x_syncpt_load(sp); + spin_lock_irqsave(&sp->fences.lock, irqflags); + list_for_each_entry_safe(fence, tmp, &sp->fences.list, list) { + if (((value - fence->threshold) & 0x80000000U) != 0U) { + /* Fence is not yet expired, we are done */ + break; + } + + list_del_init(&fence->list); + host1x_fence_signal(fence, ts); + } + spin_unlock_irqrestore(&sp->fences.lock, irqflags); +} + void host1x_poll_start(struct host1x *host) { int id; diff --git a/drivers/gpu/host1x-emu/poll.h b/drivers/gpu/host1x-emu/poll.h index 070e995c..dfa1c1bd 100644 --- a/drivers/gpu/host1x-emu/poll.h +++ b/drivers/gpu/host1x-emu/poll.h @@ -1,7 +1,5 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #ifndef __HOST1X_EMU_POLL_H #define __HOST1X_EMU_POLL_H @@ -10,6 +8,7 @@ #include struct host1x; +struct host1x_syncpt; struct host1x_syncpt_fence; struct host1x_fence_list { @@ -58,4 +57,8 @@ void host1x_poll_add_fence_locked(struct host1x *host, struct host1x_syncpt_fenc */ bool host1x_poll_remove_fence(struct host1x *host, struct host1x_syncpt_fence *fence); +/** + * Description: Check if syncpoint fence expired + */ +void host1x_poll_irq_check_syncpt_fence(struct host1x_syncpt *sp); #endif diff --git a/drivers/gpu/host1x-emu/syncpt.c b/drivers/gpu/host1x-emu/syncpt.c index 82d369cc..8f908531 100644 --- a/drivers/gpu/host1x-emu/syncpt.c +++ b/drivers/gpu/host1x-emu/syncpt.c @@ -1,17 +1,33 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * SPDX-License-Identifier: GPL-2.0-only - */ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include #include #include #include #include #include +#include +#include #include "dev.h" #include "syncpt.h" +#ifdef HOST1X_EMU_SYNC_INC_TASKLET +static void tasklet_fn(struct tasklet_struct *unused); +static DEFINE_PER_CPU(struct host1x_syncpt *, tasklet_sp); + +DECLARE_TASKLET(syncpt_tasklet, tasklet_fn); + +static void tasklet_fn(struct tasklet_struct *unused) +{ + struct host1x_syncpt *sp = NULL; + + sp = this_cpu_read(tasklet_sp); + if (sp != NULL) + host1x_poll_irq_check_syncpt_fence(sp); +} +#endif + static void syncpt_release(struct kref *ref) { struct host1x_syncpt *sp = container_of(ref, struct host1x_syncpt, ref); @@ -241,7 +257,17 @@ HOST1X_EMU_EXPORT_SYMBOL(host1x_syncpt_read_max); */ HOST1X_EMU_EXPORT_DECL(int, host1x_syncpt_incr(struct host1x_syncpt *sp)) { - return host1x_hw_syncpt_cpu_incr(sp->host, sp); + int err; + + err = host1x_hw_syncpt_cpu_incr(sp->host, sp); +#ifdef HOST1X_EMU_SYNC_INC_TASKLET + /*Improve Signaling performance*/ + this_cpu_write(tasklet_sp, sp); + tasklet_schedule(&syncpt_tasklet); +#else + host1x_poll_irq_check_syncpt_fence(sp); +#endif + return err; } HOST1X_EMU_EXPORT_SYMBOL(host1x_syncpt_incr);