diff --git a/arch/nvgpu-common.yaml b/arch/nvgpu-common.yaml index cba831fa4..1e22ff38e 100644 --- a/arch/nvgpu-common.yaml +++ b/arch/nvgpu-common.yaml @@ -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: diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 909b41ac8..7bc58db9f 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -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 \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 299b74273..c4d6586ba 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -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) diff --git a/drivers/gpu/nvgpu/common/fifo/channel.c b/drivers/gpu/nvgpu/common/fifo/channel.c index 73e464d36..24a3b88d1 100644 --- a/drivers/gpu/nvgpu/common/fifo/channel.c +++ b/drivers/gpu/nvgpu/common/fifo/channel.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -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) diff --git a/drivers/gpu/nvgpu/common/fifo/submit.c b/drivers/gpu/nvgpu/common/fifo/submit.c index 938f4904a..162cc19b5 100644 --- a/drivers/gpu/nvgpu/common/fifo/submit.c +++ b/drivers/gpu/nvgpu/common/fifo/submit.c @@ -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; diff --git a/drivers/gpu/nvgpu/common/init/nvgpu_init.c b/drivers/gpu/nvgpu/common/init/nvgpu_init.c index 22e8bb5c2..62c4c773c 100644 --- a/drivers/gpu/nvgpu/common/init/nvgpu_init.c +++ b/drivers/gpu/nvgpu/common/init/nvgpu_init.c @@ -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); diff --git a/drivers/gpu/nvgpu/common/sync/channel_sync.c b/drivers/gpu/nvgpu/common/sync/channel_sync.c index fbb7d3d97..ccd14f392 100644 --- a/drivers/gpu/nvgpu/common/sync/channel_sync.c +++ b/drivers/gpu/nvgpu/common/sync/channel_sync.c @@ -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); diff --git a/drivers/gpu/nvgpu/common/sync/channel_sync_priv.h b/drivers/gpu/nvgpu/common/sync/channel_sync_priv.h index 0264c9eae..f41221fb5 100644 --- a/drivers/gpu/nvgpu/common/sync/channel_sync_priv.h +++ b/drivers/gpu/nvgpu/common/sync/channel_sync_priv.h @@ -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 #include @@ -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 */ diff --git a/drivers/gpu/nvgpu/common/sync/channel_sync_semaphore.c b/drivers/gpu/nvgpu/common/sync/channel_sync_semaphore.c index 0aa4f1eba..8a8f386c1 100644 --- a/drivers/gpu/nvgpu/common/sync/channel_sync_semaphore.c +++ b/drivers/gpu/nvgpu/common/sync/channel_sync_semaphore.c @@ -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; diff --git a/drivers/gpu/nvgpu/common/sync/channel_sync_syncpt.c b/drivers/gpu/nvgpu/common/sync/channel_sync_syncpt.c index fab2fd36c..94e886c43 100644 --- a/drivers/gpu/nvgpu/common/sync/channel_sync_syncpt.c +++ b/drivers/gpu/nvgpu/common/sync/channel_sync_syncpt.c @@ -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"); diff --git a/drivers/gpu/nvgpu/common/sync/channel_user_syncpt.c b/drivers/gpu/nvgpu/common/sync/channel_user_syncpt.c new file mode 100644 index 000000000..518d33fbd --- /dev/null +++ b/drivers/gpu/nvgpu/common/sync/channel_user_syncpt.c @@ -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 +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/drivers/gpu/nvgpu/common/sync/channel_user_syncpt_priv.h b/drivers/gpu/nvgpu/common/sync/channel_user_syncpt_priv.h new file mode 100644 index 000000000..0f30b50c7 --- /dev/null +++ b/drivers/gpu/nvgpu/common/sync/channel_user_syncpt_priv.h @@ -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 +#include + +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 */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel.h b/drivers/gpu/nvgpu/include/nvgpu/channel.h index 58e37288e..0840bcdb7 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel.h @@ -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. */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel_sync.h b/drivers/gpu/nvgpu/include/nvgpu/channel_sync.h index bb8714eb5..dbecadf34 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel_sync.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel_sync.h @@ -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 diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel_sync_semaphore.h b/drivers/gpu/nvgpu/include/nvgpu/channel_sync_semaphore.h index 18ae40af2..c6969c114 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel_sync_semaphore.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel_sync_semaphore.h @@ -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 diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel_sync_syncpt.h b/drivers/gpu/nvgpu/include/nvgpu/channel_sync_syncpt.h index 5aa3eb185..a6fcff99f 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/channel_sync_syncpt.h +++ b/drivers/gpu/nvgpu/include/nvgpu/channel_sync_syncpt.h @@ -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; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/channel_user_syncpt.h b/drivers/gpu/nvgpu/include/nvgpu/channel_user_syncpt.h new file mode 100644 index 000000000..7362cb4e1 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/channel_user_syncpt.h @@ -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 + +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 */ diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 35088a538..7083f7b32 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -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 diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c index 1dd894cb3..0fba35576 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/userspace/units/fifo/channel/nvgpu-channel.c b/userspace/units/fifo/channel/nvgpu-channel.c index 21e2f4186..4d3f1afd6 100644 --- a/userspace/units/fifo/channel/nvgpu-channel.c +++ b/userspace/units/fifo/channel/nvgpu-channel.c @@ -35,10 +35,10 @@ #include #include #include - -#include "common/sync/channel_sync_priv.h" +#include #include +#include #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); diff --git a/userspace/units/sync/nvgpu-sync.c b/userspace/units/sync/nvgpu-sync.c index fb445ab92..7eda9e1f0 100644 --- a/userspace/units/sync/nvgpu-sync.c +++ b/userspace/units/sync/nvgpu-sync.c @@ -31,8 +31,7 @@ #include #include #include -#include -#include +#include #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"); }