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 <dnibade@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2367224
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Deepak Nibade
2020-04-30 16:23:44 +05:30
committed by Alex Waterman
parent b21116485f
commit 08308bc936
24 changed files with 666 additions and 278 deletions

View File

@@ -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

View File

@@ -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,

View File

@@ -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 \

View File

@@ -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 \

View File

@@ -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;
}
}

View File

@@ -40,6 +40,7 @@
#include <nvgpu/nvhost.h>
#include <nvgpu/fb.h>
#include <nvgpu/device.h>
#include <nvgpu/pm_reservation.h>
#ifdef CONFIG_NVGPU_LS_PMU
#include <nvgpu/pmu/pmu_pstate.h>
@@ -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) {

View File

@@ -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 <nvgpu/gk20a.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/log.h>
#include <nvgpu/kmem.h>
#include <nvgpu/lock.h>
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);
}

View File

@@ -21,6 +21,7 @@
*/
#include <nvgpu/gk20a.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/profiler.h>
#include <nvgpu/atomic.h>
#include <nvgpu/log.h>
@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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 */

View File

@@ -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 <nvgpu/vgpu/vgpu_ivc.h>
#include <nvgpu/vgpu/tegra_vgpu.h>
#include <nvgpu/vgpu/vgpu.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/pm_reservation.h>
#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;
}

View File

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

View File

@@ -25,6 +25,7 @@
#include <nvgpu/error_notifier.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/debugger.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/runlist.h>
#include <nvgpu/pbdma.h>
#include <nvgpu/engines.h>
@@ -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;

View File

@@ -25,6 +25,7 @@
#include <nvgpu/error_notifier.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/debugger.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/pbdma.h>
#include <nvgpu/engines.h>
#include <nvgpu/runlist.h>
@@ -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;

View File

@@ -195,6 +195,7 @@
#include <nvgpu/ptimer.h>
#include <nvgpu/error_notifier.h>
#include <nvgpu/debugger.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/runlist.h>
#include <nvgpu/fifo/userd.h>
#include <nvgpu/perfbuf.h>
@@ -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;

View File

@@ -218,6 +218,7 @@
#include <nvgpu/clk_arb.h>
#include <nvgpu/class.h>
#include <nvgpu/debugger.h>
#include <nvgpu/pm_reservation.h>
#include <nvgpu/pbdma.h>
#include <nvgpu/engines.h>
#include <nvgpu/runlist.h>
@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 <nvgpu/lock.h>
#include <nvgpu/thread.h>
@@ -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

View File

@@ -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 <nvgpu/list.h>
#include <nvgpu/lock.h>
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 */

View File

@@ -26,6 +26,7 @@
#ifdef CONFIG_NVGPU_PROFILER
#include <nvgpu/list.h>
#include <nvgpu/pm_reservation.h>
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 */

View File

@@ -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 {

View File

@@ -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;