From 08308bc936e862de2a3987e9bef1c55b05f95c9b Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Thu, 30 Apr 2020 16:23:44 +0530 Subject: [PATCH] gpu: nvgpu: rework pm resource reservation system Current PM resource reservation system is limited to HWPM resources only. And reservation tracking is done using boolean variables. New upcoming profiler support requires reservation for all the PM resources like SMPC and PMA stream. Using boolean variables is not scalable and confusing. Plus the variables have to be replicated on gpu server in case of virtualization. Remove flag tracking mechanism and use list based approach to track all PM reservations. Also, current HALs are defined on debugger object. Implement new HALs in new pm_reservation object since it is really an independent functionality. Add new source file common/profiler/pm_reservation.c which implements functions to reserve/release resources and to check if any resource is reserved or not. Add common/vgpu/pm_reservation_vgpu.c for vGPU which simply forwards the request to gpu server. Define new HAL object gops.pm_reservation and assign above functions to below respective HALs : g->ops.pm_reservation.acquire() g->ops.pm_reservation.release() g->ops.pm_reservation.release_all_per_vmid() Last HAL above is only used for gpu server cleanup of guest OS. Add below new common profiler functions that act as APIs to reserve/ release resources for rest of the units in nvgpu. nvgpu_profiler_pm_resource_reserve() nvgpu_profiler_pm_resource_release() Initialize the meta data required for reservtion system in nvgpu_pm_reservation_init() and call it during nvgpu_finalize_poweron. Clean up the meta data before releasing struct gk20a. Delete below HALs : g->ops.debugger.check_and_set_global_reservation() g->ops.debugger.check_and_set_context_reservation() g->ops.debugger.release_profiler_reservation() Bug 2510974 Jira NVGPU-5360 Change-Id: I4d9f89c58c791b3b2e63099a8a603462e5319222 Signed-off-by: Deepak Nibade Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2367224 Tested-by: mobile promotions Reviewed-by: mobile promotions --- arch/nvgpu-common.yaml | 4 +- arch/nvgpu-vgpu.yaml | 2 + drivers/gpu/nvgpu/Makefile | 4 +- drivers/gpu/nvgpu/Makefile.sources | 4 +- drivers/gpu/nvgpu/common/debugger.c | 47 ---- drivers/gpu/nvgpu/common/init/nvgpu_init.c | 8 + .../nvgpu/common/profiler/pm_reservation.c | 230 ++++++++++++++++++ drivers/gpu/nvgpu/common/profiler/profiler.c | 75 +++++- drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c | 79 ------ drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.h | 9 - .../nvgpu/common/vgpu/pm_reservation_vgpu.c | 72 ++++++ .../nvgpu/common/vgpu/pm_reservation_vgpu.h | 40 +++ drivers/gpu/nvgpu/hal/init/hal_gm20b.c | 18 +- drivers/gpu/nvgpu/hal/init/hal_gp10b.c | 18 +- drivers/gpu/nvgpu/hal/init/hal_gv11b.c | 18 +- drivers/gpu/nvgpu/hal/init/hal_tu104.c | 18 +- .../gpu/nvgpu/hal/vgpu/init/vgpu_hal_gp10b.c | 17 +- .../gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c | 17 +- drivers/gpu/nvgpu/include/nvgpu/debugger.h | 11 - drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 28 ++- .../gpu/nvgpu/include/nvgpu/pm_reservation.h | 79 ++++++ drivers/gpu/nvgpu/include/nvgpu/profiler.h | 16 +- .../gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h | 8 +- drivers/gpu/nvgpu/os/linux/ioctl_dbg.c | 122 ++++------ 24 files changed, 666 insertions(+), 278 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/profiler/pm_reservation.c create mode 100644 drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.c create mode 100644 drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.h create mode 100644 drivers/gpu/nvgpu/include/nvgpu/pm_reservation.h diff --git a/arch/nvgpu-common.yaml b/arch/nvgpu-common.yaml index 1925068e5..0a9e4ed67 100644 --- a/arch/nvgpu-common.yaml +++ b/arch/nvgpu-common.yaml @@ -63,7 +63,9 @@ profiler: safe: no owner: Deepak N sources: [ common/profiler/profiler.c, - include/nvgpu/profiler.h ] + include/nvgpu/profiler.h, + common/profiler/pm_reservation.c, + include/nvgpu/pm_reservation.h ] defaults: safe: yes diff --git a/arch/nvgpu-vgpu.yaml b/arch/nvgpu-vgpu.yaml index a31abd759..adcd33034 100644 --- a/arch/nvgpu-vgpu.yaml +++ b/arch/nvgpu-vgpu.yaml @@ -18,6 +18,8 @@ all: common/vgpu/clk_vgpu.h, common/vgpu/debugger_vgpu.c, common/vgpu/debugger_vgpu.h, + common/vgpu/pm_reservation_vgpu.c, + common/vgpu/pm_reservation_vgpu.h, common/vgpu/ecc_vgpu.c, common/vgpu/ecc_vgpu.h, common/vgpu/fifo/fifo_vgpu.c, diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 13b72549d..3d0339ac7 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -543,7 +543,8 @@ nvgpu-y += \ common/log_common.o \ common/ce/ce.o \ common/debugger.o \ - common/profiler/profiler.o + common/profiler/profiler.o \ + common/profiler/pm_reservation.o nvgpu-$(CONFIG_NVGPU_GR_VIRTUALIZATION) += \ common/vgpu/ltc/ltc_vgpu.o \ @@ -568,6 +569,7 @@ nvgpu-$(CONFIG_NVGPU_GR_VIRTUALIZATION) += \ common/vgpu/intr/intr_vgpu.o \ common/vgpu/ptimer/ptimer_vgpu.o \ common/vgpu/debugger_vgpu.o \ + common/vgpu/pm_reservation_vgpu.o \ common/vgpu/perf/perf_vgpu.o \ common/vgpu/ecc_vgpu.o \ common/vgpu/clk_vgpu.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 6cdefb7ac..7fb4b8ed1 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -390,7 +390,8 @@ endif endif ifeq ($(CONFIG_NVGPU_PROFILER),1) -srcs += common/profiler/profiler.c +srcs += common/profiler/profiler.c \ + += common/profiler/pm_reservation.c endif ifeq ($(CONFIG_NVGPU_KERNEL_MODE_SUBMIT),1) @@ -553,6 +554,7 @@ srcs += common/vgpu/init/init_vgpu.c \ common/vgpu/gr/subctx_vgpu.c \ common/vgpu/clk_vgpu.c \ common/vgpu/debugger_vgpu.c \ + common/vgpu/pm_reservation_vgpu.c \ common/vgpu/ltc/ltc_vgpu.c \ common/vgpu/fbp/fbp_vgpu.c \ common/vgpu/ce_vgpu.c \ diff --git a/drivers/gpu/nvgpu/common/debugger.c b/drivers/gpu/nvgpu/common/debugger.c index 93136cf6a..18fa4bacd 100644 --- a/drivers/gpu/nvgpu/common/debugger.c +++ b/drivers/gpu/nvgpu/common/debugger.c @@ -239,50 +239,3 @@ int nvgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powerg g->name, disable_powergate ? "disable" : "enable"); return err; } - -bool nvgpu_check_and_set_global_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - if (g->profiler_reservation_count == 0) { - g->global_profiler_reservation_held = true; - g->profiler_reservation_count = 1; - dbg_s->has_profiler_reservation = true; - prof_obj->has_reservation = true; - return true; - } - return false; -} - -bool nvgpu_check_and_set_context_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - /* Assumes that we've already checked that no global reservation - * is in effect. - */ - g->profiler_reservation_count++; - dbg_s->has_profiler_reservation = true; - prof_obj->has_reservation = true; - return true; -} - -void nvgpu_release_profiler_reservation(struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - g->profiler_reservation_count--; - if (g->profiler_reservation_count < 0) { - nvgpu_err(g, "Negative reservation count!"); - } - dbg_s->has_profiler_reservation = false; - prof_obj->has_reservation = false; - if (prof_obj->tsg == NULL) { - g->global_profiler_reservation_held = false; - } -} diff --git a/drivers/gpu/nvgpu/common/init/nvgpu_init.c b/drivers/gpu/nvgpu/common/init/nvgpu_init.c index 853ffae49..fabbcbd16 100644 --- a/drivers/gpu/nvgpu/common/init/nvgpu_init.c +++ b/drivers/gpu/nvgpu/common/init/nvgpu_init.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef CONFIG_NVGPU_LS_PMU #include @@ -686,6 +687,9 @@ int nvgpu_finalize_poweron(struct gk20a *g) #endif NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_xve_set_speed, NO_FLAG), NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_syncpt_mem, NO_FLAG), +#ifdef CONFIG_NVGPU_PROFILER + NVGPU_INIT_TABLE_ENTRY(&nvgpu_pm_reservation_init, NO_FLAG), +#endif NVGPU_INIT_TABLE_ENTRY(g->ops.channel.resume_all_serviceable_ch, NO_FLAG), }; @@ -878,6 +882,10 @@ static void gk20a_free_cb(struct nvgpu_ref *refcount) nvgpu_device_cleanup(g); +#ifdef CONFIG_NVGPU_PROFILER + nvgpu_pm_reservation_deinit(g); +#endif + nvgpu_sw_quiesce_remove_support(g); if (g->gfree != NULL) { diff --git a/drivers/gpu/nvgpu/common/profiler/pm_reservation.c b/drivers/gpu/nvgpu/common/profiler/pm_reservation.c new file mode 100644 index 000000000..dc1591ba5 --- /dev/null +++ b/drivers/gpu/nvgpu/common/profiler/pm_reservation.c @@ -0,0 +1,230 @@ +/* + * 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 bool check_pm_resource_existing_reservation_locked( + struct nvgpu_pm_resource_reservations *reservations, + u32 reservation_id, u32 vmid) +{ + struct nvgpu_pm_resource_reservation_entry *reservation_entry; + bool reserved = false; + + nvgpu_list_for_each_entry(reservation_entry, + &reservations->head, + nvgpu_pm_resource_reservation_entry, + entry) { + if ((reservation_entry->reservation_id == reservation_id) && + (reservation_entry->vmid == vmid )) { + reserved = true; + break; + } + } + + return reserved; +} + +static bool check_pm_resource_reservation_allowed_locked( + struct nvgpu_pm_resource_reservations *reservations, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 reservation_id, u32 vmid) +{ + struct nvgpu_pm_resource_reservation_entry *reservation_entry; + bool allowed = false; + + switch (scope) { + case NVGPU_PROFILER_PM_RESERVATION_SCOPE_DEVICE: + /* + * Reservation of SCOPE_DEVICE is allowed only if there is + * no current reservation of any scope by any profiler object. + */ + if (reservations->count == 0U) { + allowed = true; + } + break; + + case NVGPU_PROFILER_PM_RESERVATION_SCOPE_CONTEXT: + /* + * Reservation of SCOPE_CONTEXT is allowed only if - + * 1. There is no current SCOPE_DEVICE reservation by any other profiler + * object. + * 2. Requesting profiler object does not already have the reservation. + */ + + if (!nvgpu_list_empty(&reservations->head)) { + reservation_entry = nvgpu_list_first_entry( + &reservations->head, + nvgpu_pm_resource_reservation_entry, + entry); + if (reservation_entry->scope == + NVGPU_PROFILER_PM_RESERVATION_SCOPE_DEVICE) { + break; + } + } + + if (check_pm_resource_existing_reservation_locked(reservations, + reservation_id, vmid)) { + break; + } + + allowed = true; + break; + } + + return allowed; +} + +int nvgpu_pm_reservation_acquire(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 vmid) +{ + struct nvgpu_pm_resource_reservations *reservations = + &g->pm_reservations[pm_resource]; + struct nvgpu_pm_resource_reservation_entry *reservation_entry; + int err = 0; + + nvgpu_mutex_acquire(&reservations->lock); + + if (!check_pm_resource_reservation_allowed_locked(reservations, scope, + reservation_id, vmid)) { + err = -EBUSY; + goto done; + } + + reservation_entry = nvgpu_kzalloc(g, sizeof(*reservation_entry)); + if (reservation_entry == NULL) { + err = -ENOMEM; + goto done; + } + + nvgpu_init_list_node(&reservation_entry->entry); + + reservation_entry->reservation_id = reservation_id; + reservation_entry->scope = scope; + reservation_entry->vmid = vmid; + + nvgpu_list_add(&reservation_entry->entry, &reservations->head); + reservations->count++; + +done: + nvgpu_mutex_release(&reservations->lock); + + return err; +} + +int nvgpu_pm_reservation_release(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + u32 vmid) +{ + struct nvgpu_pm_resource_reservations *reservations = + &g->pm_reservations[pm_resource]; + struct nvgpu_pm_resource_reservation_entry *reservation_entry, *n; + bool was_reserved = false; + int err = 0; + + nvgpu_mutex_acquire(&reservations->lock); + + nvgpu_list_for_each_entry_safe(reservation_entry, n, + &reservations->head, + nvgpu_pm_resource_reservation_entry, + entry) { + if ((reservation_entry->reservation_id == reservation_id) && + (reservation_entry->vmid == vmid)) { + was_reserved = true; + nvgpu_list_del(&reservation_entry->entry); + reservations->count--; + nvgpu_kfree(g, reservation_entry); + break; + } + } + + if (!was_reserved) { + err = -EINVAL; + } + + nvgpu_mutex_release(&reservations->lock); + + return err; +} + +void nvgpu_pm_reservation_release_all_per_vmid(struct gk20a *g, u32 vmid) +{ + struct nvgpu_pm_resource_reservations *reservations; + struct nvgpu_pm_resource_reservation_entry *reservation_entry, *n; + int i; + + for (i = 0; i < NVGPU_PROFILER_PM_RESOURCE_TYPE_COUNT; i++) { + reservations = &g->pm_reservations[i]; + + nvgpu_mutex_acquire(&reservations->lock); + nvgpu_list_for_each_entry_safe(reservation_entry, n, + &reservations->head, + nvgpu_pm_resource_reservation_entry, + entry) { + if (reservation_entry->vmid == vmid) { + nvgpu_list_del(&reservation_entry->entry); + reservations->count--; + nvgpu_kfree(g, reservation_entry); + } + } + nvgpu_mutex_release(&reservations->lock); + } +} + +int nvgpu_pm_reservation_init(struct gk20a *g) +{ + struct nvgpu_pm_resource_reservations *reservations; + int i; + + nvgpu_log(g, gpu_dbg_prof, " "); + + if (g->pm_reservations) { + return 0; + } + + reservations = nvgpu_kzalloc(g, sizeof(*reservations) * + NVGPU_PROFILER_PM_RESOURCE_TYPE_COUNT); + if (reservations == NULL) { + return -ENOMEM; + } + + for (i = 0; i < NVGPU_PROFILER_PM_RESOURCE_TYPE_COUNT; i++) { + nvgpu_init_list_node(&reservations[i].head); + nvgpu_mutex_init(&reservations[i].lock); + } + + g->pm_reservations = reservations; + + nvgpu_log(g, gpu_dbg_prof, "initialized"); + + return 0; +} + +void nvgpu_pm_reservation_deinit(struct gk20a *g) +{ + nvgpu_kfree(g, g->pm_reservations); +} diff --git a/drivers/gpu/nvgpu/common/profiler/profiler.c b/drivers/gpu/nvgpu/common/profiler/profiler.c index 6e6e84184..19f51b9c4 100644 --- a/drivers/gpu/nvgpu/common/profiler/profiler.c +++ b/drivers/gpu/nvgpu/common/profiler/profiler.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -33,7 +34,8 @@ static int generate_unique_id(void) } int nvgpu_profiler_alloc(struct gk20a *g, - struct nvgpu_profiler_object **_prof) + struct nvgpu_profiler_object **_prof, + enum nvgpu_profiler_pm_reservation_scope scope) { struct nvgpu_profiler_object *prof; *_prof = NULL; @@ -46,6 +48,7 @@ int nvgpu_profiler_alloc(struct gk20a *g, } prof->prof_handle = generate_unique_id(); + prof->scope = scope; prof->g = g; nvgpu_init_list_node(&prof->prof_obj_entry); @@ -68,3 +71,73 @@ void nvgpu_profiler_free(struct nvgpu_profiler_object *prof) nvgpu_list_del(&prof->prof_obj_entry); nvgpu_kfree(g, prof); } + +int nvgpu_profiler_pm_resource_reserve(struct nvgpu_profiler_object *prof, + enum nvgpu_profiler_pm_resource_type pm_resource) +{ + struct gk20a *g = prof->g; + enum nvgpu_profiler_pm_reservation_scope scope = prof->scope; + u32 reservation_id = prof->prof_handle; + int err; + + nvgpu_log(g, gpu_dbg_prof, + "Request reservation for profiler handle %u, resource %u, scope %u", + prof->prof_handle, pm_resource, prof->scope); + + if (prof->reserved[pm_resource]) { + nvgpu_err(g, "Profiler handle %u already has the reservation", + prof->prof_handle); + return -EEXIST; + } + + err = g->ops.pm_reservation.acquire(g, reservation_id, pm_resource, + scope, 0); + if (err != 0) { + nvgpu_err(g, "Profiler handle %u denied the reservation, err %d", + prof->prof_handle, err); + return err; + } + + prof->reserved[pm_resource] = true; + + nvgpu_log(g, gpu_dbg_prof, + "Granted reservation for profiler handle %u, resource %u, scope %u", + prof->prof_handle, pm_resource, prof->scope); + + return 0; +} + +int nvgpu_profiler_pm_resource_release(struct nvgpu_profiler_object *prof, + enum nvgpu_profiler_pm_resource_type pm_resource) +{ + struct gk20a *g = prof->g; + u32 reservation_id = prof->prof_handle; + int err; + + nvgpu_log(g, gpu_dbg_prof, + "Release reservation for profiler handle %u, resource %u, scope %u", + prof->prof_handle, pm_resource, prof->scope); + + if (!prof->reserved[pm_resource]) { + nvgpu_log(g, gpu_dbg_prof, + "Profiler handle %u resource is not reserved", + prof->prof_handle); + return -EINVAL; + } + + err = g->ops.pm_reservation.release(g, reservation_id, pm_resource, 0); + if (err != 0) { + nvgpu_err(g, "Profiler handle %u does not have valid reservation, err %d", + prof->prof_handle, err); + prof->reserved[pm_resource] = false; + return err; + } + + prof->reserved[pm_resource] = false; + + nvgpu_log(g, gpu_dbg_prof, + "Released reservation for profiler handle %u, resource %u, scope %u", + prof->prof_handle, pm_resource, prof->scope); + + return 0; +} diff --git a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c index e76154d10..b8b851ba9 100644 --- a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c +++ b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.c @@ -118,82 +118,3 @@ int vgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, err = err ? err : msg.ret; return err; } - -static int vgpu_sendrecv_prof_cmd(struct dbg_session_gk20a *dbg_s, u32 mode) -{ - struct tegra_vgpu_cmd_msg msg; - struct tegra_vgpu_prof_mgt_params *p = &msg.params.prof_management; - int err = 0; - - msg.cmd = TEGRA_VGPU_CMD_PROF_MGT; - msg.handle = vgpu_get_handle(dbg_s->g); - - p->mode = mode; - - err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); - err = err ? err : msg.ret; - return err; -} - -bool vgpu_check_and_set_global_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - if (g->profiler_reservation_count > 0) { - return false; - } - - /* Check that another guest OS doesn't already have a reservation */ - if (!vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_GET_GLOBAL)) { - g->global_profiler_reservation_held = true; - g->profiler_reservation_count = 1; - dbg_s->has_profiler_reservation = true; - prof_obj->has_reservation = true; - return true; - } - return false; -} - -bool vgpu_check_and_set_context_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - /* Assumes that we've already checked that no global reservation - * is in effect for this guest. - * - * If our reservation count is non-zero, then no other guest has the - * global reservation; if it is zero, need to check with RM server. - * - */ - if ((g->profiler_reservation_count != 0) || - !vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_GET_CONTEXT)) { - g->profiler_reservation_count++; - dbg_s->has_profiler_reservation = true; - prof_obj->has_reservation = true; - return true; - } - return false; -} - -void vgpu_release_profiler_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj) -{ - struct gk20a *g = dbg_s->g; - - dbg_s->has_profiler_reservation = false; - prof_obj->has_reservation = false; - if (prof_obj->tsg == NULL) { - g->global_profiler_reservation_held = false; - } - - /* If new reservation count is zero, notify server */ - g->profiler_reservation_count--; - if (g->profiler_reservation_count == 0) { - vgpu_sendrecv_prof_cmd(dbg_s, TEGRA_VGPU_PROF_RELEASE); - } -} diff --git a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.h b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.h index c7201a12c..439ff0788 100644 --- a/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.h +++ b/drivers/gpu/nvgpu/common/vgpu/debugger_vgpu.h @@ -37,14 +37,5 @@ int vgpu_exec_regops(struct gk20a *g, bool *is_current_ctx); int vgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate); -bool vgpu_check_and_set_global_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); -bool vgpu_check_and_set_context_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); -void vgpu_release_profiler_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); #endif /* NVGPU_DBG_VGPU_H */ diff --git a/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.c b/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.c new file mode 100644 index 000000000..25d7d3b7b --- /dev/null +++ b/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.c @@ -0,0 +1,72 @@ +/* + * 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 "pm_reservation_vgpu.h" +#include "common/vgpu/ivc/comm_vgpu.h" + +int vgpu_pm_reservation_acquire(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 vmid) +{ + struct tegra_vgpu_cmd_msg msg; + struct tegra_vgpu_prof_mgt_params *p = &msg.params.prof_management; + int err = 0; + + msg.cmd = TEGRA_VGPU_CMD_PROF_MGT; + msg.handle = vgpu_get_handle(g); + + p->mode = TEGRA_VGPU_PROF_PM_RESERVATION_ACQUIRE; + p->reservation_id = reservation_id; + p->pm_resource = pm_resource; + p->scope = scope; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + return err; +} + +int vgpu_pm_reservation_release(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + u32 vmid) +{ + struct tegra_vgpu_cmd_msg msg; + struct tegra_vgpu_prof_mgt_params *p = &msg.params.prof_management; + int err = 0; + + msg.cmd = TEGRA_VGPU_CMD_PROF_MGT; + msg.handle = vgpu_get_handle(g); + + p->mode = TEGRA_VGPU_PROF_PM_RESERVATION_RELEASE; + p->reservation_id = reservation_id; + p->pm_resource = pm_resource; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + return err; +} diff --git a/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.h b/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.h new file mode 100644 index 000000000..e7f9103ba --- /dev/null +++ b/drivers/gpu/nvgpu/common/vgpu/pm_reservation_vgpu.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_PM_RESERVATION_VGPU_H +#define NVGPU_PM_RESERVATION_VGPU_H + +#include + +struct gk20a; +enum nvgpu_profiler_pm_resource_type; +enum nvgpu_profiler_pm_reservation_scope; + +int vgpu_pm_reservation_acquire(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 vmid); +int vgpu_pm_reservation_release(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + u32 vmid); + +#endif /* NVGPU_PM_RESERVATION_VGPU_H */ diff --git a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c index d0efacb91..265836be2 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -996,12 +997,6 @@ static const struct gpu_ops gm20b_ops = { .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = nvgpu_dbg_set_powergate, - .check_and_set_global_reservation = - nvgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - nvgpu_check_and_set_context_reservation, - .release_profiler_reservation = - nvgpu_release_profiler_reservation, }, .perf = { .enable_membuf = gm20b_perf_enable_membuf, @@ -1018,6 +1013,14 @@ static const struct gpu_ops gm20b_ops = { .perfbuf_enable = nvgpu_perfbuf_enable_locked, .perfbuf_disable = nvgpu_perfbuf_disable_locked, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = nvgpu_pm_reservation_acquire, + .release = nvgpu_pm_reservation_release, + .release_all_per_vmid = + nvgpu_pm_reservation_release_all_per_vmid, + }, #endif .bus = { .init_hw = gk20a_bus_init_hw, @@ -1189,6 +1192,9 @@ int gm20b_init_hal(struct gk20a *g) gops->regops = gm20b_ops.regops; gops->perf = gm20b_ops.perf; gops->perfbuf = gm20b_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = gm20b_ops.pm_reservation; #endif gops->bus = gm20b_ops.bus; gops->ptimer = gm20b_ops.ptimer; diff --git a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c index a8de45a15..236cf103d 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1098,12 +1099,6 @@ static const struct gpu_ops gp10b_ops = { .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = nvgpu_dbg_set_powergate, - .check_and_set_global_reservation = - nvgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - nvgpu_check_and_set_context_reservation, - .release_profiler_reservation = - nvgpu_release_profiler_reservation, }, .perf = { .enable_membuf = gm20b_perf_enable_membuf, @@ -1120,6 +1115,14 @@ static const struct gpu_ops gp10b_ops = { .perfbuf_enable = nvgpu_perfbuf_enable_locked, .perfbuf_disable = nvgpu_perfbuf_disable_locked, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = nvgpu_pm_reservation_acquire, + .release = nvgpu_pm_reservation_release, + .release_all_per_vmid = + nvgpu_pm_reservation_release_all_per_vmid, + }, #endif .bus = { .init_hw = gk20a_bus_init_hw, @@ -1289,6 +1292,9 @@ int gp10b_init_hal(struct gk20a *g) gops->regops = gp10b_ops.regops; gops->perf = gp10b_ops.perf; gops->perfbuf = gp10b_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = gp10b_ops.pm_reservation; #endif gops->bus = gp10b_ops.bus; gops->ptimer = gp10b_ops.ptimer; diff --git a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c index f1cabc3f0..e0390f91a 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c @@ -195,6 +195,7 @@ #include #include #include +#include #include #include #include @@ -1359,12 +1360,6 @@ NVGPU_COV_WHITELIST_BLOCK_END(NVGPU_MISRA(Rule, 8_7)) .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = nvgpu_dbg_set_powergate, - .check_and_set_global_reservation = - nvgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - nvgpu_check_and_set_context_reservation, - .release_profiler_reservation = - nvgpu_release_profiler_reservation, }, .perf = { .enable_membuf = gv11b_perf_enable_membuf, @@ -1381,6 +1376,14 @@ NVGPU_COV_WHITELIST_BLOCK_END(NVGPU_MISRA(Rule, 8_7)) .perfbuf_enable = nvgpu_perfbuf_enable_locked, .perfbuf_disable = nvgpu_perfbuf_disable_locked, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = nvgpu_pm_reservation_acquire, + .release = nvgpu_pm_reservation_release, + .release_all_per_vmid = + nvgpu_pm_reservation_release_all_per_vmid, + }, #endif .bus = { .init_hw = gk20a_bus_init_hw, @@ -1545,6 +1548,9 @@ int gv11b_init_hal(struct gk20a *g) gops->regops = gv11b_ops.regops; gops->perf = gv11b_ops.perf; gops->perfbuf = gv11b_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = gv11b_ops.pm_reservation; #endif gops->bus = gv11b_ops.bus; gops->ptimer = gv11b_ops.ptimer; diff --git a/drivers/gpu/nvgpu/hal/init/hal_tu104.c b/drivers/gpu/nvgpu/hal/init/hal_tu104.c index 45f755c1e..e8528e0df 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_tu104.c +++ b/drivers/gpu/nvgpu/hal/init/hal_tu104.c @@ -218,6 +218,7 @@ #include #include #include +#include #include #include #include @@ -1400,12 +1401,6 @@ static const struct gpu_ops tu104_ops = { .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = nvgpu_dbg_set_powergate, - .check_and_set_global_reservation = - nvgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - nvgpu_check_and_set_context_reservation, - .release_profiler_reservation = - nvgpu_release_profiler_reservation, }, .perf = { .enable_membuf = gv11b_perf_enable_membuf, @@ -1422,6 +1417,14 @@ static const struct gpu_ops tu104_ops = { .perfbuf_enable = nvgpu_perfbuf_enable_locked, .perfbuf_disable = nvgpu_perfbuf_disable_locked, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = nvgpu_pm_reservation_acquire, + .release = nvgpu_pm_reservation_release, + .release_all_per_vmid = + nvgpu_pm_reservation_release_all_per_vmid, + }, #endif .bus = { .init_hw = tu104_bus_init_hw, @@ -1674,6 +1677,9 @@ int tu104_init_hal(struct gk20a *g) gops->regops = tu104_ops.regops; gops->perf = tu104_ops.perf; gops->perfbuf = tu104_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = tu104_ops.pm_reservation; #endif gops->bus = tu104_ops.bus; gops->ptimer = tu104_ops.ptimer; diff --git a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gp10b.c b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gp10b.c index e613cb220..7a8d637fc 100644 --- a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gp10b.c +++ b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gp10b.c @@ -106,6 +106,7 @@ #include "common/vgpu/mm/mm_vgpu.h" #include "common/vgpu/cbc/cbc_vgpu.h" #include "common/vgpu/debugger_vgpu.h" +#include "common/vgpu/pm_reservation_vgpu.h" #include "common/vgpu/gr/fecs_trace_vgpu.h" #include "common/vgpu/perf/perf_vgpu.h" #include "common/vgpu/perf/cyclestats_snapshot_vgpu.h" @@ -775,12 +776,6 @@ static const struct gpu_ops vgpu_gp10b_ops = { .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = vgpu_dbg_set_powergate, - .check_and_set_global_reservation = - vgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - vgpu_check_and_set_context_reservation, - .release_profiler_reservation = - vgpu_release_profiler_reservation, }, .perf = { .get_pmm_per_chiplet_offset = @@ -790,6 +785,13 @@ static const struct gpu_ops vgpu_gp10b_ops = { .perfbuf_enable = vgpu_perfbuffer_enable, .perfbuf_disable = vgpu_perfbuffer_disable, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = vgpu_pm_reservation_acquire, + .release = vgpu_pm_reservation_release, + .release_all_per_vmid = NULL, + }, #endif .bus = { .init_hw = NULL, @@ -904,6 +906,9 @@ int vgpu_gp10b_init_hal(struct gk20a *g) gops->regops = vgpu_gp10b_ops.regops; gops->perf = vgpu_gp10b_ops.perf; gops->perfbuf = vgpu_gp10b_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = vgpu_gp10b_ops.pm_reservation; #endif gops->bus = vgpu_gp10b_ops.bus; gops->ptimer = vgpu_gp10b_ops.ptimer; diff --git a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c index 56151ce7f..04aa12e34 100644 --- a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c +++ b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c @@ -125,6 +125,7 @@ #include "common/vgpu/mm/mm_vgpu.h" #include "common/vgpu/cbc/cbc_vgpu.h" #include "common/vgpu/debugger_vgpu.h" +#include "common/vgpu/pm_reservation_vgpu.h" #include "common/vgpu/perf/perf_vgpu.h" #include "common/vgpu/gr/fecs_trace_vgpu.h" #include "common/vgpu/perf/cyclestats_snapshot_vgpu.h" @@ -901,12 +902,6 @@ static const struct gpu_ops vgpu_gv11b_ops = { .debugger = { .post_events = nvgpu_dbg_gpu_post_events, .dbg_set_powergate = vgpu_dbg_set_powergate, - .check_and_set_global_reservation = - vgpu_check_and_set_global_reservation, - .check_and_set_context_reservation = - vgpu_check_and_set_context_reservation, - .release_profiler_reservation = - vgpu_release_profiler_reservation, }, .perf = { .get_pmm_per_chiplet_offset = @@ -916,6 +911,13 @@ static const struct gpu_ops vgpu_gv11b_ops = { .perfbuf_enable = vgpu_perfbuffer_enable, .perfbuf_disable = vgpu_perfbuffer_disable, }, +#endif +#ifdef CONFIG_NVGPU_PROFILER + .pm_reservation = { + .acquire = vgpu_pm_reservation_acquire, + .release = vgpu_pm_reservation_release, + .release_all_per_vmid = NULL, + }, #endif .bus = { .init_hw = NULL, @@ -1026,6 +1028,9 @@ int vgpu_gv11b_init_hal(struct gk20a *g) gops->regops = vgpu_gv11b_ops.regops; gops->perf = vgpu_gv11b_ops.perf; gops->perfbuf = vgpu_gv11b_ops.perfbuf; +#endif +#ifdef CONFIG_NVGPU_PROFILER + gops->pm_reservation = vgpu_gv11b_ops.pm_reservation; #endif gops->bus = vgpu_gv11b_ops.bus; gops->ptimer = vgpu_gv11b_ops.ptimer; diff --git a/drivers/gpu/nvgpu/include/nvgpu/debugger.h b/drivers/gpu/nvgpu/include/nvgpu/debugger.h index 78c0f6673..c964ff97b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/debugger.h +++ b/drivers/gpu/nvgpu/include/nvgpu/debugger.h @@ -51,9 +51,6 @@ struct dbg_session_gk20a { /* profiler session, if any */ bool is_profiler; - /* has a valid profiler reservation */ - bool has_profiler_reservation; - /* power enabled or disabled */ bool is_pg_disabled; @@ -109,14 +106,6 @@ bool nvgpu_dbg_gpu_broadcast_stop_trigger(struct nvgpu_channel *ch); void nvgpu_dbg_gpu_clear_broadcast_stop_trigger(struct nvgpu_channel *ch); int nvgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate); -bool nvgpu_check_and_set_global_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); -bool nvgpu_check_and_set_context_reservation( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); -void nvgpu_release_profiler_reservation(struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s); u32 nvgpu_set_powergate_locked(struct dbg_session_gk20a *dbg_s, diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index ae4a85eae..1fbcb7122 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -112,6 +112,8 @@ enum nvgpu_flush_op; enum gk20a_mem_rw_flag; enum nvgpu_nvlink_minion_dlcmd; enum nvgpu_unit; +enum nvgpu_profiler_pm_resource_type; +enum nvgpu_profiler_pm_reservation_scope; #include #include @@ -437,15 +439,6 @@ struct gpu_ops { void (*post_events)(struct nvgpu_channel *ch); int (*dbg_set_powergate)(struct dbg_session_gk20a *dbg_s, bool disable_powergate); - bool (*check_and_set_global_reservation)( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); - bool (*check_and_set_context_reservation)( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); - void (*release_profiler_reservation)( - struct dbg_session_gk20a *dbg_s, - struct nvgpu_profiler_object *prof_obj); } debugger; struct { void (*enable_membuf)(struct gk20a *g, u32 size, @@ -463,6 +456,18 @@ struct gpu_ops { int (*perfbuf_disable)(struct gk20a *g); } perfbuf; #endif +#ifdef CONFIG_NVGPU_PROFILER + struct { + int (*acquire)(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 vmid); + int (*release)(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + u32 vmid); + void (*release_all_per_vmid)(struct gk20a *g, u32 vmid); + } pm_reservation; +#endif u32 (*get_litter_value)(struct gk20a *g, int value); int (*chip_init_gpu_characteristics)(struct gk20a *g); @@ -831,16 +836,13 @@ struct gk20a { u64 offset; } perfbuf; - /* For profiler reservations */ - bool global_profiler_reservation_held; - int profiler_reservation_count; - bool mmu_debug_ctrl; u32 mmu_debug_mode_refcnt; #endif /* CONFIG_NVGPU_DEBUGGER */ #ifdef CONFIG_NVGPU_PROFILER struct nvgpu_list_node profiler_objects; + struct nvgpu_pm_resource_reservations *pm_reservations; #endif #ifdef CONFIG_NVGPU_FECS_TRACE diff --git a/drivers/gpu/nvgpu/include/nvgpu/pm_reservation.h b/drivers/gpu/nvgpu/include/nvgpu/pm_reservation.h new file mode 100644 index 000000000..4d9c9d898 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/pm_reservation.h @@ -0,0 +1,79 @@ +/* + * 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_PM_RESERVATION_H +#define NVGPU_PM_RESERVATION_H + +#ifdef CONFIG_NVGPU_PROFILER + +#include +#include + +struct gk20a; + +enum nvgpu_profiler_pm_reservation_scope { + NVGPU_PROFILER_PM_RESERVATION_SCOPE_DEVICE, + NVGPU_PROFILER_PM_RESERVATION_SCOPE_CONTEXT, +}; + +enum nvgpu_profiler_pm_resource_type { + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY, + NVGPU_PROFILER_PM_RESOURCE_TYPE_SMPC, + NVGPU_PROFILER_PM_RESOURCE_TYPE_PMA_STREAM, + NVGPU_PROFILER_PM_RESOURCE_TYPE_COUNT, +}; + +struct nvgpu_pm_resource_reservation_entry { + struct nvgpu_list_node entry; + + u32 reservation_id; + u32 vmid; + enum nvgpu_profiler_pm_reservation_scope scope; +}; + +static inline struct nvgpu_pm_resource_reservation_entry * +nvgpu_pm_resource_reservation_entry_from_entry(struct nvgpu_list_node *node) +{ + return (struct nvgpu_pm_resource_reservation_entry *) + ((uintptr_t)node - offsetof(struct nvgpu_pm_resource_reservation_entry, entry)); +} + +struct nvgpu_pm_resource_reservations { + struct nvgpu_list_node head; + u32 count; + struct nvgpu_mutex lock; +}; + +int nvgpu_pm_reservation_init(struct gk20a *g); +void nvgpu_pm_reservation_deinit(struct gk20a *g); + +int nvgpu_pm_reservation_acquire(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + enum nvgpu_profiler_pm_reservation_scope scope, + u32 vmid); +int nvgpu_pm_reservation_release(struct gk20a *g, u32 reservation_id, + enum nvgpu_profiler_pm_resource_type pm_resource, + u32 vmid); +void nvgpu_pm_reservation_release_all_per_vmid(struct gk20a *g, u32 vmid); + +#endif /* CONFIG_NVGPU_PROFILER */ +#endif /* NVGPU_PM_RESERVATION_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/profiler.h b/drivers/gpu/nvgpu/include/nvgpu/profiler.h index 7014bedc0..00861d526 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/profiler.h +++ b/drivers/gpu/nvgpu/include/nvgpu/profiler.h @@ -26,6 +26,7 @@ #ifdef CONFIG_NVGPU_PROFILER #include +#include struct gk20a; struct nvgpu_channel; @@ -48,8 +49,11 @@ struct nvgpu_profiler_object { */ struct nvgpu_tsg *tsg; - /* If profiler object has HWPM reservation. */ - bool has_reservation; + /* If profiler object has reservation for each resource. */ + bool reserved[NVGPU_PROFILER_PM_RESOURCE_TYPE_COUNT]; + + /* Scope of the profiler object */ + enum nvgpu_profiler_pm_reservation_scope scope; /* * Entry of this object into global list of objects @@ -66,8 +70,14 @@ nvgpu_profiler_object_from_prof_obj_entry(struct nvgpu_list_node *node) }; int nvgpu_profiler_alloc(struct gk20a *g, - struct nvgpu_profiler_object **_prof); + struct nvgpu_profiler_object **_prof, + enum nvgpu_profiler_pm_reservation_scope scope); void nvgpu_profiler_free(struct nvgpu_profiler_object *prof); +int nvgpu_profiler_pm_resource_reserve(struct nvgpu_profiler_object *prof, + enum nvgpu_profiler_pm_resource_type pm_resource); +int nvgpu_profiler_pm_resource_release(struct nvgpu_profiler_object *prof, + enum nvgpu_profiler_pm_resource_type pm_resource); + #endif /* CONFIG_NVGPU_PROFILER */ #endif /* NVGPU_PROFILER_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h index 535aceeab..1538d730b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h @@ -564,13 +564,15 @@ struct tegra_vgpu_clear_sm_error_state { }; enum { - TEGRA_VGPU_PROF_GET_GLOBAL = 0, - TEGRA_VGPU_PROF_GET_CONTEXT, - TEGRA_VGPU_PROF_RELEASE + TEGRA_VGPU_PROF_PM_RESERVATION_ACQUIRE = 0, + TEGRA_VGPU_PROF_PM_RESERVATION_RELEASE, }; struct tegra_vgpu_prof_mgt_params { u32 mode; + u32 reservation_id; + u32 pm_resource; + u32 scope; }; struct tegra_vgpu_perfbuf_mgt_params { diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c index 4167c87ad..00839a299 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c @@ -210,11 +210,9 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp) nvgpu_list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, nvgpu_profiler_object, prof_obj_entry) { if (prof_obj->session_id == dbg_s->id) { - 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_pm_resource_release(prof_obj, + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY); + nvgpu_profiler_free(prof_obj); } } nvgpu_mutex_release(&g->dbg_sessions_lock); @@ -460,12 +458,9 @@ static int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, nvgpu_profiler_object, prof_obj_entry) { if ((prof_obj->session_id == dbg_s->id) && (prof_obj->tsg->tsgid == ch->tsgid)) { - 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_pm_resource_release(prof_obj, + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY); + nvgpu_profiler_free(prof_obj); } } @@ -1025,6 +1020,8 @@ static int nvgpu_dbg_gpu_ioctl_hwpm_ctxsw_mode(struct dbg_session_gk20a *dbg_s, struct nvgpu_channel *ch_gk20a; struct nvgpu_tsg *tsg; u32 mode = nvgpu_hwpm_ctxsw_mode_to_common_mode(args->mode); + struct nvgpu_profiler_object *prof_obj, *tmp_obj; + bool reserved = false; nvgpu_log_fn(g, "%s pm ctxsw mode = %d", g->name, args->mode); @@ -1033,9 +1030,17 @@ static int nvgpu_dbg_gpu_ioctl_hwpm_ctxsw_mode(struct dbg_session_gk20a *dbg_s, * return an error, at the point where all client sw has been * cleaned up. */ - if (!dbg_s->has_profiler_reservation) { - nvgpu_err(g, - "session doesn't have a valid reservation"); + nvgpu_list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, + nvgpu_profiler_object, prof_obj_entry) { + if (prof_obj->session_id == dbg_s->id) { + if (prof_obj->reserved[NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY]) { + reserved = true; + } + } + } + + if (!reserved) { + nvgpu_err(g, "session doesn't have a valid reservation"); } err = gk20a_busy(g); @@ -1191,6 +1196,7 @@ static int nvgpu_ioctl_allocate_profiler_object( struct nvgpu_profiler_object *prof_obj; struct nvgpu_channel *ch = NULL; struct nvgpu_tsg *tsg; + enum nvgpu_profiler_pm_reservation_scope scope; nvgpu_log_fn(g, "%s", g->name); @@ -1205,7 +1211,13 @@ static int nvgpu_ioctl_allocate_profiler_object( } } - err = nvgpu_profiler_alloc(g, &prof_obj); + if (ch != NULL) { + scope = NVGPU_PROFILER_PM_RESERVATION_SCOPE_CONTEXT; + } else { + scope = NVGPU_PROFILER_PM_RESERVATION_SCOPE_DEVICE; + } + + err = nvgpu_profiler_alloc(g, &prof_obj, scope); if (err != 0) { goto clean_up; } @@ -1256,9 +1268,8 @@ static int nvgpu_ioctl_free_profiler_object( err = -EINVAL; break; } - if (prof_obj->has_reservation) - g->ops.debugger. - release_profiler_reservation(dbg_s, prof_obj); + nvgpu_profiler_pm_resource_release(prof_obj, + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY); nvgpu_profiler_free(prof_obj); obj_found = true; break; @@ -1716,13 +1727,9 @@ static int nvgpu_profiler_reserve_release(struct dbg_session_gk20a *dbg_s, goto exit; } - if (prof_obj->has_reservation) - g->ops.debugger.release_profiler_reservation(dbg_s, prof_obj); - else { - nvgpu_err(g, "No reservation found"); - err = -EINVAL; - goto exit; - } + err = nvgpu_profiler_pm_resource_release(prof_obj, + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY); + exit: nvgpu_mutex_release(&g->dbg_sessions_lock); return err; @@ -1732,73 +1739,42 @@ static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, u32 profiler_handle) { struct gk20a *g = dbg_s->g; - struct nvgpu_profiler_object *prof_obj, *my_prof_obj; + struct nvgpu_profiler_object *prof_obj; int err = 0; nvgpu_log_fn(g, "%s profiler_handle = %x", g->name, profiler_handle); - if (g->profiler_reservation_count < 0) { - nvgpu_err(g, "Negative reservation count!"); - return -EINVAL; - } - nvgpu_mutex_acquire(&g->dbg_sessions_lock); /* Find matching object. */ - my_prof_obj = find_matching_prof_obj(dbg_s, profiler_handle); + prof_obj = find_matching_prof_obj(dbg_s, profiler_handle); - if (!my_prof_obj) { + if (!prof_obj) { nvgpu_err(g, "object not found"); err = -EINVAL; goto exit; } - /* If we already have the reservation, we're done */ - if (my_prof_obj->has_reservation) { - err = 0; - goto exit; - } + if (prof_obj->tsg != NULL) { + struct nvgpu_tsg *tsg = prof_obj->tsg; + struct nvgpu_profiler_object *tmp_obj; - if (my_prof_obj->tsg == NULL) { - /* Global reservations are only allowed if there are no other - * global or per-context reservations currently held - */ - if (!g->ops.debugger.check_and_set_global_reservation( - dbg_s, my_prof_obj)) { - nvgpu_err(g, - "global reserve: have existing reservation"); - err = -EBUSY; - } - } else if (g->global_profiler_reservation_held) { - /* If there's a global reservation, - * we can't take a per-context one. - */ - nvgpu_err(g, - "per-ctxt reserve: global reservation in effect"); - err = -EBUSY; - } 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, + nvgpu_list_for_each_entry(tmp_obj, &g->profiler_objects, nvgpu_profiler_object, prof_obj_entry) { - if (prof_obj->has_reservation && - (prof_obj->tsg->tsgid == my_tsgid)) { - nvgpu_err(g, - "per-ctxt reserve (tsg): already reserved"); - err = -EBUSY; + if (tmp_obj->tsg == NULL) { + continue; + } + if ((tmp_obj->tsg->tsgid == tsg->tsgid) && + tmp_obj->reserved[NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY]) { + err = -EINVAL; goto exit; } } - - 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; - } } + + err = nvgpu_profiler_pm_resource_reserve(prof_obj, + NVGPU_PROFILER_PM_RESOURCE_TYPE_HWPM_LEGACY); + exit: nvgpu_mutex_release(&g->dbg_sessions_lock); return err;