From 2cc3c99c6ee57c077014aa6c6fa5cd402c24d8fe Mon Sep 17 00:00:00 2001 From: amitabhd Date: Thu, 20 Feb 2025 11:05:00 +0000 Subject: [PATCH] host1x_emu: Adding API dispatch functionality Adding dynamic APi dispatch functionality in host1x-fence modue. This CL exports new host1x wrapper API, which can be called by client kernel modules. The wrapper API dispatch call to either Host1x module or Host1x-EMU depending if the host1x-emu driver registered its interface during its probe. Bug 5064819 Change-Id: I49445cdce7c3795a2c94fde9d0871da393993554 Signed-off-by: amitabhd Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3306857 GVS: buildbot_gerritrpt Reviewed-by: Leslin Varghese Reviewed-by: Raghavendra Vishnu Kumar --- BUILD.bazel | 1 + drivers/gpu/host1x-emu/Makefile | 6 +- drivers/gpu/host1x-emu/dev.c | 65 +++ .../gpu/host1x-emu/include/linux/symbol-emu.h | 8 +- drivers/gpu/host1x-fence/Makefile | 6 +- drivers/gpu/host1x-fence/dev.c | 16 +- drivers/gpu/host1x-fence/dispatch.c | 383 ++++++++++++++++++ .../include/linux/host1x-dispatch.h | 62 +++ .../include/linux/host1x-dispatch_api.h | 150 +++++++ .../include/linux/host1x-dispatch_type.h | 75 ++++ 10 files changed, 764 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/host1x-fence/dispatch.c create mode 100644 drivers/gpu/host1x-fence/include/linux/host1x-dispatch.h create mode 100644 drivers/gpu/host1x-fence/include/linux/host1x-dispatch_api.h create mode 100644 drivers/gpu/host1x-fence/include/linux/host1x-dispatch_type.h diff --git a/BUILD.bazel b/BUILD.bazel index 4535c05c..510e2733 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -20,6 +20,7 @@ filegroup( name = "host1x.includes", srcs = glob([ "drivers/gpu/host1x/include/**/*.h", + "drivers/gpu/host1x-fence/include/**/*.h", ]), ) diff --git a/drivers/gpu/host1x-emu/Makefile b/drivers/gpu/host1x-emu/Makefile index 2ef18f80..e3aa43a8 100644 --- a/drivers/gpu/host1x-emu/Makefile +++ b/drivers/gpu/host1x-emu/Makefile @@ -15,16 +15,18 @@ ccflags-y += -DHOST1X_EMU_KTHREAD_FENCE_SCAN # Enable HRTimer based fence scanning ccflags-y += -DHOST1X_EMU_HRTIMER_FENCE_SCAN -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 # to co-exits with "Host1x" driver by exporting modified kernel symbol. ccflags-y += -DCONFIG_TEGRA_HOST1X_EMU_DBG_SYMBL +ifeq ($(NV_BUILD_CONFIGURATION_EXPOSING_T26X), 1) # Enable debug CONFIG_TEGRA_HOST1X_EMU_SYNCPT_DEBUG := 1 endif +LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-emu/include +LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-fence/include + host1x-emu-y += \ dev.o \ poll.o \ diff --git a/drivers/gpu/host1x-emu/dev.c b/drivers/gpu/host1x-emu/dev.c index 686da4aa..275a0394 100644 --- a/drivers/gpu/host1x-emu/dev.c +++ b/drivers/gpu/host1x-emu/dev.c @@ -12,6 +12,15 @@ #include #include +#ifdef CONFIG_TEGRA_HOST1X_EMU_DBG_SYMBL +#include +#include +#else +#include +#include +#include +#endif + #if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) #include #endif @@ -21,6 +30,7 @@ #include "dev.h" #include "debug.h" #include "hw/host1xEMU.h" +#include #define HOST1X_POOL_MSEC_PERIOD 70 /*70msec*/ #define HOST1X_SYNCPT_POOL_BASE(x) (x*2+0) @@ -32,6 +42,58 @@ static const struct host1x_info host1xEmu_info = { .dma_mask = DMA_BIT_MASK(40), }; +struct host1x_interface_ops host1x_emu_api = { + .host1x_fence_create = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_fence_create), + .host1x_fence_extract = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_fence_extract), + .host1x_fence_cancel = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_fence_cancel), + .host1x_fence_get_node = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_fence_get_node), + .host1x_get_dma_mask = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_get_dma_mask), + .host1x_syncpt_get = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_get), + .host1x_syncpt_get_by_id = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_get_by_id), + .host1x_syncpt_get_by_id_noref = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_get_by_id_noref), + .host1x_syncpt_read = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_read), + .host1x_syncpt_read_min = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_read_min), + .host1x_syncpt_read_max = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_read_max), + .host1x_syncpt_incr = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_incr), + .host1x_syncpt_incr_max = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_incr_max), + .host1x_syncpt_alloc = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_alloc), + .host1x_syncpt_put = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_put), + .host1x_syncpt_id = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_id), + .host1x_syncpt_wait_ts = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_wait_ts), + .host1x_syncpt_wait = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_syncpt_wait), + +//nvhost.h Interface + .host1x_writel = HOST1X_EMU_EXPORT_SYMBOL_NAME(host1x_writel), + .nvhost_get_default_device = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_get_default_device), + .nvhost_get_host1x = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_get_host1x), + .nvhost_client_device_get_resources = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_client_device_get_resources), + .nvhost_client_device_init = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_client_device_init), + .nvhost_client_device_release = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_client_device_release), + .nvhost_get_syncpt_host_managed = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_get_syncpt_host_managed), + .nvhost_get_syncpt_client_managed = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_get_syncpt_client_managed), + .nvhost_get_syncpt_gpu_managed = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_get_syncpt_gpu_managed), + .nvhost_syncpt_put_ref_ext = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_put_ref_ext), + .nvhost_syncpt_is_valid_pt_ext = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_is_valid_pt_ext), + .nvhost_syncpt_is_expired_ext = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_is_expired_ext), + .nvhost_syncpt_set_min_update = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_set_min_update), + .nvhost_syncpt_read_ext_check = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_read_ext_check), + .nvhost_syncpt_read_maxval = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_read_maxval), + .nvhost_syncpt_incr_max_ext = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_incr_max_ext), + .nvhost_syncpt_unit_interface_get_byte_offset_ext = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_unit_interface_get_byte_offset_ext), + .nvhost_syncpt_unit_interface_get_byte_offset = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_unit_interface_get_byte_offset), + .nvhost_syncpt_unit_interface_get_aperture = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_unit_interface_get_aperture), + .nvhost_syncpt_unit_interface_init = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_unit_interface_init), + .nvhost_syncpt_unit_interface_deinit = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_unit_interface_deinit), + .nvhost_syncpt_address = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_syncpt_address), + .nvhost_intr_register_notifier = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_intr_register_notifier), + .nvhost_module_init = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_init), + .nvhost_module_deinit = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_deinit), + .nvhost_module_reset = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_reset), + .nvhost_module_busy = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_busy), + .nvhost_module_idle = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_idle), + .nvhost_module_idle_mult = HOST1X_EMU_EXPORT_SYMBOL_NAME(nvhost_module_idle_mult), +}; + static const struct of_device_id host1x_of_match[] = { { .compatible = "nvidia,tegraEmu-host1x", .data = &host1xEmu_info, }, { }, @@ -309,6 +371,9 @@ static int host1x_probe(struct platform_device *pdev) /* Start pool polling thread*/ host1x_poll_start(host); + /* Register Host1x-EMU Interface*/ + host1x_wrapper_register_interface(&host1x_emu_api); + pr_info("Host1x-EMU: Probe Done\n"); return 0; diff --git a/drivers/gpu/host1x-emu/include/linux/symbol-emu.h b/drivers/gpu/host1x-emu/include/linux/symbol-emu.h index 8508a714..446e58d0 100644 --- a/drivers/gpu/host1x-emu/include/linux/symbol-emu.h +++ b/drivers/gpu/host1x-emu/include/linux/symbol-emu.h @@ -4,13 +4,15 @@ #define __HOST1X_EMU_SYMMBOL_H #ifdef CONFIG_TEGRA_HOST1X_EMU_DBG_SYMBL -#define HOST1X_EMU_EXPORT_CALL(...) Dbg_ ## __VA_ARGS__ -#define HOST1X_EMU_EXPORT_DECL(ret, ...) ret Dbg_ ## __VA_ARGS__ -#define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(Dbg_## f) +#define HOST1X_EMU_EXPORT_CALL(...) Emu_ ## __VA_ARGS__ +#define HOST1X_EMU_EXPORT_DECL(ret, ...) ret Emu_ ## __VA_ARGS__ +#define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(Emu_## f) +#define HOST1X_EMU_EXPORT_SYMBOL_NAME(f) Emu_## f #else #define HOST1X_EMU_EXPORT_CALL(...) __VA_ARGS__ #define HOST1X_EMU_EXPORT_DECL(ret, ...) ret __VA_ARGS__ #define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(f) +#define HOST1X_EMU_EXPORT_SYMBOL_NAME(f) f #endif #endif /*__HOST1X_EMU_SYMMBOL_H*/ diff --git a/drivers/gpu/host1x-fence/Makefile b/drivers/gpu/host1x-fence/Makefile index 4f15cabb..92d00d20 100644 --- a/drivers/gpu/host1x-fence/Makefile +++ b/drivers/gpu/host1x-fence/Makefile @@ -6,6 +6,10 @@ ccflags-y += -DCONFIG_TEGRA_HOST1X ccflags-y += -Werror -host1x-fence-objs = dev.o +LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-fence/include + +host1x-fence-objs += \ + dev.o \ + dispatch.o obj-m += host1x-fence.o diff --git a/drivers/gpu/host1x-fence/dev.c b/drivers/gpu/host1x-fence/dev.c index 39759882..98eaf551 100644 --- a/drivers/gpu/host1x-fence/dev.c +++ b/drivers/gpu/host1x-fence/dev.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -15,11 +14,14 @@ #include #include #include +#include #include "include/uapi/linux/host1x-fence.h" #define HOST1X_INSTANCE_MAX 2 +bool host1x_wrapper_init(void); + static struct host1x_uapi { struct class *class; @@ -527,11 +529,21 @@ static int host1x_uapi_init(struct host1x_uapi *uapi) err = PTR_ERR(uapi->dev); goto del_cdev; } - cdev_add(&uapi->cdev, dev_num, 1); uapi->dev_num = dev_num; + host1x_wrapper_init(); + + /* + * Don't allow the kernel module to be unloaded. Unloading adds complexity + * during GVS verification. Resolving is not worth the effort in this case + */ + if (!try_module_get(THIS_MODULE)) { + pr_info("Host1x-Fence: Get Module Failed\n"); + goto del_cdev; + } + return 0; del_cdev: diff --git a/drivers/gpu/host1x-fence/dispatch.c b/drivers/gpu/host1x-fence/dispatch.c new file mode 100644 index 00000000..a19d223d --- /dev/null +++ b/drivers/gpu/host1x-fence/dispatch.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +#include "include/linux/host1x-dispatch_type.h" +#include "include/linux/host1x-dispatch_api.h" +#include +#include + +bool host1x_wrapper_init(void); + +struct host1x_interface_ops host1x_api_table = {NULL}; + +static bool host1x_wrapper_init_default_interface(void) +{ + host1x_api_table.host1x_fence_create = host1x_fence_create; + host1x_api_table.host1x_fence_extract = host1x_fence_extract; + host1x_api_table.host1x_fence_cancel = host1x_fence_cancel; + host1x_api_table.host1x_fence_get_node = host1x_fence_get_node; + host1x_api_table.host1x_get_dma_mask = host1x_get_dma_mask; + host1x_api_table.host1x_syncpt_get = host1x_syncpt_get; + host1x_api_table.host1x_syncpt_get_by_id = host1x_syncpt_get_by_id; + host1x_api_table.host1x_syncpt_get_by_id_noref = host1x_syncpt_get_by_id_noref; + host1x_api_table.host1x_syncpt_read = host1x_syncpt_read; + host1x_api_table.host1x_syncpt_read_min = host1x_syncpt_read_min; + host1x_api_table.host1x_syncpt_read_max = host1x_syncpt_read_max; + host1x_api_table.host1x_syncpt_incr = host1x_syncpt_incr; + host1x_api_table.host1x_syncpt_incr_max = host1x_syncpt_incr_max; + host1x_api_table.host1x_syncpt_alloc = host1x_syncpt_alloc; + host1x_api_table.host1x_syncpt_put = host1x_syncpt_put; + host1x_api_table.host1x_syncpt_id = host1x_syncpt_id; + host1x_api_table.host1x_syncpt_wait_ts = host1x_syncpt_wait_ts; + host1x_api_table.host1x_syncpt_wait = host1x_syncpt_wait; + // Interface for nvhost.h + host1x_api_table.host1x_writel = host1x_writel; + host1x_api_table.nvhost_get_default_device = nvhost_get_default_device; + host1x_api_table.nvhost_get_host1x = nvhost_get_host1x; + host1x_api_table.nvhost_client_device_get_resources = nvhost_client_device_get_resources; + host1x_api_table.nvhost_client_device_init = nvhost_client_device_init; + host1x_api_table.nvhost_client_device_release = nvhost_client_device_release; + host1x_api_table.nvhost_get_syncpt_host_managed = nvhost_get_syncpt_host_managed; + host1x_api_table.nvhost_get_syncpt_client_managed = nvhost_get_syncpt_client_managed; + host1x_api_table.nvhost_get_syncpt_gpu_managed = nvhost_get_syncpt_gpu_managed; + host1x_api_table.nvhost_syncpt_put_ref_ext = nvhost_syncpt_put_ref_ext; + host1x_api_table.nvhost_syncpt_is_valid_pt_ext = nvhost_syncpt_is_valid_pt_ext; + host1x_api_table.nvhost_syncpt_is_expired_ext = nvhost_syncpt_is_expired_ext; + host1x_api_table.nvhost_syncpt_set_min_update = nvhost_syncpt_set_min_update; + host1x_api_table.nvhost_syncpt_read_ext_check = nvhost_syncpt_read_ext_check; + host1x_api_table.nvhost_syncpt_read_maxval = nvhost_syncpt_read_maxval; + host1x_api_table.nvhost_syncpt_incr_max_ext = nvhost_syncpt_incr_max_ext; + host1x_api_table.nvhost_syncpt_unit_interface_get_byte_offset_ext = nvhost_syncpt_unit_interface_get_byte_offset_ext; + host1x_api_table.nvhost_syncpt_unit_interface_get_byte_offset = nvhost_syncpt_unit_interface_get_byte_offset; + host1x_api_table.nvhost_syncpt_unit_interface_get_aperture = nvhost_syncpt_unit_interface_get_aperture; + host1x_api_table.nvhost_syncpt_unit_interface_init = nvhost_syncpt_unit_interface_init; + host1x_api_table.nvhost_syncpt_unit_interface_deinit = nvhost_syncpt_unit_interface_deinit; + host1x_api_table.nvhost_syncpt_address = nvhost_syncpt_address; + host1x_api_table.nvhost_intr_register_notifier = nvhost_intr_register_notifier; + host1x_api_table.nvhost_module_init = nvhost_module_init; + host1x_api_table.nvhost_module_deinit = nvhost_module_deinit; + host1x_api_table.nvhost_module_idle_mult = nvhost_module_idle_mult; + + return true; +} + +bool host1x_wrapper_init(void) +{ + host1x_wrapper_init_default_interface(); + pr_info("Host1x-Fence: Default interface init done\n"); + return true; +} + +bool host1x_wrapper_register_interface(struct host1x_interface_ops *host1x_ops) +{ + + if (host1x_ops == NULL) + return false; + + host1x_api_table = *host1x_ops; + return true; +} +EXPORT_SYMBOL(host1x_wrapper_register_interface); + +struct dma_fence* wrap_host1x_fence_create(struct host1x_syncpt *sp, + u32 threshold, + bool timeout) +{ + return host1x_api_table.host1x_fence_create(sp, threshold, timeout); +} +EXPORT_SYMBOL(wrap_host1x_fence_create); + +int wrap_host1x_fence_extract(struct dma_fence *dfence, u32 *id, u32 *threshold) +{ + return host1x_api_table.host1x_fence_extract(dfence, id, threshold); +} +EXPORT_SYMBOL(wrap_host1x_fence_extract); + +void wrap_host1x_fence_cancel(struct dma_fence *dfence) +{ + return host1x_api_table.host1x_fence_cancel(dfence); +} +EXPORT_SYMBOL(wrap_host1x_fence_cancel); + +int wrap_host1x_fence_get_node(struct dma_fence *fence) +{ + return host1x_api_table.host1x_fence_get_node(fence); +} +EXPORT_SYMBOL(wrap_host1x_fence_get_node); + +// Syncpt.c +u64 wrap_host1x_get_dma_mask(struct host1x *host1x) +{ + return host1x_api_table.host1x_get_dma_mask(host1x); +} +EXPORT_SYMBOL(wrap_host1x_get_dma_mask); + +struct host1x_syncpt* wrap_host1x_syncpt_get( + struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_get(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_get); + +struct host1x_syncpt* wrap_host1x_syncpt_get_by_id( + struct host1x *host, unsigned int id) +{ + return host1x_api_table.host1x_syncpt_get_by_id(host, id); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_get_by_id); + +struct host1x_syncpt* wrap_host1x_syncpt_get_by_id_noref(struct host1x *host, unsigned int id) +{ + return host1x_api_table.host1x_syncpt_get_by_id_noref(host, id); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_get_by_id_noref); + +u32 wrap_host1x_syncpt_read(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_read(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_read); + +u32 wrap_host1x_syncpt_read_min(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_read_min(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_read_min); + +u32 wrap_host1x_syncpt_read_max(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_read_max(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_read_max); + +int wrap_host1x_syncpt_incr(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_incr(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_incr); + +u32 wrap_host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs) +{ + return host1x_api_table.host1x_syncpt_incr_max(sp, incrs); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_incr_max); + +struct host1x_syncpt* wrap_host1x_syncpt_alloc(struct host1x *host, + unsigned long flags, + const char *name) +{ + return host1x_api_table.host1x_syncpt_alloc(host, flags, name); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_alloc); + +void wrap_host1x_syncpt_put(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_put(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_put); + +u32 wrap_host1x_syncpt_id(struct host1x_syncpt *sp) +{ + return host1x_api_table.host1x_syncpt_id(sp); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_id); + +int wrap_host1x_syncpt_wait_ts(struct host1x_syncpt *sp, + u32 thresh, long timeout, u32 *value, ktime_t *ts) +{ + return host1x_api_table.host1x_syncpt_wait_ts(sp, thresh, timeout, value, ts); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_wait_ts); + +int wrap_host1x_syncpt_wait(struct host1x_syncpt *sp, + u32 thresh, long timeout, u32 *value) +{ + return host1x_api_table.host1x_syncpt_wait(sp, thresh, timeout, value); +} +EXPORT_SYMBOL(wrap_host1x_syncpt_wait); + +// nvhost.c +void wrap_host1x_writel(struct platform_device *pdev, u32 r, u32 v) +{ + return host1x_api_table.host1x_writel(pdev, r, v); +} +EXPORT_SYMBOL(wrap_host1x_writel); + +struct platform_device* wrap_nvhost_get_default_device(void) +{ + return host1x_api_table.nvhost_get_default_device(); +} +EXPORT_SYMBOL(wrap_nvhost_get_default_device); + +struct host1x* wrap_nvhost_get_host1x(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_get_host1x(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_get_host1x); + +int wrap_nvhost_client_device_get_resources(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_client_device_get_resources(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_client_device_get_resources); + +int wrap_nvhost_client_device_init(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_client_device_init(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_client_device_init); + +int wrap_nvhost_client_device_release(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_client_device_release(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_client_device_release); + +u32 wrap_nvhost_get_syncpt_host_managed(struct platform_device *pdev, + u32 param, const char *syncpt_name) +{ + return host1x_api_table.nvhost_get_syncpt_host_managed(pdev, param, syncpt_name); +} +EXPORT_SYMBOL(wrap_nvhost_get_syncpt_host_managed); + +u32 wrap_nvhost_get_syncpt_client_managed(struct platform_device *pdev, + const char *syncpt_name) +{ + return host1x_api_table.nvhost_get_syncpt_client_managed(pdev, syncpt_name); +} +EXPORT_SYMBOL(wrap_nvhost_get_syncpt_client_managed); + +u32 wrap_nvhost_get_syncpt_gpu_managed(struct platform_device *pdev, + const char *syncpt_name) +{ + return host1x_api_table.nvhost_get_syncpt_gpu_managed(pdev, syncpt_name); +} +EXPORT_SYMBOL(wrap_nvhost_get_syncpt_gpu_managed); + +void wrap_nvhost_syncpt_put_ref_ext(struct platform_device *pdev, u32 id) +{ + return host1x_api_table.nvhost_syncpt_put_ref_ext(pdev, id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_put_ref_ext); + +bool wrap_nvhost_syncpt_is_valid_pt_ext(struct platform_device *pdev, u32 id) +{ + return host1x_api_table.nvhost_syncpt_is_valid_pt_ext(pdev, id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_is_valid_pt_ext); + +int wrap_nvhost_syncpt_is_expired_ext(struct platform_device *pdev, u32 id, + u32 thresh) +{ + return host1x_api_table.nvhost_syncpt_is_expired_ext(pdev, id, thresh); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_is_expired_ext); + +void wrap_nvhost_syncpt_set_min_update(struct platform_device *pdev, u32 id, u32 val) +{ + return host1x_api_table.nvhost_syncpt_set_min_update(pdev, id, val); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_set_min_update); + +int wrap_nvhost_syncpt_read_ext_check(struct platform_device *pdev, u32 id, u32 *val) +{ + return host1x_api_table.nvhost_syncpt_read_ext_check(pdev, id, val); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_read_ext_check); + +u32 wrap_nvhost_syncpt_read_maxval(struct platform_device *pdev, u32 id) +{ + return host1x_api_table.nvhost_syncpt_read_maxval(pdev, id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_read_maxval); + +u32 wrap_nvhost_syncpt_incr_max_ext(struct platform_device *pdev, u32 id, u32 incrs) +{ + return host1x_api_table.nvhost_syncpt_incr_max_ext(pdev, id, incrs); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_incr_max_ext); + +u32 wrap_nvhost_syncpt_unit_interface_get_byte_offset_ext(struct platform_device *pdev, + u32 syncpt_id) +{ + return host1x_api_table.nvhost_syncpt_unit_interface_get_byte_offset_ext(pdev, syncpt_id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_unit_interface_get_byte_offset_ext); + +u32 wrap_nvhost_syncpt_unit_interface_get_byte_offset(u32 syncpt_id) +{ + return host1x_api_table.nvhost_syncpt_unit_interface_get_byte_offset(syncpt_id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_unit_interface_get_byte_offset); + +int wrap_nvhost_syncpt_unit_interface_get_aperture(struct platform_device *pdev, + u64 *base, size_t *size) +{ + return host1x_api_table.nvhost_syncpt_unit_interface_get_aperture(pdev, base, size); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_unit_interface_get_aperture); + +int wrap_nvhost_syncpt_unit_interface_init(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_syncpt_unit_interface_init(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_unit_interface_init); + +void wrap_nvhost_syncpt_unit_interface_deinit(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_syncpt_unit_interface_deinit(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_unit_interface_deinit); + +dma_addr_t wrap_nvhost_syncpt_address(struct platform_device *pdev, u32 id) +{ + return host1x_api_table.nvhost_syncpt_address(pdev, id); +} +EXPORT_SYMBOL(wrap_nvhost_syncpt_address); + +int wrap_nvhost_intr_register_notifier(struct platform_device *pdev, + u32 id, u32 thresh, + void (*callback)(void *data), + void *private_data) +{ + return host1x_api_table.nvhost_intr_register_notifier(pdev, + id, thresh, + callback, + private_data); +} +EXPORT_SYMBOL(wrap_nvhost_intr_register_notifier); + +int wrap_nvhost_module_init(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_module_init(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_module_init); + +void wrap_nvhost_module_deinit(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_module_deinit(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_module_deinit); + +void wrap_nvhost_module_reset(struct platform_device *pdev, bool reboot) +{ + return host1x_api_table.nvhost_module_reset(pdev, reboot); +} +EXPORT_SYMBOL(wrap_nvhost_module_reset); + +int wrap_nvhost_module_busy(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_module_busy(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_module_busy); + +inline void wrap_nvhost_module_idle(struct platform_device *pdev) +{ + return host1x_api_table.nvhost_module_idle(pdev); +} +EXPORT_SYMBOL(wrap_nvhost_module_idle); + +void wrap_nvhost_module_idle_mult(struct platform_device *pdev, int refs) +{ + return host1x_api_table.nvhost_module_idle_mult(pdev, refs); +} +EXPORT_SYMBOL(wrap_nvhost_module_idle_mult); diff --git a/drivers/gpu/host1x-fence/include/linux/host1x-dispatch.h b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch.h new file mode 100644 index 00000000..64991724 --- /dev/null +++ b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch.h @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: GPL-2.0-only + */ +#ifndef __HOST1X_DISPATCH_H +#define __HOST1X_DISPATCH_H +#include + +// fence.c +#define host1x_fence_create wrap_host1x_fence_create +#define host1x_fence_extract wrap_host1x_fence_extract +#define host1x_fence_cancel wrap_host1x_fence_cancel +#define host1x_syncpt_fence_scan wrap_host1x_syncpt_fence_scan +// Syncpt.c +#define host1x_get_dma_mask wrap_host1x_get_dma_mask +#define host1x_syncpt_get wrap_host1x_syncpt_get +#define host1x_syncpt_get_by_id wrap_host1x_syncpt_get_by_id +#define host1x_syncpt_get_by_id_noref wrap_host1x_syncpt_get_by_id_noref +#define host1x_syncpt_read wrap_host1x_syncpt_read +#define host1x_syncpt_read_min wrap_host1x_syncpt_read_min +#define host1x_syncpt_read_max wrap_host1x_syncpt_read_max +#define host1x_syncpt_incr wrap_host1x_syncpt_incr +#define host1x_syncpt_incr_max wrap_host1x_syncpt_incr_max +#define host1x_syncpt_alloc wrap_host1x_syncpt_alloc +#define host1x_syncpt_put wrap_host1x_syncpt_put +#define host1x_syncpt_id wrap_host1x_syncpt_id +#define host1x_syncpt_wait_ts wrap_host1x_syncpt_wait_ts +#define host1x_syncpt_wait wrap_host1x_syncpt_wait +#define host1x_fence_get_node wrap_host1x_fence_get_node +//nvhost.h + +#define host1x_writel wrap_host1x_writel +#define nvhost_get_default_device wrap_nvhost_get_default_device +#define nvhost_get_host1x wrap_nvhost_get_host1x +#define nvhost_client_device_get_resources wrap_nvhost_client_device_get_resources +#define nvhost_client_device_init wrap_nvhost_client_device_init +#define nvhost_client_device_release wrap_nvhost_client_device_release +#define nvhost_get_syncpt_host_managed wrap_nvhost_get_syncpt_host_managed +#define nvhost_get_syncpt_client_managed wrap_nvhost_get_syncpt_client_managed +#define nvhost_get_syncpt_gpu_managed wrap_nvhost_get_syncpt_gpu_managed +#define nvhost_syncpt_put_ref_ext wrap_nvhost_syncpt_put_ref_ext +#define nvhost_syncpt_is_valid_pt_ext wrap_nvhost_syncpt_is_valid_pt_ext +#define nvhost_syncpt_is_expired_ext wrap_nvhost_syncpt_is_expired_ext +#define nvhost_syncpt_set_min_update wrap_nvhost_syncpt_set_min_update +#define nvhost_syncpt_read_ext_check wrap_nvhost_syncpt_read_ext_check +#define nvhost_syncpt_read_maxval wrap_nvhost_syncpt_read_maxval +#define nvhost_syncpt_incr_max_ext wrap_nvhost_syncpt_incr_max_ext +#define nvhost_syncpt_unit_interface_get_byte_offset_ext wrap_nvhost_syncpt_unit_interface_get_byte_offset_ext +#define nvhost_syncpt_unit_interface_get_byte_offset wrap_nvhost_syncpt_unit_interface_get_byte_offset +#define nvhost_syncpt_unit_interface_get_aperture wrap_nvhost_syncpt_unit_interface_get_aperture +#define nvhost_syncpt_unit_interface_init wrap_nvhost_syncpt_unit_interface_init +#define nvhost_syncpt_unit_interface_deinit wrap_nvhost_syncpt_unit_interface_deinit +#define nvhost_syncpt_address wrap_nvhost_syncpt_address +#define nvhost_intr_register_notifier wrap_nvhost_intr_register_notifier +#define nvhost_module_init wrap_nvhost_module_init +#define nvhost_module_deinit wrap_nvhost_module_deinit +#define nvhost_module_reset wrap_nvhost_module_reset +#define nvhost_module_busy wrap_nvhost_module_busy +#define nvhost_module_idle wrap_nvhost_module_idle +#define nvhost_module_idle_mult wrap_nvhost_module_idle_mult + +#endif /*__HOST1X_DISPATCH_H */ \ No newline at end of file diff --git a/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_api.h b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_api.h new file mode 100644 index 00000000..c55f3955 --- /dev/null +++ b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_api.h @@ -0,0 +1,150 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: GPL-2.0-only + */ +#ifndef __HOST1X_DISPATCH_API_H +#define __HOST1X_DISPATCH_API_H +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HOST1X_SYNCPT_CLIENT_MANAGED (1 << 0) +#define HOST1X_SYNCPT_HAS_BASE (1 << 1) +#define HOST1X_SYNCPT_GPU (1 << 2) + +#define HOST1X_GLOBAL_TO_LOCAL_SYNCPOINT(global_syncpoint_id) \ + (global_syncpoint_id & 0xFFFFFF) + +#define HOST1X_INSTANCE_NUM_FROM_GLOBAL_SYNCPOINT(global_syncpoint_id) \ + ((global_syncpoint_id & 0xFF000000) >> 24) + +#define HOST1X_LOCAL_TO_GLOBAL_SYNCPOINT(local_syncpoint_id, instance) \ + ((instance << 24) | (local_syncpoint_id)) + +#define HOST1X_EMU_EXPORT_CALL(...) wrap_ ## __VA_ARGS__ + +struct host1x; +struct host1x_syncpt; + +// fence.c +struct dma_fence* wrap_host1x_fence_create(struct host1x_syncpt *sp, + u32 threshold, + bool timeout); + +int wrap_host1x_fence_extract(struct dma_fence *dfence, u32 *id, u32 *threshold); + +void wrap_host1x_fence_cancel(struct dma_fence *dfence); + +void wrap_host1x_syncpt_fence_scan(struct host1x_syncpt *sp); + +// Syncpt.c +u64 wrap_host1x_get_dma_mask(struct host1x *host1x); + +struct host1x_syncpt* wrap_host1x_syncpt_get( + struct host1x_syncpt *sp); + +struct host1x_syncpt* wrap_host1x_syncpt_get_by_id( + struct host1x *host, unsigned int id); + +struct host1x_syncpt* wrap_host1x_syncpt_get_by_id_noref(struct host1x *host, unsigned int id); + +u32 wrap_host1x_syncpt_read(struct host1x_syncpt *sp); + +u32 wrap_host1x_syncpt_read_min(struct host1x_syncpt *sp); + +u32 wrap_host1x_syncpt_read_max(struct host1x_syncpt *sp); + +int wrap_host1x_syncpt_incr(struct host1x_syncpt *sp); + +u32 wrap_host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); + +struct host1x_syncpt* wrap_host1x_syncpt_alloc(struct host1x *host, + unsigned long flags, + const char *name); + +void wrap_host1x_syncpt_put(struct host1x_syncpt *sp); + +u32 wrap_host1x_syncpt_id(struct host1x_syncpt *sp); + +int wrap_host1x_syncpt_wait_ts(struct host1x_syncpt *sp, + u32 thresh, long timeout, u32 *value, ktime_t *ts); + +int wrap_host1x_syncpt_wait(struct host1x_syncpt *sp, + u32 thresh, long timeout, u32 *value); + +int wrap_host1x_fence_get_node(struct dma_fence *fence); + +//nvhost.h +void wrap_host1x_writel(struct platform_device *pdev, u32 r, u32 v); + +struct platform_device* wrap_nvhost_get_default_device(void); + +struct host1x* wrap_nvhost_get_host1x(struct platform_device *pdev); + +int wrap_nvhost_client_device_get_resources(struct platform_device *pdev); + +int wrap_nvhost_client_device_init(struct platform_device *pdev); + +int wrap_nvhost_client_device_release(struct platform_device *pdev); + +u32 wrap_nvhost_get_syncpt_host_managed(struct platform_device *pdev, + u32 param, const char *syncpt_name); + +u32 wrap_nvhost_get_syncpt_client_managed(struct platform_device *pdev, + const char *syncpt_name); + +u32 wrap_nvhost_get_syncpt_gpu_managed(struct platform_device *pdev, + const char *syncpt_name); + +void wrap_nvhost_syncpt_put_ref_ext(struct platform_device *pdev, u32 id); + +bool wrap_nvhost_syncpt_is_valid_pt_ext(struct platform_device *pdev, u32 id); + +int wrap_nvhost_syncpt_is_expired_ext(struct platform_device *pdev, u32 id, + u32 thresh); + +void wrap_nvhost_syncpt_set_min_update(struct platform_device *pdev, u32 id, u32 val); + +int wrap_nvhost_syncpt_read_ext_check(struct platform_device *pdev, u32 id, u32 *val); + +u32 wrap_nvhost_syncpt_read_maxval(struct platform_device *pdev, u32 id); + +u32 wrap_nvhost_syncpt_incr_max_ext(struct platform_device *pdev, u32 id, u32 incrs); + +u32 wrap_nvhost_syncpt_unit_interface_get_byte_offset_ext(struct platform_device *pdev, + u32 syncpt_id); + +u32 wrap_nvhost_syncpt_unit_interface_get_byte_offset(u32 syncpt_id); + +int wrap_nvhost_syncpt_unit_interface_get_aperture(struct platform_device *pdev, + u64 *base, size_t *size); + +int wrap_nvhost_syncpt_unit_interface_init(struct platform_device *pdev); + +void wrap_nvhost_syncpt_unit_interface_deinit(struct platform_device *pdev); + +dma_addr_t wrap_nvhost_syncpt_address(struct platform_device *pdev, u32 id); + +int wrap_nvhost_intr_register_notifier(struct platform_device *pdev, + u32 id, u32 thresh, + void (*callback)(void *data), + void *private_data); + +int wrap_nvhost_module_init(struct platform_device *pdev); + +void wrap_nvhost_module_deinit(struct platform_device *pdev); + +void wrap_nvhost_module_reset(struct platform_device *pdev, bool reboot); + +int wrap_nvhost_module_busy(struct platform_device *dev); + +inline void wrap_nvhost_module_idle(struct platform_device *pdev); + +void wrap_nvhost_module_idle_mult(struct platform_device *pdev, int refs); +#endif /*__HOST1X_DISPATCH_API_H */ \ No newline at end of file diff --git a/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_type.h b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_type.h new file mode 100644 index 00000000..a0bad12e --- /dev/null +++ b/drivers/gpu/host1x-fence/include/linux/host1x-dispatch_type.h @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: GPL-2.0-only + */ +#ifndef __HOST1X_DISPATCH_TYPE_H +#define __HOST1X_DISPATCH_TYPE_H +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct host1x; +struct host1x_syncpt; + +struct host1x_interface_ops { +//host1x.h Interface +struct dma_fence* (*host1x_fence_create)(struct host1x_syncpt *sp, u32 threshold,bool timeout); +int (*host1x_fence_extract)(struct dma_fence *fence, u32 *id, u32 *threshold); +void (*host1x_fence_cancel)(struct dma_fence *fence); +int (*host1x_fence_get_node)(struct dma_fence *fence); +u64 (*host1x_get_dma_mask)(struct host1x *host1x); +struct host1x_syncpt* (*host1x_syncpt_get)(struct host1x_syncpt *sp); +struct host1x_syncpt* (*host1x_syncpt_get_by_id)(struct host1x *host, u32 id); +struct host1x_syncpt* (*host1x_syncpt_get_by_id_noref)(struct host1x *host, u32 id); +u32 (*host1x_syncpt_read)(struct host1x_syncpt *sp); +u32 (*host1x_syncpt_read_min)(struct host1x_syncpt *sp); +u32 (*host1x_syncpt_read_max)(struct host1x_syncpt *sp); +int (*host1x_syncpt_incr)(struct host1x_syncpt *sp); +u32 (*host1x_syncpt_incr_max)(struct host1x_syncpt *sp, u32 incrs); +struct host1x_syncpt* (*host1x_syncpt_alloc)(struct host1x *host, unsigned long flags, const char *name); +void (*host1x_syncpt_put)(struct host1x_syncpt *sp); +u32 (*host1x_syncpt_id)(struct host1x_syncpt *sp); +int (*host1x_syncpt_wait_ts)(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value, ktime_t *ts); +int (*host1x_syncpt_wait)(struct host1x_syncpt *sp, u32 thresh, long timeout,u32 *value); + +//nvhost.h Interface +void (*host1x_writel)(struct platform_device *pdev, u32 r, u32 v); +struct platform_device* (*nvhost_get_default_device)(void); +struct host1x* (*nvhost_get_host1x)(struct platform_device *pdev); +int (*nvhost_client_device_get_resources)(struct platform_device *pdev); +int (*nvhost_client_device_init)(struct platform_device *pdev); +int (*nvhost_client_device_release)(struct platform_device *pdev); +u32 (*nvhost_get_syncpt_host_managed)(struct platform_device *pdev, u32 param, const char *syncpt_name); +u32 (*nvhost_get_syncpt_client_managed)(struct platform_device *pdev,const char *syncpt_name); +u32 (*nvhost_get_syncpt_gpu_managed)(struct platform_device *pdev,const char *syncpt_name); +void (*nvhost_syncpt_put_ref_ext)(struct platform_device *pdev, u32 id); +bool (*nvhost_syncpt_is_valid_pt_ext)(struct platform_device *pdev, u32 id); +int (*nvhost_syncpt_is_expired_ext)(struct platform_device *pdev, u32 id, u32 thresh); +void (*nvhost_syncpt_set_min_update)(struct platform_device *pdev, u32 id, u32 val); +int (*nvhost_syncpt_read_ext_check)(struct platform_device *pdev, u32 id, u32 *val); +u32 (*nvhost_syncpt_read_maxval)(struct platform_device *pdev, u32 id); +u32 (*nvhost_syncpt_incr_max_ext)(struct platform_device *pdev, u32 id, u32 incrs); +u32 (*nvhost_syncpt_unit_interface_get_byte_offset_ext)(struct platform_device *pdev,u32 syncpt_id); +u32 (*nvhost_syncpt_unit_interface_get_byte_offset)(u32 syncpt_id); +int (*nvhost_syncpt_unit_interface_get_aperture)(struct platform_device *pdev, u64 *base, size_t *size); +int (*nvhost_syncpt_unit_interface_init)(struct platform_device *pdev); +void (*nvhost_syncpt_unit_interface_deinit)(struct platform_device *pdev); +dma_addr_t (*nvhost_syncpt_address)(struct platform_device *pdev, u32 id); +int (*nvhost_intr_register_notifier)(struct platform_device *pdev,u32 id, u32 thresh,void (*callback)(void *data),void *private_data); +int (*nvhost_module_init)(struct platform_device *pdev); +void (*nvhost_module_deinit)(struct platform_device *pdev); +void (*nvhost_module_reset)(struct platform_device *pdev, bool reboot); +int (*nvhost_module_busy)(struct platform_device *dev); +void (*nvhost_module_idle)(struct platform_device *pdev); +void (*nvhost_module_idle_mult)(struct platform_device *pdev, int refs); +}; + +bool host1x_wrapper_register_interface(struct host1x_interface_ops *host1x_hw_ops); + +#endif /*__HOST1X_DISPATCH_API_H */ \ No newline at end of file