mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
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 <amitabhd@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3267144 Reviewed-by: Raghavendra Vishnu Kumar <rvk@nvidia.com> Reviewed-by: Sanif Veeras <sveeras@nvidia.com> GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-by: Leslin Varghese <lvarghese@nvidia.com>
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# 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
|
# Enable below flag for hypervisor build configuration
|
||||||
ifeq ($(NV_BUILD_CONFIGURATION_EMU_SYNCPT),1)
|
ifeq ($(NV_BUILD_CONFIGURATION_EMU_SYNCPT),1)
|
||||||
ccflags-y += -DHOST1X_EMU_HYPERVISOR
|
ccflags-y += -DHOST1X_EMU_HYPERVISOR
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
#Enable Tasklet based fence scanning in SyncpointIncr
|
||||||
|
#ccflags-y += -DHOST1X_EMU_SYNC_INC_TASKLET
|
||||||
|
|
||||||
ifeq ($(NV_BUILD_CONFIGURATION_EXPOSING_T26X), 1)
|
ifeq ($(NV_BUILD_CONFIGURATION_EXPOSING_T26X), 1)
|
||||||
LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-emu/include
|
LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x-emu/include
|
||||||
# Enable for verification in VDK. Below allow Emulated Syncpoint driver
|
# Enable for verification in VDK. Below allow Emulated Syncpoint driver
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -188,3 +186,9 @@ HOST1X_EMU_EXPORT_DECL(void, host1x_fence_cancel(struct dma_fence *dfence))
|
|||||||
flush_delayed_work(&sf->timeout_work);
|
flush_delayed_work(&sf->timeout_work);
|
||||||
}
|
}
|
||||||
HOST1X_EMU_EXPORT_SYMBOL(host1x_fence_cancel);
|
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);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#ifndef __LINUX_HOST1X_H
|
#ifndef __LINUX_HOST1X_H
|
||||||
#define __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,
|
HOST1X_EMU_EXPORT_DECL(u32, host1x_syncpt_incr_max(struct host1x_syncpt *sp,
|
||||||
u32 incrs));
|
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,
|
HOST1X_EMU_EXPORT_DECL(int, host1x_syncpt_wait_ts(struct host1x_syncpt *sp,
|
||||||
u32 thresh, long timeout, u32 *value, ktime_t *ts));
|
u32 thresh, long timeout, u32 *value, ktime_t *ts));
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#ifndef __HOST1X_EMU_SYMMBOL_H
|
#ifndef __HOST1X_EMU_SYMMBOL_H
|
||||||
#define __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_DECL(ret, ...) ret __VA_ARGS__
|
||||||
#define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(f)
|
#define HOST1X_EMU_EXPORT_SYMBOL(f) EXPORT_SYMBOL(f)
|
||||||
#endif
|
#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*/
|
#endif /*__HOST1X_EMU_SYMMBOL_H*/
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
#include "fence.h"
|
#include "fence.h"
|
||||||
#include "poll.h"
|
#include "poll.h"
|
||||||
@@ -56,29 +54,11 @@ static void host1x_pool_timeout_handler(struct work_struct *work)
|
|||||||
struct host1x_syncpt *sp;
|
struct host1x_syncpt *sp;
|
||||||
struct host1x_syncpt *tmp_spt;
|
struct host1x_syncpt *tmp_spt;
|
||||||
struct host1x *host = pool->host;
|
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) {
|
list_for_each_entry_safe(sp, tmp_spt, &pool->syncpt_list.list, list) {
|
||||||
struct host1x_syncpt_fence *fence, *tmp;
|
host1x_poll_irq_check_syncpt_fence(sp);
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Optimize pool polling mechanism
|
* TODO: Optimize pool polling mechanism
|
||||||
*/
|
*/
|
||||||
@@ -116,12 +96,33 @@ int host1x_poll_init(struct host1x *host)
|
|||||||
INIT_LIST_HEAD(&syncpt->list);
|
INIT_LIST_HEAD(&syncpt->list);
|
||||||
|
|
||||||
/* Add syncpoint to pool 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;
|
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)
|
void host1x_poll_start(struct host1x *host)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#ifndef __HOST1X_EMU_POLL_H
|
#ifndef __HOST1X_EMU_POLL_H
|
||||||
#define __HOST1X_EMU_POLL_H
|
#define __HOST1X_EMU_POLL_H
|
||||||
|
|
||||||
@@ -10,6 +8,7 @@
|
|||||||
#include <linux/timekeeping.h>
|
#include <linux/timekeeping.h>
|
||||||
|
|
||||||
struct host1x;
|
struct host1x;
|
||||||
|
struct host1x_syncpt;
|
||||||
struct host1x_syncpt_fence;
|
struct host1x_syncpt_fence;
|
||||||
|
|
||||||
struct host1x_fence_list {
|
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);
|
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
|
#endif
|
||||||
|
|||||||
@@ -1,17 +1,33 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
*/
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/dma-fence.h>
|
#include <linux/dma-fence.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/timekeeping.h>
|
#include <linux/timekeeping.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
#include "syncpt.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)
|
static void syncpt_release(struct kref *ref)
|
||||||
{
|
{
|
||||||
struct host1x_syncpt *sp = container_of(ref, struct host1x_syncpt, 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))
|
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);
|
HOST1X_EMU_EXPORT_SYMBOL(host1x_syncpt_incr);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user