From e4e6be85ea714f3507a2429b5af256887f802742 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 29 Apr 2020 16:51:53 +0530 Subject: [PATCH] gpu: nvgpu: move profiler alloc/free APIs to separate file Move profiler object allocation/free APIs to separate profiler specific file common/profiler.c. Store struct gk20a pointer in struct dbg_profiler_object_data for convenience of accessing global struct pointer. Update profiler object to store TSG pointer instead of channel pointer. Since expectations is to have one profiler object per context/TSG. nvgpu_profiler_reserve_acquire() has a case to check if resource reservation is acquired by some other channel in TSG. But now since we keep track of TSG itself, this case becomes redundant and can be removed. All the support is compiled out of safety build with compile flag CONFIG_NVGPU_PROFILER. Linux will always compile the support. Bug 2510974 Change-Id: I197bbd67a9cdd1fbea42f1effd1b74b15a6068e5 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2365674 Tested-by: mobile promotions Reviewed-by: mobile promotions --- arch/nvgpu-common.yaml | 6 ++ drivers/gpu/nvgpu/Makefile | 4 +- drivers/gpu/nvgpu/Makefile.shared.configs | 3 + drivers/gpu/nvgpu/Makefile.sources | 4 + drivers/gpu/nvgpu/common/debugger.c | 3 +- drivers/gpu/nvgpu/common/profiler/profiler.c | 64 +++++++++++ drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c | 3 +- drivers/gpu/nvgpu/include/nvgpu/debugger.h | 16 +-- drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 5 +- drivers/gpu/nvgpu/include/nvgpu/profiler.h | 54 ++++++++++ drivers/gpu/nvgpu/os/linux/ioctl_dbg.c | 102 ++++++------------ 11 files changed, 176 insertions(+), 88 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/profiler/profiler.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/profiler.h diff --git a/arch/nvgpu-common.yaml b/arch/nvgpu-common.yaml index eacdc2639..1925068e5 100644 --- a/arch/nvgpu-common.yaml +++ b/arch/nvgpu-common.yaml @@ -59,6 +59,12 @@ debugger: include/nvgpu/debugger.h ] deps: +profiler: + safe: no + owner: Deepak N + sources: [ common/profiler/profiler.c, + include/nvgpu/profiler.h ] + defaults: safe: yes sources: [ include/nvgpu/defaults.h ] diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index b3e75eb27..13b72549d 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -50,6 +50,7 @@ ccflags-y += -DCONFIG_NVGPU_GR_FALCON_NON_SECURE_BOOT ccflags-y += -DCONFIG_NVGPU_SET_FALCON_ACCESS_MAP ccflags-y += -DCONFIG_NVGPU_SW_SEMAPHORE ccflags-y += -DCONFIG_NVGPU_FENCE +ccflags-y += -DCONFIG_NVGPU_PROFILER ifeq ($(CONFIG_NVGPU_LOGGING),y) ccflags-y += -DCONFIG_NVGPU_LOGGING=1 @@ -541,7 +542,8 @@ nvgpu-y += \ common/ecc.o \ common/log_common.o \ common/ce/ce.o \ - common/debugger.o + common/debugger.o \ + common/profiler/profiler.o nvgpu-$(CONFIG_NVGPU_GR_VIRTUALIZATION) += \ common/vgpu/ltc/ltc_vgpu.o \ diff --git a/drivers/gpu/nvgpu/Makefile.shared.configs b/drivers/gpu/nvgpu/Makefile.shared.configs index 882ee8e91..8bea08ac1 100644 --- a/drivers/gpu/nvgpu/Makefile.shared.configs +++ b/drivers/gpu/nvgpu/Makefile.shared.configs @@ -156,6 +156,9 @@ NVGPU_COMMON_CFLAGS += -DCONFIG_NVGPU_ENGINE_QUEUE CONFIG_NVGPU_DEBUGGER := 1 NVGPU_COMMON_CFLAGS += -DCONFIG_NVGPU_DEBUGGER +CONFIG_NVGPU_PROFILER := 1 +NVGPU_COMMON_CFLAGS += -DCONFIG_NVGPU_PROFILER + CONFIG_NVGPU_RECOVERY := 1 NVGPU_COMMON_CFLAGS += -DCONFIG_NVGPU_RECOVERY diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 6aad1299e..6cdefb7ac 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -389,6 +389,10 @@ srcs += hal/regops/regops_gm20b.c \ endif endif +ifeq ($(CONFIG_NVGPU_PROFILER),1) +srcs += common/profiler/profiler.c +endif + ifeq ($(CONFIG_NVGPU_KERNEL_MODE_SUBMIT),1) srcs += common/fifo/submit.c \ common/fifo/priv_cmdbuf.c \ diff --git a/drivers/gpu/nvgpu/common/debugger.c b/drivers/gpu/nvgpu/common/debugger.c index b0d468c8e..72d700c2a 100644 --- a/drivers/gpu/nvgpu/common/debugger.c +++ b/drivers/gpu/nvgpu/common/debugger.c @@ -34,6 +34,7 @@ #include #include #include +#include #include /* @@ -281,7 +282,7 @@ void nvgpu_release_profiler_reservation(struct dbg_session_gk20a *dbg_s, } dbg_s->has_profiler_reservation = false; prof_obj->has_reservation = false; - if (prof_obj->ch == NULL) { + if (prof_obj->tsg == NULL) { g->global_profiler_reservation_held = false; } } diff --git a/drivers/gpu/nvgpu/common/profiler/profiler.c b/drivers/gpu/nvgpu/common/profiler/profiler.c new file mode 100644 index 000000000..7da67cc0b --- /dev/null +++ b/drivers/gpu/nvgpu/common/profiler/profiler.c @@ -0,0 +1,64 @@ +/* + * 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 + +static nvgpu_atomic_t unique_id = NVGPU_ATOMIC_INIT(0); +static int generate_unique_id(void) +{ + return nvgpu_atomic_add_return(1, &unique_id); +} + +int nvgpu_profiler_alloc(struct gk20a *g, + struct dbg_profiler_object_data **_prof) +{ + struct dbg_profiler_object_data *prof; + *_prof = NULL; + + nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " "); + + prof = nvgpu_kzalloc(g, sizeof(*prof)); + if (prof == NULL) { + return -ENOMEM; + } + + prof->prof_handle = generate_unique_id(); + prof->g = g; + + nvgpu_init_list_node(&prof->prof_obj_entry); + nvgpu_list_add(&prof->prof_obj_entry, &g->profiler_objects); + + *_prof = prof; + return 0; +} + +void nvgpu_profiler_free(struct dbg_profiler_object_data *prof) +{ + struct gk20a *g = prof->g; + + nvgpu_list_del(&prof->prof_obj_entry); + nvgpu_kfree(g, prof); +} diff --git a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c index ff82e91c7..9a24242c0 100644 --- a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c +++ b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -186,7 +187,7 @@ void vgpu_release_profiler_reservation( dbg_s->has_profiler_reservation = false; prof_obj->has_reservation = false; - if (prof_obj->ch == NULL) { + if (prof_obj->tsg == NULL) { g->global_profiler_reservation_held = false; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/debugger.h b/drivers/gpu/nvgpu/include/nvgpu/debugger.h index ce63603ae..3258439b8 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/debugger.h +++ b/drivers/gpu/nvgpu/include/nvgpu/debugger.h @@ -33,6 +33,7 @@ struct gk20a; struct nvgpu_channel; struct dbg_session_gk20a; +struct dbg_profiler_object_data; struct nvgpu_channel * nvgpu_dbg_gpu_get_session_channel(struct dbg_session_gk20a *dbg_s); @@ -101,21 +102,6 @@ dbg_session_channel_data_from_ch_entry(struct nvgpu_list_node *node) ((uintptr_t)node - offsetof(struct dbg_session_channel_data, ch_entry)); }; -struct dbg_profiler_object_data { - int session_id; - u32 prof_handle; - struct nvgpu_channel *ch; - bool has_reservation; - struct nvgpu_list_node prof_obj_entry; -}; - -static inline struct dbg_profiler_object_data * -dbg_profiler_object_data_from_prof_obj_entry(struct nvgpu_list_node *node) -{ - return (struct dbg_profiler_object_data *) - ((uintptr_t)node - offsetof(struct dbg_profiler_object_data, prof_obj_entry)); -}; - /* used by the interrupt handler to post events */ void nvgpu_dbg_gpu_post_events(struct nvgpu_channel *ch); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index c2005f719..7b0916755 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -830,7 +830,6 @@ struct gk20a { } perfbuf; /* For profiler reservations */ - struct nvgpu_list_node profiler_objects; bool global_profiler_reservation_held; int profiler_reservation_count; @@ -838,6 +837,10 @@ struct gk20a { u32 mmu_debug_mode_refcnt; #endif /* CONFIG_NVGPU_DEBUGGER */ +#ifdef CONFIG_NVGPU_PROFILER + struct nvgpu_list_node profiler_objects; +#endif + #ifdef CONFIG_NVGPU_FECS_TRACE struct gk20a_ctxsw_trace *ctxsw_trace; struct nvgpu_gr_fecs_trace *fecs_trace; diff --git a/drivers/gpu/nvgpu/include/nvgpu/profiler.h b/drivers/gpu/nvgpu/include/nvgpu/profiler.h new file mode 100644 index 000000000..4614838ee --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/profiler.h @@ -0,0 +1,54 @@ +/* + * 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_PROFILER_H +#define NVGPU_PROFILER_H + +#ifdef CONFIG_NVGPU_PROFILER + +#include + +struct gk20a; +struct nvgpu_channel; + +struct dbg_profiler_object_data { + struct gk20a *g; + int session_id; + u32 prof_handle; + struct nvgpu_tsg *tsg; + bool has_reservation; + struct nvgpu_list_node prof_obj_entry; +}; + +static inline struct dbg_profiler_object_data * +dbg_profiler_object_data_from_prof_obj_entry(struct nvgpu_list_node *node) +{ + return (struct dbg_profiler_object_data *) + ((uintptr_t)node - offsetof(struct dbg_profiler_object_data, prof_obj_entry)); +}; + +int nvgpu_profiler_alloc(struct gk20a *g, + struct dbg_profiler_object_data **_prof); +void nvgpu_profiler_free(struct dbg_profiler_object_data *prof); + +#endif /* CONFIG_NVGPU_PROFILER */ +#endif /* NVGPU_PROFILER_H */ diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c index af1393d0d..3369cef7f 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -79,23 +80,6 @@ static int generate_unique_id(void) return nvgpu_atomic_add_return(1, &unique_id); } -static int alloc_profiler(struct gk20a *g, - struct dbg_profiler_object_data **_prof) -{ - struct dbg_profiler_object_data *prof; - *_prof = NULL; - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " "); - - prof = nvgpu_kzalloc(g, sizeof(*prof)); - if (!prof) - return -ENOMEM; - - prof->prof_handle = generate_unique_id(); - *_prof = prof; - return 0; -} - static int alloc_session(struct gk20a *g, struct dbg_session_gk20a_linux **_dbg_s_linux) { struct dbg_session_gk20a_linux *dbg_s_linux; @@ -462,10 +446,12 @@ static int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, struct dbg_session_data *session_data; struct dbg_profiler_object_data *prof_obj, *tmp_obj; struct dbg_session_channel_data_linux *ch_data_linux; + struct nvgpu_channel *ch; nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " "); chid = ch_data->chid; + ch = &g->fifo.channel[chid]; /* If there's a profiler ctx reservation record associated with this * session/channel pair, release it. @@ -473,7 +459,7 @@ static int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, nvgpu_list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, dbg_profiler_object_data, prof_obj_entry) { if ((prof_obj->session_id == dbg_s->id) && - (prof_obj->ch->chid == chid)) { + (prof_obj->tsg->tsgid == ch->tsgid)) { if (prof_obj->has_reservation) { g->ops.debugger. release_profiler_reservation(dbg_s, prof_obj); @@ -1186,36 +1172,42 @@ static int nvgpu_ioctl_allocate_profiler_object( struct dbg_session_gk20a *dbg_s = &dbg_session_linux->dbg_s; struct gk20a *g = get_gk20a(dbg_session_linux->dev); struct dbg_profiler_object_data *prof_obj; + struct nvgpu_channel *ch = NULL; + struct nvgpu_tsg *tsg; nvgpu_log_fn(g, "%s", g->name); nvgpu_mutex_acquire(&g->dbg_sessions_lock); - err = alloc_profiler(g, &prof_obj); - if (err) - goto clean_up; - - prof_obj->session_id = dbg_s->id; - - if (dbg_s->is_profiler) - prof_obj->ch = NULL; - else { - prof_obj->ch = nvgpu_dbg_gpu_get_session_channel(dbg_s); - if (prof_obj->ch == NULL) { - nvgpu_err(g, - "bind a channel for dbg session"); - nvgpu_kfree(g, prof_obj); + if (!dbg_s->is_profiler) { + ch = nvgpu_dbg_gpu_get_session_channel(dbg_s); + if (ch == NULL) { + nvgpu_err(g, "no channel for dbg session"); err = -EINVAL; goto clean_up; } } + err = nvgpu_profiler_alloc(g, &prof_obj); + if (err != 0) { + goto clean_up; + } + + if (ch != NULL) { + tsg = nvgpu_tsg_from_ch(ch); + if (tsg == NULL) { + nvgpu_profiler_free(prof_obj); + goto clean_up; + } + + prof_obj->tsg = tsg; + } + + prof_obj->session_id = dbg_s->id; + /* Return handle to client */ args->profiler_handle = prof_obj->prof_handle; - nvgpu_init_list_node(&prof_obj->prof_obj_entry); - - nvgpu_list_add(&prof_obj->prof_obj_entry, &g->profiler_objects); clean_up: nvgpu_mutex_release(&g->dbg_sessions_lock); return err; @@ -1250,8 +1242,7 @@ static int nvgpu_ioctl_free_profiler_object( if (prof_obj->has_reservation) g->ops.debugger. release_profiler_reservation(dbg_s, prof_obj); - nvgpu_list_del(&prof_obj->prof_obj_entry); - nvgpu_kfree(g, prof_obj); + nvgpu_profiler_free(prof_obj); obj_found = true; break; } @@ -1726,7 +1717,6 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, struct gk20a *g = dbg_s->g; struct dbg_profiler_object_data *prof_obj, *my_prof_obj; int err = 0; - struct nvgpu_tsg *tsg; nvgpu_log_fn(g, "%s profiler_handle = %x", g->name, profiler_handle); @@ -1752,7 +1742,7 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, goto exit; } - if (my_prof_obj->ch == NULL) { + if (my_prof_obj->tsg == NULL) { /* Global reservations are only allowed if there are no other * global or per-context reservations currently held */ @@ -1769,16 +1759,14 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, nvgpu_err(g, "per-ctxt reserve: global reservation in effect"); err = -EBUSY; - } else if ((tsg = nvgpu_tsg_from_ch(my_prof_obj->ch)) != NULL) { - /* TSG: check that another channel in the TSG - * doesn't already have the reservation - */ - u32 my_tsgid = tsg->tsgid; + } else { + /* check that this TSG doesn't already have the reservation */ + u32 my_tsgid = my_prof_obj->tsg->tsgid; nvgpu_list_for_each_entry(prof_obj, &g->profiler_objects, dbg_profiler_object_data, prof_obj_entry) { if (prof_obj->has_reservation && - (prof_obj->ch->tsgid == my_tsgid)) { + (prof_obj->tsg->tsgid == my_tsgid)) { nvgpu_err(g, "per-ctxt reserve (tsg): already reserved"); err = -EBUSY; @@ -1786,30 +1774,6 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, } } - if (!g->ops.debugger.check_and_set_context_reservation( - dbg_s, my_prof_obj)) { - /* Another guest OS has the global reservation */ - nvgpu_err(g, - "per-ctxt reserve: global reservation in effect"); - err = -EBUSY; - } - } else { - /* channel: check that some other profiler object doesn't - * already have the reservation. - */ - struct nvgpu_channel *my_ch = my_prof_obj->ch; - - nvgpu_list_for_each_entry(prof_obj, &g->profiler_objects, - dbg_profiler_object_data, prof_obj_entry) { - if (prof_obj->has_reservation && - (prof_obj->ch == my_ch)) { - nvgpu_err(g, - "per-ctxt reserve (ch): already reserved"); - err = -EBUSY; - goto exit; - } - } - if (!g->ops.debugger.check_and_set_context_reservation( dbg_s, my_prof_obj)) { /* Another guest OS has the global reservation */