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;