gpu: nvgpu: add channel_user_syncpt

Refactor user managed syncpoints out of the channel sync infrastructure
that deals with jobs submitted via the kernel api. The user syncpt only
needs to expose the id and gpu address of the reserved syncpoint. None
of the rest (fences, priv cmdbufs) is needed for that, so it hasn't been
ideal to couple with the user-allocated syncpts.

With user syncpts now provided by channel_user_syncpt, remove the
user_managed flag from the kernel sync api.

This allows moving all the kernel submit sync code to be conditionally
compiled in only when needed, and separates the user sync functionality
in a more clear way from the rest with a minimal API.

[this is squashed with commit 5111caea601a (gpu: nvgpu: guard user
syncpt with nvhost config) from
https://git-master.nvidia.com/r/c/linux-nvgpu/+/2325009]

Jira NVGPU-4548

Change-Id: I99259fc9cbd30bbd478ed86acffcce12768502d3
Signed-off-by: Konsta Hölttä <kholtta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2321768
(cherry picked from commit 1095ad353f5f1cf7ca180d0701bc02a607404f5e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2319629
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Konsta Hölttä
2020-03-26 11:53:59 +02:00
committed by Alex Waterman
parent b813adbf49
commit 4f80c6b8a9
21 changed files with 380 additions and 191 deletions

View File

@@ -955,6 +955,11 @@ sync:
safe: no
sources: [ common/sync/channel_sync_semaphore.c,
include/nvgpu/channel_sync_semaphore.h ]
user_syncpt:
safe: yes
sources: [ common/sync/channel_user_syncpt.c,
common/sync/channel_user_syncpt_priv.h,
include/nvgpu/channel_user_syncpt.h ]
power_features:
owner: Seema K
children:

View File

@@ -454,7 +454,8 @@ nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
os/linux/nvhost.o \
hal/sync/syncpt_cmdbuf_gk20a.o \
hal/sync/syncpt_cmdbuf_gv11b.o \
hal/sync/syncpt_cmdbuf_gv11b_fusa.o
hal/sync/syncpt_cmdbuf_gv11b_fusa.o \
common/sync/channel_user_syncpt.o
nvgpu-$(CONFIG_NVGPU_GR_VIRTUALIZATION) += \
os/linux/vgpu/platform_vgpu_tegra.o \

View File

@@ -134,9 +134,8 @@ srcs += common/utils/enabled.c \
common/acr/acr_bootstrap.c \
common/acr/acr_sw_gv11b.c \
common/ptimer/ptimer.c \
common/sync/channel_sync.c \
common/sync/channel_sync_syncpt.c \
common/power_features/cg/cg.c \
common/sync/channel_user_syncpt.c \
common/fifo/preempt.c \
common/fifo/channel.c \
common/fifo/fifo.c \
@@ -387,7 +386,9 @@ endif
endif
ifeq ($(CONFIG_NVGPU_KERNEL_MODE_SUBMIT),1)
srcs += common/fifo/submit.c
srcs += common/fifo/submit.c \
common/sync/channel_sync.c \
common/sync/channel_sync_syncpt.c
endif
ifeq ($(CONFIG_NVGPU_SW_SEMAPHORE),1)

View File

@@ -51,6 +51,7 @@
#include <nvgpu/channel.h>
#include <nvgpu/channel_sync.h>
#include <nvgpu/channel_sync_syncpt.h>
#include <nvgpu/channel_user_syncpt.h>
#include <nvgpu/runlist.h>
#include <nvgpu/fifo/userd.h>
#include <nvgpu/fence.h>
@@ -194,9 +195,12 @@ void nvgpu_channel_abort_clean_up(struct nvgpu_channel *ch)
if (ch->sync != NULL) {
nvgpu_channel_sync_set_min_eq_max(ch->sync);
}
#ifdef CONFIG_TEGRA_GK20A_NVHOST
if (ch->user_sync != NULL) {
nvgpu_channel_sync_set_safe_state(ch->user_sync);
nvgpu_channel_user_syncpt_set_safe_state(ch->user_sync);
}
#endif
nvgpu_mutex_release(&ch->sync_lock);
nvgpu_mutex_release(&ch->joblist.cleanup_lock);
@@ -728,7 +732,7 @@ static int channel_setup_kernelmode(struct nvgpu_channel *c,
if (g->aggressive_sync_destroy_thresh == 0U) {
nvgpu_mutex_acquire(&c->sync_lock);
c->sync = nvgpu_channel_sync_create(c, false);
c->sync = nvgpu_channel_sync_create(c);
if (c->sync == NULL) {
err = -ENOMEM;
nvgpu_mutex_release(&c->sync_lock);
@@ -1502,7 +1506,7 @@ void nvgpu_channel_abort_clean_up(struct nvgpu_channel *ch)
/* ensure no fences are pending */
nvgpu_mutex_acquire(&ch->sync_lock);
if (ch->user_sync != NULL) {
nvgpu_channel_sync_set_safe_state(ch->user_sync);
nvgpu_channel_user_syncpt_set_safe_state(ch->user_sync);
}
nvgpu_mutex_release(&ch->sync_lock);
}
@@ -1627,20 +1631,21 @@ static void channel_free_invoke_deferred_engine_reset(struct nvgpu_channel *ch)
static void channel_free_invoke_sync_destroy(struct nvgpu_channel *ch)
{
#ifdef CONFIG_TEGRA_GK20A_NVHOST
nvgpu_mutex_acquire(&ch->sync_lock);
if (ch->user_sync != NULL) {
/*
* Set user managed syncpoint to safe state
* But it's already done if channel is recovered
*/
if (nvgpu_channel_check_unserviceable(ch)) {
nvgpu_channel_sync_destroy(ch->user_sync, false);
} else {
nvgpu_channel_sync_destroy(ch->user_sync, true);
if (!nvgpu_channel_check_unserviceable(ch)) {
nvgpu_channel_user_syncpt_set_safe_state(ch->user_sync);
}
nvgpu_channel_user_syncpt_destroy(ch->user_sync);
ch->user_sync = NULL;
}
nvgpu_mutex_release(&ch->sync_lock);
#endif
}
static void channel_free_unlink_debug_session(struct nvgpu_channel *ch)

View File

@@ -62,7 +62,7 @@ static int nvgpu_submit_prepare_syncs(struct nvgpu_channel *c,
if (g->aggressive_sync_destroy_thresh != 0U) {
nvgpu_mutex_acquire(&c->sync_lock);
if (c->sync == NULL) {
c->sync = nvgpu_channel_sync_create(c, false);
c->sync = nvgpu_channel_sync_create(c);
if (c->sync == NULL) {
err = -ENOMEM;
goto fail;

View File

@@ -767,12 +767,18 @@ int nvgpu_init_gpu_characteristics(struct gk20a *g)
true);
/*
* Sync framework requires deferred job cleanup, wrapping syncs in FDs,
* and other heavy stuff, which prevents deterministic submits. This is
* supported otherwise, provided that the user doesn't request anything
* that depends on deferred cleanup.
* Sync framework is needed when we don't have syncpoint support
* because we don't have a means to expose raw gpu semas in a way
* similar to raw syncpts. Use of the framework requires heavy stuff
* like deferred job cleanup and wrapping syncs in FDs which prevents
* deterministic submits. This is supported otherwise, provided that
* the user doesn't request anything that depends on deferred cleanup.
*
* Note that userspace expects this to be set for usermode submits
* (even if kernel-mode submits aren't enabled where full deterministic
* features matter).
*/
if (!nvgpu_channel_sync_needs_os_fence_framework(g)) {
if (nvgpu_has_syncpoints(g)) {
nvgpu_set_enabled(g,
NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_FULL,
true);

View File

@@ -39,14 +39,13 @@
#include "channel_sync_priv.h"
struct nvgpu_channel_sync *nvgpu_channel_sync_create(struct nvgpu_channel *c,
bool user_managed)
struct nvgpu_channel_sync *nvgpu_channel_sync_create(struct nvgpu_channel *c)
{
if (nvgpu_has_syncpoints(c->g)) {
return nvgpu_channel_sync_syncpt_create(c, user_managed);
return nvgpu_channel_sync_syncpt_create(c);
} else {
#ifdef CONFIG_NVGPU_SW_SEMAPHORE
return nvgpu_channel_sync_semaphore_create(c, user_managed);
return nvgpu_channel_sync_semaphore_create(c);
#else
return NULL;
#endif
@@ -58,7 +57,6 @@ bool nvgpu_channel_sync_needs_os_fence_framework(struct gk20a *g)
return !nvgpu_has_syncpoints(g);
}
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
int nvgpu_channel_sync_wait_fence_fd(struct nvgpu_channel_sync *s, int fd,
struct priv_cmd_entry *entry, u32 max_wait_cmds)
{
@@ -96,8 +94,6 @@ bool nvgpu_channel_sync_put_ref_and_check(struct nvgpu_channel_sync *s)
return nvgpu_atomic_dec_and_test(&s->refcount);
}
#endif /* CONFIG_NVGPU_KERNEL_MODE_SUBMIT */
void nvgpu_channel_sync_set_safe_state(struct nvgpu_channel_sync *s)
{
s->ops->set_safe_state(s);

View File

@@ -26,6 +26,13 @@
#ifndef NVGPU_CHANNEL_SYNC_PRIV_H
#define NVGPU_CHANNEL_SYNC_PRIV_H
/*
* These APIs are used for job synchronization that we know about in the
* driver. If submits happen in userspace only, none of this will be needed and
* won't be included. This is here just to double check for now.
*/
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
#include <nvgpu/atomic.h>
#include <nvgpu/types.h>
@@ -47,7 +54,6 @@ struct nvgpu_channel_sync {
* instead use the public APIs starting with nvgpu_channel_sync_*
*/
struct nvgpu_channel_sync_ops {
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
int (*wait_fence_raw)(struct nvgpu_channel_sync *s, u32 id, u32 thresh,
struct priv_cmd_entry *entry);
@@ -69,11 +75,12 @@ struct nvgpu_channel_sync_ops {
bool register_irq);
void (*set_min_eq_max)(struct nvgpu_channel_sync *s);
#endif
void (*set_safe_state)(struct nvgpu_channel_sync *s);
void (*destroy)(struct nvgpu_channel_sync *s);
};
#endif /* CONFIG_NVGPU_KERNEL_MODE_SUBMIT */
#endif /* NVGPU_CHANNEL_SYNC_PRIV_H */

View File

@@ -341,8 +341,7 @@ struct nvgpu_channel_sync_semaphore *
}
struct nvgpu_channel_sync *
nvgpu_channel_sync_semaphore_create(
struct nvgpu_channel *c, bool user_managed)
nvgpu_channel_sync_semaphore_create(struct nvgpu_channel *c)
{
struct nvgpu_channel_sync_semaphore *sema;
struct gk20a *g = c->g;

View File

@@ -55,7 +55,6 @@ nvgpu_channel_sync_syncpt_from_base(struct nvgpu_channel_sync *base)
offsetof(struct nvgpu_channel_sync_syncpt, base));
}
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
static int channel_sync_syncpt_gen_wait_cmd(struct nvgpu_channel *c,
u32 id, u32 thresh, struct priv_cmd_entry *wait_cmd,
u32 wait_cmd_size, u32 pos, bool preallocated)
@@ -307,8 +306,6 @@ static void channel_sync_syncpt_set_min_eq_max(struct nvgpu_channel_sync *s)
nvgpu_nvhost_syncpt_set_min_eq_max_ext(sp->nvhost, sp->id);
}
#endif /* CONFIG_NVGPU_KERNEL_MODE_SUBMIT */
static void channel_sync_syncpt_set_safe_state(struct nvgpu_channel_sync *s)
{
struct nvgpu_channel_sync_syncpt *sp =
@@ -350,12 +347,10 @@ u64 nvgpu_channel_sync_get_syncpt_address(struct nvgpu_channel_sync_syncpt *s)
}
static const struct nvgpu_channel_sync_ops channel_sync_syncpt_ops = {
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
.wait_fence_fd = channel_sync_syncpt_wait_fd,
.incr = channel_sync_syncpt_incr,
.incr_user = channel_sync_syncpt_incr_user,
.set_min_eq_max = channel_sync_syncpt_set_min_eq_max,
#endif
.set_safe_state = channel_sync_syncpt_set_safe_state,
.destroy = channel_sync_syncpt_destroy,
};
@@ -373,7 +368,7 @@ nvgpu_channel_sync_to_syncpt(struct nvgpu_channel_sync *sync)
}
struct nvgpu_channel_sync *
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c, bool user_managed)
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c)
{
struct nvgpu_channel_sync_syncpt *sp;
char syncpt_name[32];
@@ -387,34 +382,12 @@ nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c, bool user_managed)
sp->c = c;
sp->nvhost = c->g->nvhost;
if (user_managed) {
(void)strncpy(syncpt_name, c->g->name, sizeof(syncpt_name));
syncpt_name[nvgpu_safe_sub_u64(sizeof(syncpt_name), 1UL)] = '\0';
(void)strncat(syncpt_name, "_",
nvgpu_safe_sub_u64(sizeof(syncpt_name),
nvgpu_safe_add_u64(strlen(syncpt_name), 1UL)));
err = nvgpu_strnadd_u32(syncpt_name, c->chid,
nvgpu_safe_sub_u64(sizeof(syncpt_name),
strlen(syncpt_name)), 10);
if (err == 0) {
nvgpu_err(c->g, "strnadd failed!");
nvgpu_kfree(c->g, sp);
return NULL;
}
(void)strcat(syncpt_name, "_user");
snprintf(syncpt_name, sizeof(syncpt_name),
"%s_%d", c->g->name, c->chid);
sp->id = nvgpu_nvhost_get_syncpt_client_managed(sp->nvhost,
syncpt_name);
}
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
else {
snprintf(syncpt_name, sizeof(syncpt_name),
"%s_%d", c->g->name, c->chid);
sp->id = nvgpu_nvhost_get_syncpt_host_managed(sp->nvhost,
c->chid, syncpt_name);
sp->id = nvgpu_nvhost_get_syncpt_host_managed(sp->nvhost,
c->chid, syncpt_name);
}
#endif
if (sp->id == 0U) {
nvgpu_kfree(c->g, sp);
nvgpu_err(c->g, "failed to get free syncpt");

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <nvgpu/kmem.h>
#include <nvgpu/log.h>
#include <nvgpu/nvhost.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/channel.h>
#include <nvgpu/channel_user_syncpt.h>
#include <nvgpu/string.h>
#include "channel_user_syncpt_priv.h"
static int user_sync_build_debug_name(struct nvgpu_channel *ch,
char *buf, size_t capacity)
{
struct gk20a *g = ch->g;
int n;
(void)strncpy(buf, g->name, capacity);
capacity = nvgpu_safe_sub_u64(capacity, strlen(g->name));
(void)strncat(buf, "_", capacity);
capacity = nvgpu_safe_sub_u64(capacity, strlen("_"));
/*
* however, nvgpu_strnadd_u32 expects capacity to include the
* terminating byte, so add it back
*/
capacity = nvgpu_safe_add_u64(capacity, 1);
n = nvgpu_strnadd_u32(&buf[strlen(buf)], ch->chid,
capacity, 10);
if (n == 0) {
nvgpu_err(g, "strnadd failed!");
return -EINVAL;
}
capacity = nvgpu_safe_sub_u64(capacity, n);
/* nul byte */
capacity = nvgpu_safe_sub_u64(capacity, 1);
(void)strncat(buf, "_user", capacity);
/* make sure it didn't get truncated */
capacity = nvgpu_safe_sub_u64(capacity, strlen("_user"));
return 0;
}
struct nvgpu_channel_user_syncpt *
nvgpu_channel_user_syncpt_create(struct nvgpu_channel *ch)
{
struct gk20a *g = ch->g;
struct nvgpu_channel_user_syncpt *s;
char syncpt_name[32] = {0}; /* e.g. gp10b_42_user */
int err;
s = nvgpu_kzalloc(ch->g, sizeof(*s));
if (s == NULL) {
return NULL;
}
s->ch = ch;
s->nvhost = g->nvhost;
err = user_sync_build_debug_name(ch, syncpt_name,
sizeof(syncpt_name) - 1);
if (err < 0) {
goto err_free;
}
s->syncpt_id = nvgpu_nvhost_get_syncpt_client_managed(s->nvhost,
syncpt_name);
if (s->syncpt_id == 0U) {
nvgpu_err(g, "failed to get free syncpt");
goto err_free;
}
err = g->ops.sync.syncpt.alloc_buf(ch, s->syncpt_id, &s->syncpt_buf);
if (err != 0) {
nvgpu_err(g, "failed to allocate syncpoint buffer");
goto err_put;
}
nvgpu_nvhost_syncpt_set_min_eq_max_ext(s->nvhost, s->syncpt_id);
return s;
err_put:
nvgpu_nvhost_syncpt_put_ref_ext(s->nvhost, s->syncpt_id);
err_free:
nvgpu_kfree(g, s);
return NULL;
}
u32 nvgpu_channel_user_syncpt_get_id(struct nvgpu_channel_user_syncpt *s)
{
return s->syncpt_id;
}
u64 nvgpu_channel_user_syncpt_get_address(struct nvgpu_channel_user_syncpt *s)
{
return s->syncpt_buf.gpu_va;
}
void nvgpu_channel_user_syncpt_set_safe_state(struct nvgpu_channel_user_syncpt *s)
{
nvgpu_nvhost_syncpt_set_safe_state(s->nvhost, s->syncpt_id);
}
void nvgpu_channel_user_syncpt_destroy(struct nvgpu_channel_user_syncpt *s)
{
struct gk20a *g = s->ch->g;
g->ops.sync.syncpt.free_buf(s->ch, &s->syncpt_buf);
nvgpu_nvhost_syncpt_set_min_eq_max_ext(s->nvhost, s->syncpt_id);
nvgpu_nvhost_syncpt_put_ref_ext(s->nvhost, s->syncpt_id);
nvgpu_kfree(g, s);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef NVGPU_USER_SYNCPT_PRIV_H
#define NVGPU_USER_SYNCPT_PRIV_H
#include <nvgpu/types.h>
#include <nvgpu/nvgpu_mem.h>
struct nvgpu_channel;
struct nvgpu_nvhost_dev;
struct nvgpu_channel_user_syncpt {
struct nvgpu_channel *ch;
struct nvgpu_nvhost_dev *nvhost;
uint32_t syncpt_id;
struct nvgpu_mem syncpt_buf;
};
#endif /* NVGPU_USER_SYNC_PRIV_H */

View File

@@ -357,6 +357,8 @@ struct nvgpu_channel_ref_action {
};
#endif
struct nvgpu_channel_user_syncpt;
/** Channel context */
struct nvgpu_channel {
/** Pointer to GPU context. Set only when channel is active. */
@@ -481,8 +483,10 @@ struct nvgpu_channel {
/** Syncpoint lock to allocate fences. */
struct nvgpu_mutex sync_lock;
#ifdef CONFIG_TEGRA_GK20A_NVHOST
/** Syncpoint for usermode submit case. */
struct nvgpu_channel_sync *user_sync;
struct nvgpu_channel_user_syncpt *user_sync;
#endif
#ifdef CONFIG_NVGPU_GR_VIRTUALIZATION
/** Channel handle for vgpu case. */

View File

@@ -111,7 +111,6 @@ void nvgpu_channel_sync_destroy(struct nvgpu_channel_sync *sync,
* @brief Create channel syncpoint/semaphore
*
* @param c [in] Pointer to Channel.
* @param user_managed [in] True is syncpoint is user managed.
*
* Construct a channel_sync backed by either a syncpoint or a semaphore.
* A channel_sync is by default constructed as backed by a syncpoint
@@ -121,8 +120,7 @@ void nvgpu_channel_sync_destroy(struct nvgpu_channel_sync *sync,
* @return Pointer to nvgpu_channel_sync in case of success, or NULL
* in case of failure.
*/
struct nvgpu_channel_sync *nvgpu_channel_sync_create(struct nvgpu_channel *c,
bool user_managed);
struct nvgpu_channel_sync *nvgpu_channel_sync_create(struct nvgpu_channel *c);
/**
* @brief Check if OS fence framwework is needed

View File

@@ -45,8 +45,7 @@ nvgpu_channel_sync_to_semaphore(struct nvgpu_channel_sync *sync);
* returns a pointer to the struct nvgpu_channel_sync associated with it.
*/
struct nvgpu_channel_sync *
nvgpu_channel_sync_semaphore_create(
struct nvgpu_channel *c, bool user_managed);
nvgpu_channel_sync_semaphore_create(struct nvgpu_channel *c);
#endif

View File

@@ -87,15 +87,13 @@ nvgpu_channel_sync_to_syncpt(struct nvgpu_channel_sync *sync);
* @brief Create syncpoint.
*
* @param c [in] Pointer to channel.
* @param user_managed [in] True is syncpoint is managed by client.
*
* Constructs a struct nvgpu_channel_sync_syncpt.
*
* @return Pointer to nvgpu_channel_sync associated with created syncpoint.
*/
struct nvgpu_channel_sync *
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c,
bool user_managed);
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c);
#else
@@ -124,7 +122,7 @@ nvgpu_channel_sync_to_syncpt(struct nvgpu_channel_sync *sync)
}
static inline struct nvgpu_channel_sync *
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c, bool user_managed)
nvgpu_channel_sync_syncpt_create(struct nvgpu_channel *c)
{
return NULL;
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef NVGPU_USER_SYNC_H
#define NVGPU_USER_SYNC_H
#ifdef CONFIG_TEGRA_GK20A_NVHOST
#include <nvgpu/types.h>
struct nvgpu_channel;
struct nvgpu_channel_user_syncpt;
/**
* @brief Create user syncpoint for a channel.
*
* @param c [in] Pointer to Channel.
*
* Construct a nvgpu_channel_user_syncpt that represents a syncpoint allocation
* to be managed by userspace in conjunction with usermode submits.
*
* @return Pointer to nvgpu_channel_user_syncpt in case of success, or NULL in
* case of failure.
*/
struct nvgpu_channel_user_syncpt *
nvgpu_channel_user_syncpt_create(struct nvgpu_channel *ch);
/**
* @brief Get user syncpoint id
*
* @param s [in] User syncpoint pointer.
*
* @return Syncpoint id of \a s.
*/
u32 nvgpu_channel_user_syncpt_get_id(struct nvgpu_channel_user_syncpt *s);
/**
* @brief Get user syncpoint address
*
* @param s [in] User syncpoint pointer.
*
* Get syncpoint GPU VA. This address can be used in push buffer entries
* for acquire/release operations.
*
* @return Syncpoint address (GPU VA) of syncpoint or 0 if not supported
*/
u64 nvgpu_channel_user_syncpt_get_address(struct nvgpu_channel_user_syncpt *s);
/**
* @brief Set the user syncpoint to safe state
*
* @param s [in] User syncpoint pointer.
*
* This should be used to reset user managed syncpoint since we don't track
* threshold values for those syncpoints
*/
void nvgpu_channel_user_syncpt_set_safe_state(struct nvgpu_channel_user_syncpt *s);
/**
* @brief Free user syncpoint
*
* @param s [in] User syncpoint pointer.
*
* Free the resources allocated by nvgpu_channel_user_syncpt_create.
*/
void nvgpu_channel_user_syncpt_destroy(struct nvgpu_channel_user_syncpt *s);
#endif /* CONFIG_TEGRA_GK20A_NVHOST */
#endif /* NVGPU_USER_SYNC_H */

View File

@@ -323,13 +323,11 @@ nvgpu_channel_set_unserviceable
nvgpu_channel_setup_sw
nvgpu_channel_suspend_all_serviceable_ch
nvgpu_channel_sw_quiesce
nvgpu_channel_sync_create
nvgpu_channel_sync_destroy
nvgpu_channel_sync_get_syncpt_address
nvgpu_channel_sync_get_syncpt_id
nvgpu_channel_sync_needs_os_fence_framework
nvgpu_channel_sync_set_safe_state
nvgpu_channel_sync_to_syncpt
nvgpu_channel_user_syncpt_create
nvgpu_channel_user_syncpt_get_id
nvgpu_channel_user_syncpt_get_address
nvgpu_channel_user_syncpt_set_safe_state
nvgpu_channel_user_syncpt_destroy
nvgpu_check_gpu_state
nvgpu_cond_broadcast
nvgpu_cond_broadcast_interruptible

View File

@@ -39,6 +39,7 @@
#include <nvgpu/channel.h>
#include <nvgpu/channel_sync.h>
#include <nvgpu/channel_sync_syncpt.h>
#include <nvgpu/channel_user_syncpt.h>
#include <nvgpu/runlist.h>
#include <nvgpu/gr/ctx.h>
#include <nvgpu/gr/obj_ctx.h>
@@ -1047,7 +1048,6 @@ static int nvgpu_ioctl_channel_get_user_syncpoint(struct nvgpu_channel *ch,
{
#ifdef CONFIG_TEGRA_GK20A_NVHOST
struct gk20a *g = ch->g;
struct nvgpu_channel_sync_syncpt *user_sync_syncpt = NULL;
if (!nvgpu_is_enabled(g, NVGPU_SUPPORT_USER_SYNCPOINT)) {
nvgpu_err(g, "user syncpoints not supported");
@@ -1068,24 +1068,20 @@ static int nvgpu_ioctl_channel_get_user_syncpoint(struct nvgpu_channel *ch,
if (ch->user_sync) {
nvgpu_mutex_release(&ch->sync_lock);
} else {
ch->user_sync = nvgpu_channel_sync_create(ch, true);
ch->user_sync = nvgpu_channel_user_syncpt_create(ch);
if (!ch->user_sync) {
nvgpu_mutex_release(&ch->sync_lock);
return -ENOMEM;
}
nvgpu_mutex_release(&ch->sync_lock);
}
user_sync_syncpt = nvgpu_channel_sync_to_syncpt(ch->user_sync);
if (user_sync_syncpt == NULL) {
return -EINVAL;
}
args->syncpoint_id = nvgpu_channel_sync_get_syncpt_id(user_sync_syncpt);
args->syncpoint_id = nvgpu_channel_user_syncpt_get_id(ch->user_sync);
args->syncpoint_max = nvgpu_nvhost_syncpt_read_maxval(g->nvhost,
args->syncpoint_id);
if (nvgpu_is_enabled(g, NVGPU_SUPPORT_SYNCPOINT_ADDRESS)) {
args->gpu_va =
nvgpu_channel_sync_get_syncpt_address(user_sync_syncpt);
nvgpu_channel_user_syncpt_get_address(ch->user_sync);
} else {
args->gpu_va = 0;
}

View File

@@ -35,10 +35,10 @@
#include <nvgpu/runlist.h>
#include <nvgpu/debug.h>
#include <nvgpu/thread.h>
#include "common/sync/channel_sync_priv.h"
#include <nvgpu/channel_user_syncpt.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/posix/posix-nvhost.h>
#include "../nvgpu-fifo-common.h"
#include "nvgpu-channel.h"
@@ -382,22 +382,6 @@ static void stub_gr_intr_flush_channel_tlb(struct gk20a *g)
{
}
static void stub_channel_sync_syncpt_set_safe_state(
struct nvgpu_channel_sync *s)
{
}
static void stub_channel_sync_destroy(struct nvgpu_channel_sync *s)
{
stub[0].chid = 1;
}
static const struct nvgpu_channel_sync_ops stub_channel_sync_ops = {
.set_safe_state = stub_channel_sync_syncpt_set_safe_state,
.destroy = stub_channel_sync_destroy,
};
static bool channel_close_pruned(u32 branches, u32 final)
{
u32 branches_init = branches;
@@ -426,7 +410,6 @@ int test_channel_close(struct unit_module *m, struct gk20a *g, void *vargs)
struct gpu_ops gops = g->ops;
struct nvgpu_channel *ch = NULL;
struct nvgpu_tsg *tsg;
struct nvgpu_channel_sync user_sync = { {0} };
u32 branches = 0U;
int ret = UNIT_FAIL;
u32 fail = F_CHANNEL_CLOSE_ALREADY_FREED |
@@ -520,17 +503,7 @@ int test_channel_close(struct unit_module *m, struct gk20a *g, void *vargs)
gops.gr.setup.free_subctx : NULL;
if (branches & F_CHANNEL_CLOSE_USER_SYNC) {
/* Channel requires to be as_bound */
memset(&mm, 0, sizeof(mm));
memset(&vm, 0, sizeof(vm));
mm.g = g;
vm.mm = &mm;
ch->vm = &vm;
nvgpu_ref_init(&vm.ref);
nvgpu_ref_get(&vm.ref);
ch->user_sync = &user_sync;
ch->user_sync->ops = &stub_channel_sync_ops;
/* TODO: stub ch->user_sync */
}
if (branches & F_CHANNEL_WAIT_UNTIL_COUNTER) {
@@ -561,8 +534,7 @@ int test_channel_close(struct unit_module *m, struct gk20a *g, void *vargs)
}
if ((branches & F_CHANNEL_CLOSE_USER_SYNC) != 0U) {
unit_assert(stub[0].chid == 1U, goto done);
ch->user_sync = NULL;
unit_assert(ch->user_sync == NULL, goto done);
}
if (branches & fail) {
@@ -1915,10 +1887,6 @@ int test_channel_abort_cleanup(struct unit_module *m, struct gk20a *g,
err = nvgpu_tsg_bind_channel(tsg, ch);
unit_assert(err == 0, goto done);
ch->user_sync = nvgpu_kzalloc(g,
sizeof(struct nvgpu_channel_sync));
ch->user_sync->ops = &stub_channel_sync_ops;
err = nvgpu_tsg_unbind_channel(tsg, ch);
unit_assert(err == 0, goto done);

View File

@@ -31,8 +31,7 @@
#include <nvgpu/posix/posix-fault-injection.h>
#include <nvgpu/posix/posix-nvhost.h>
#include <nvgpu/channel.h>
#include <nvgpu/channel_sync.h>
#include <nvgpu/channel_sync_syncpt.h>
#include <nvgpu/channel_user_syncpt.h>
#include "../fifo/nvgpu-fifo-common.h"
#include "../fifo/nvgpu-fifo-gv11b.h"
@@ -167,56 +166,36 @@ int test_sync_init(struct unit_module *m, struct gk20a *g, void *args)
return UNIT_SUCCESS;
}
#define F_SYNC_DESTROY_SET_SAFE 0
#define F_SYNC_DESTROY_LAST 1
static const char *f_sync_destroy_syncpt[] = {
"sync_destroy_set_safe",
"sync_destroy",
};
int test_sync_create_destroy_sync(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_channel_sync *sync = NULL;
u32 branches;
bool set_safe_state = true;
struct nvgpu_channel_user_syncpt *sync = NULL;
u32 syncpt_value = 0U;
int ret = UNIT_FAIL;
for (branches = 0U; branches <= F_SYNC_DESTROY_LAST; branches++) {
sync = nvgpu_channel_sync_create(ch, true);
if (sync == NULL) {
unit_return_fail(m, "unexpected failure in creating sync points");
}
syncpt_value = g->nvhost->syncpt_value;
unit_info(m, "Syncpt ID: %u, Syncpt Value: %u\n",
g->nvhost->syncpt_id, syncpt_value);
assert((g->nvhost->syncpt_id > 0U) &&
(g->nvhost->syncpt_id <= NUM_HW_PTS));
assert(syncpt_value < (UINT_MAX - SYNCPT_SAFE_STATE_INCR));
if (branches == F_SYNC_DESTROY_LAST) {
set_safe_state = false;
}
unit_info(m, "%s branch: %s\n", __func__, f_sync_destroy_syncpt[branches]);
nvgpu_channel_sync_destroy(sync, set_safe_state);
sync = NULL;
sync = nvgpu_channel_user_syncpt_create(ch);
if (sync == NULL) {
unit_return_fail(m, "unexpected failure in creating sync points");
}
syncpt_value = g->nvhost->syncpt_value;
unit_info(m, "Syncpt ID: %u, Syncpt Value: %u\n",
g->nvhost->syncpt_id, syncpt_value);
assert((g->nvhost->syncpt_id > 0U) &&
(g->nvhost->syncpt_id <= NUM_HW_PTS));
assert(syncpt_value < (UINT_MAX - SYNCPT_SAFE_STATE_INCR));
nvgpu_channel_user_syncpt_destroy(sync);
sync = NULL;
ret = UNIT_SUCCESS;
done:
if (sync != NULL)
nvgpu_channel_sync_destroy(sync, set_safe_state);
nvgpu_channel_user_syncpt_destroy(sync);
if (nvgpu_mem_is_valid(&g->syncpt_mem) &&
ch->vm->syncpt_ro_map_gpu_va != 0ULL) {
@@ -230,14 +209,14 @@ done:
int test_sync_set_safe_state(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_channel_sync *sync = NULL;
struct nvgpu_channel_user_syncpt *sync = NULL;
u32 syncpt_value, syncpt_id;
u32 syncpt_safe_state_val;
int ret = UNIT_FAIL;
sync = nvgpu_channel_sync_create(ch, true);
sync = nvgpu_channel_user_syncpt_create(ch);
if (sync == NULL) {
unit_return_fail(m, "unexpected failure in creating sync points");
}
@@ -252,7 +231,7 @@ int test_sync_set_safe_state(struct unit_module *m, struct gk20a *g, void *args)
assert(syncpt_value < (UINT_MAX - SYNCPT_SAFE_STATE_INCR));
nvgpu_channel_sync_set_safe_state(sync);
nvgpu_channel_user_syncpt_set_safe_state(sync);
syncpt_safe_state_val = g->nvhost->syncpt_value;
@@ -260,7 +239,7 @@ int test_sync_set_safe_state(struct unit_module *m, struct gk20a *g, void *args)
unit_return_fail(m, "unexpected increment value for safe state");
}
nvgpu_channel_sync_destroy(sync, false);
nvgpu_channel_user_syncpt_destroy(sync);
sync = NULL;
@@ -268,7 +247,7 @@ int test_sync_set_safe_state(struct unit_module *m, struct gk20a *g, void *args)
done:
if (sync != NULL)
nvgpu_channel_sync_destroy(sync, false);
nvgpu_channel_user_syncpt_destroy(sync);
if (nvgpu_mem_is_valid(&g->syncpt_mem) &&
ch->vm->syncpt_ro_map_gpu_va != 0ULL) {
@@ -282,34 +261,28 @@ done:
int test_sync_usermanaged_syncpt_apis(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_channel_sync *user_sync = NULL;
struct nvgpu_channel_sync_syncpt *user_sync_syncpt = NULL;
struct nvgpu_channel_user_syncpt *user_sync = NULL;
u32 syncpt_id = 0U;
u64 syncpt_buf_addr = 0ULL;
int ret = UNIT_FAIL;
user_sync = nvgpu_channel_sync_create(ch, true);
user_sync = nvgpu_channel_user_syncpt_create(ch);
if (user_sync == NULL) {
unit_return_fail(m, "unexpected failure in creating user sync points");
}
user_sync_syncpt = nvgpu_channel_sync_to_syncpt(user_sync);
if (user_sync_syncpt == NULL) {
unit_return_fail(m, "unexpected failure in creating user_sync_syncpt");
}
syncpt_id = nvgpu_channel_sync_get_syncpt_id(user_sync_syncpt);
syncpt_id = nvgpu_channel_user_syncpt_get_id(user_sync);
assert((syncpt_id > 0U) && (syncpt_id <= NUM_HW_PTS));
syncpt_buf_addr = nvgpu_channel_sync_get_syncpt_address(user_sync_syncpt);
syncpt_buf_addr = nvgpu_channel_user_syncpt_get_address(user_sync);
assert(syncpt_buf_addr > 0ULL);
unit_info(m, "Syncpt ID: %u, Syncpt Shim GPU VA: %llu\n",
syncpt_id, syncpt_buf_addr);
nvgpu_channel_sync_destroy(user_sync, false);
nvgpu_channel_user_syncpt_destroy(user_sync);
user_sync = NULL;
@@ -317,7 +290,7 @@ int test_sync_usermanaged_syncpt_apis(struct unit_module *m, struct gk20a *g, vo
done:
if (user_sync != NULL)
nvgpu_channel_sync_destroy(user_sync, false);
nvgpu_channel_user_syncpt_destroy(user_sync);
if (nvgpu_mem_is_valid(&g->syncpt_mem) &&
ch->vm->syncpt_ro_map_gpu_va != 0ULL) {
@@ -425,7 +398,6 @@ done:
}
#define F_SYNC_SYNCPT_ALLOC_FAILED 1
#define F_SYNC_USER_MANAGED 2
#define F_SYNC_STRADD_FAIL 3
#define F_SYNC_NVHOST_CLIENT_MANAGED_FAIL 4
#define F_SYNC_RO_MAP_GPU_VA_MAP_FAIL 5
@@ -444,7 +416,12 @@ static const char *f_syncpt_open[] = {
"syncpt_buf_map_fail",
};
#define FAIL_G_NAME_STR "GK20A_FAILSTR_ADD_U32_CNDITION"
/*
* syncpt name is 32 chars big, including nul byte; the chid is 1 byte here
* ("0") and nvgpu_strnadd_u32 needs that plus nul byte. A "_" is added after
* g->name, so this would break just at the nul byte.
*/
#define FAIL_G_NAME_STR "123456789012345678901234567890"
static void clear_test_params(struct gk20a *g,
bool *fault_injection_enabled, u32 branch,
@@ -464,10 +441,9 @@ static void clear_test_params(struct gk20a *g,
int test_sync_create_fail(struct unit_module *m, struct gk20a *g, void *args)
{
struct nvgpu_channel_sync *sync = NULL;
struct nvgpu_channel_user_syncpt *sync = NULL;
struct nvgpu_posix_fault_inj *kmem_fi;
u32 branches;
bool user_managed = true;
bool fault_injection_enabled = false;
int ret = UNIT_FAIL;
const char *g_name = g->name;
@@ -490,8 +466,6 @@ int test_sync_create_fail(struct unit_module *m, struct gk20a *g, void *args)
/* fail first kzalloc call */
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
fault_injection_enabled = true;
} else if (branches == F_SYNC_USER_MANAGED) {
user_managed = false;
} else if (branches == F_SYNC_STRADD_FAIL) {
/*
* fill the entire buffer resulting in
@@ -526,11 +500,7 @@ int test_sync_create_fail(struct unit_module *m, struct gk20a *g, void *args)
unit_info(m, "%s branch: %s\n", __func__, f_syncpt_open[branches]);
sync = nvgpu_channel_sync_create(ch, user_managed);
if (branches == F_SYNC_USER_MANAGED) {
user_managed = true;
}
sync = nvgpu_channel_user_syncpt_create(ch);
if (branches == F_SYNC_NVHOST_CLIENT_MANAGED_FAIL) {
g->nvhost->syncpt_id = 0U;
@@ -540,7 +510,7 @@ int test_sync_create_fail(struct unit_module *m, struct gk20a *g, void *args)
g->name = g_name;
if (sync != NULL) {
nvgpu_channel_sync_destroy(sync, true);
nvgpu_channel_user_syncpt_destroy(sync);
unit_return_fail(m, "expected failure in creating sync points");
}