From 9751fb0b5405bb283f5bd884115465443f5f8608 Mon Sep 17 00:00:00 2001 From: Antony Clince Alex Date: Tue, 29 May 2018 15:29:06 +0530 Subject: gpu: nvgpu: vgpu: Unified CSS VGPU HAL - defined platform agnostic wrapper for mempool mapping and unmapping. - used platform agnositc wrapper for device tree parsing. - modified css_gr_gk20a to include special handling incase of rm-server JIRA: VQRM:3699 Change-Id: I08fd26052edfa1edf45a67be57f7d27c38ad106a Signed-off-by: Antony Clince Alex Reviewed-on: https://git-master.nvidia.com/r/1733576 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile | 8 +- drivers/gpu/nvgpu/common/linux/vgpu/css_vgpu.c | 236 --------------------- drivers/gpu/nvgpu/common/linux/vgpu/vgpu_ivm.c | 15 ++ drivers/gpu/nvgpu/gk20a/css_gr_gk20a.c | 27 ++- drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h | 6 + drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu_ivm.h | 4 +- drivers/gpu/nvgpu/vgpu/css_vgpu.c | 237 ++++++++++++++++++++++ 7 files changed, 283 insertions(+), 250 deletions(-) delete mode 100644 drivers/gpu/nvgpu/common/linux/vgpu/css_vgpu.c create mode 100644 drivers/gpu/nvgpu/vgpu/css_vgpu.c diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 9f58d6ef..e219df98 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -95,6 +95,8 @@ nvgpu-y += \ common/clock_gating/gp10b_gating_reglist.o \ common/clock_gating/gv100_gating_reglist.o \ common/clock_gating/gv11b_gating_reglist.o \ + common/sim.o \ + common/sim_pci.o \ gk20a/gk20a.o \ gk20a/ce2_gk20a.o \ gk20a/fifo_gk20a.o \ @@ -133,9 +135,7 @@ nvgpu-y += \ boardobj/boardobjgrp.o \ boardobj/boardobjgrpmask.o \ boardobj/boardobjgrp_e255.o \ - boardobj/boardobjgrp_e32.o \ - common/sim.o \ - common/sim_pci.o + boardobj/boardobjgrp_e32.o nvgpu-$(CONFIG_GK20A_VIDMEM) += \ common/mm/vidmem.o \ @@ -192,6 +192,7 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \ vgpu/vgpu.o \ vgpu/dbg_vgpu.o \ vgpu/tsg_vgpu.o \ + vgpu/css_vgpu.o \ vgpu/gm20b/vgpu_gr_gm20b.o \ vgpu/gp10b/vgpu_hal_gp10b.o \ vgpu/gp10b/vgpu_gr_gp10b.o \ @@ -206,7 +207,6 @@ nvgpu-$(CONFIG_TEGRA_GR_VIRTUALIZATION) += \ common/linux/vgpu/platform_vgpu_tegra.o \ common/linux/vgpu/fecs_trace_vgpu.o \ common/linux/vgpu/clk_vgpu.o \ - common/linux/vgpu/css_vgpu.o \ common/linux/vgpu/sysfs_vgpu.o \ common/linux/vgpu/vgpu_ivc.o \ common/linux/vgpu/vgpu_ivm.o \ diff --git a/drivers/gpu/nvgpu/common/linux/vgpu/css_vgpu.c b/drivers/gpu/nvgpu/common/linux/vgpu/css_vgpu.c deleted file mode 100644 index ba2bf58b..00000000 --- a/drivers/gpu/nvgpu/common/linux/vgpu/css_vgpu.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#if defined(CONFIG_GK20A_CYCLE_STATS) - -#include -#include -#include -#include - -#include "gk20a/gk20a.h" -#include "gk20a/channel_gk20a.h" -#include "gk20a/css_gr_gk20a.h" -#include "common/linux/platform_gk20a.h" -#include "common/linux/os_linux.h" -#include "vgpu/css_vgpu.h" - -static struct tegra_hv_ivm_cookie *css_cookie; - -static struct tegra_hv_ivm_cookie *vgpu_css_reserve_mempool(struct gk20a *g) -{ - struct device *dev = dev_from_gk20a(g); - struct device_node *np = dev->of_node; - struct of_phandle_args args; - struct tegra_hv_ivm_cookie *cookie; - u32 mempool; - int err; - - err = of_parse_phandle_with_fixed_args(np, - "mempool-css", 1, 0, &args); - if (err) { - nvgpu_err(g, "dt missing mempool-css"); - return ERR_PTR(err); - } - - mempool = args.args[0]; - cookie = vgpu_ivm_mempool_reserve(mempool); - if (IS_ERR_OR_NULL(cookie)) { - nvgpu_err(g, "mempool %u reserve failed", mempool); - return ERR_PTR(-EINVAL); - } - return cookie; -} - -u32 vgpu_css_get_buffer_size(struct gk20a *g) -{ - struct tegra_hv_ivm_cookie *cookie; - u32 size; - - nvgpu_log_fn(g, " "); - - if (css_cookie) { - size = (u32)vgpu_ivm_get_size(css_cookie); - nvgpu_log_info(g, "buffer size = 0x%08x", size); - return size; - } - - cookie = vgpu_css_reserve_mempool(g); - if (IS_ERR(cookie)) - return 0; - - size = vgpu_ivm_get_size(cookie); - - vgpu_ivm_mempool_unreserve(cookie); - nvgpu_log_info(g, "buffer size = 0x%08x", size); - return size; -} - -static int vgpu_css_init_snapshot_buffer(struct gr_gk20a *gr) -{ - struct gk20a *g = gr->g; - struct gk20a_cs_snapshot *data = gr->cs_data; - void *buf = NULL; - int err; - u64 size; - - nvgpu_log_fn(g, " "); - - if (data->hw_snapshot) - return 0; - - css_cookie = vgpu_css_reserve_mempool(g); - if (IS_ERR(css_cookie)) - return PTR_ERR(css_cookie); - - size = vgpu_ivm_get_size(css_cookie); - /* Make sure buffer size is large enough */ - if (size < CSS_MIN_HW_SNAPSHOT_SIZE) { - nvgpu_info(g, "mempool size 0x%llx too small", size); - err = -ENOMEM; - goto fail; - } - - buf = ioremap_cache(vgpu_ivm_get_ipa(css_cookie), size); - if (!buf) { - nvgpu_info(g, "ioremap_cache failed"); - err = -EINVAL; - goto fail; - } - - data->hw_snapshot = buf; - data->hw_end = data->hw_snapshot + - size / sizeof(struct gk20a_cs_snapshot_fifo_entry); - data->hw_get = data->hw_snapshot; - memset(data->hw_snapshot, 0xff, size); - return 0; -fail: - vgpu_ivm_mempool_unreserve(css_cookie); - css_cookie = NULL; - return err; -} - -void vgpu_css_release_snapshot_buffer(struct gr_gk20a *gr) -{ - struct gk20a_cs_snapshot *data = gr->cs_data; - struct gk20a *g = gr->g; - - if (!data->hw_snapshot) - return; - - iounmap(data->hw_snapshot); - data->hw_snapshot = NULL; - - vgpu_ivm_mempool_unreserve(css_cookie); - css_cookie = NULL; - - nvgpu_log_info(g, "cyclestats(vgpu): buffer for snapshots released\n"); -} - -int vgpu_css_flush_snapshots(struct channel_gk20a *ch, - u32 *pending, bool *hw_overflow) -{ - struct gk20a *g = ch->g; - struct tegra_vgpu_cmd_msg msg = {}; - struct tegra_vgpu_channel_cyclestats_snapshot_params *p; - struct gr_gk20a *gr = &g->gr; - struct gk20a_cs_snapshot *data = gr->cs_data; - int err; - - nvgpu_log_fn(g, " "); - - msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; - msg.handle = vgpu_get_handle(g); - p = &msg.params.cyclestats_snapshot; - p->handle = ch->virt_ctx; - p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_FLUSH; - p->buf_info = (uintptr_t)data->hw_get - (uintptr_t)data->hw_snapshot; - - err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); - - err = (err || msg.ret) ? -1 : 0; - - *pending = p->buf_info; - *hw_overflow = p->hw_overflow; - - return err; -} - -static int vgpu_css_attach(struct channel_gk20a *ch, - struct gk20a_cs_snapshot_client *cs_client) -{ - struct gk20a *g = ch->g; - struct tegra_vgpu_cmd_msg msg = {}; - struct tegra_vgpu_channel_cyclestats_snapshot_params *p = - &msg.params.cyclestats_snapshot; - int err; - - nvgpu_log_fn(g, " "); - - msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; - msg.handle = vgpu_get_handle(g); - p->handle = ch->virt_ctx; - p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_ATTACH; - p->perfmon_count = cs_client->perfmon_count; - - err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); - err = err ? err : msg.ret; - if (err) - nvgpu_err(g, "failed"); - else - cs_client->perfmon_start = p->perfmon_start; - - return err; -} - -int vgpu_css_detach(struct channel_gk20a *ch, - struct gk20a_cs_snapshot_client *cs_client) -{ - struct gk20a *g = ch->g; - struct tegra_vgpu_cmd_msg msg = {}; - struct tegra_vgpu_channel_cyclestats_snapshot_params *p = - &msg.params.cyclestats_snapshot; - int err; - - nvgpu_log_fn(g, " "); - - msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; - msg.handle = vgpu_get_handle(g); - p->handle = ch->virt_ctx; - p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_DETACH; - p->perfmon_start = cs_client->perfmon_start; - p->perfmon_count = cs_client->perfmon_count; - - err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); - err = err ? err : msg.ret; - if (err) - nvgpu_err(g, "failed"); - - return err; -} - -int vgpu_css_enable_snapshot_buffer(struct channel_gk20a *ch, - struct gk20a_cs_snapshot_client *cs_client) -{ - int ret; - - ret = vgpu_css_attach(ch, cs_client); - if (ret) - return ret; - - ret = vgpu_css_init_snapshot_buffer(&ch->g->gr); - return ret; -} -#endif /* CONFIG_GK20A_CYCLE_STATS */ diff --git a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_ivm.c b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_ivm.c index 82475cac..90089de8 100644 --- a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_ivm.c +++ b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_ivm.c @@ -15,8 +15,11 @@ */ #include + #include +#include "common/linux/os_linux.h" + struct tegra_hv_ivm_cookie *vgpu_ivm_mempool_reserve(unsigned int id) { return tegra_hv_mempool_reserve(id); @@ -36,3 +39,15 @@ u64 vgpu_ivm_get_size(struct tegra_hv_ivm_cookie *cookie) { return cookie->size; } + +void *vgpu_ivm_mempool_map(struct tegra_hv_ivm_cookie *cookie) +{ + return ioremap_cache(vgpu_ivm_get_ipa(cookie), + vgpu_ivm_get_size(cookie)); +} + +void vgpu_ivm_mempool_unmap(struct tegra_hv_ivm_cookie *cookie, + void *addr) +{ + iounmap(addr); +} diff --git a/drivers/gpu/nvgpu/gk20a/css_gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/css_gr_gk20a.c index 764ffe1a..6fd0d330 100644 --- a/drivers/gpu/nvgpu/gk20a/css_gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/css_gr_gk20a.c @@ -453,15 +453,24 @@ static int css_gr_create_client_data(struct gk20a *g, u32 perfmon_count, struct gk20a_cs_snapshot_client *cur) { - memset(cur->snapshot, 0, sizeof(*cur->snapshot)); - cur->snapshot->start = sizeof(*cur->snapshot); - /* we should be ensure that can fit all fifo entries here */ - cur->snapshot->end = - CSS_FIFO_ENTRY_CAPACITY(cur->snapshot_size) - * sizeof(struct gk20a_cs_snapshot_fifo_entry) - + sizeof(struct gk20a_cs_snapshot_fifo); - cur->snapshot->get = cur->snapshot->start; - cur->snapshot->put = cur->snapshot->start; + /* + * Special handling in-case of rm-server + * + * client snapshot buffer will not be mapped + * in-case of rm-server its only mapped in + * guest side + */ + if (cur->snapshot) { + memset(cur->snapshot, 0, sizeof(*cur->snapshot)); + cur->snapshot->start = sizeof(*cur->snapshot); + /* we should be ensure that can fit all fifo entries here */ + cur->snapshot->end = + CSS_FIFO_ENTRY_CAPACITY(cur->snapshot_size) + * sizeof(struct gk20a_cs_snapshot_fifo_entry) + + sizeof(struct gk20a_cs_snapshot_fifo); + cur->snapshot->get = cur->snapshot->start; + cur->snapshot->put = cur->snapshot->start; + } cur->perfmon_count = perfmon_count; diff --git a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h index 3890249d..3e4372eb 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h @@ -509,6 +509,12 @@ struct tegra_vgpu_constants_params { u32 l2_en_mask[TEGRA_VGPU_L2_EN_MASK]; }; +enum { + TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_FLUSH = 0, + TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_ATTACH = 1, + TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_DETACH = 2, +}; + struct tegra_vgpu_channel_cyclestats_snapshot_params { u64 handle; u32 perfmon_start; diff --git a/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu_ivm.h b/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu_ivm.h index ba2cfc56..cecdd516 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu_ivm.h +++ b/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu_ivm.h @@ -31,5 +31,7 @@ struct tegra_hv_ivm_cookie *vgpu_ivm_mempool_reserve(unsigned int id); int vgpu_ivm_mempool_unreserve(struct tegra_hv_ivm_cookie *cookie); u64 vgpu_ivm_get_ipa(struct tegra_hv_ivm_cookie *cookie); u64 vgpu_ivm_get_size(struct tegra_hv_ivm_cookie *cookie); - +void *vgpu_ivm_mempool_map(struct tegra_hv_ivm_cookie *cookie); +void vgpu_ivm_mempool_unmap(struct tegra_hv_ivm_cookie *cookie, + void *addr); #endif diff --git a/drivers/gpu/nvgpu/vgpu/css_vgpu.c b/drivers/gpu/nvgpu/vgpu/css_vgpu.c new file mode 100644 index 00000000..0e44b81a --- /dev/null +++ b/drivers/gpu/nvgpu/vgpu/css_vgpu.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2017-2018, 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. + */ +#if defined(CONFIG_GK20A_CYCLE_STATS) + +#include +#include +#include +#include + +#include "gk20a/gk20a.h" +#include "gk20a/channel_gk20a.h" +#include "gk20a/css_gr_gk20a.h" + +#include "vgpu/css_vgpu.h" + +static struct tegra_hv_ivm_cookie *css_cookie; + +static struct tegra_hv_ivm_cookie *vgpu_css_reserve_mempool(struct gk20a *g) +{ + struct tegra_hv_ivm_cookie *cookie; + u32 mempool; + int err; + + err = nvgpu_dt_read_u32_index(g, "mempool-css", 1, &mempool); + if (err) { + nvgpu_err(g, "dt missing mempool-css"); + return ERR_PTR(err); + } + + cookie = vgpu_ivm_mempool_reserve(mempool); + if (IS_ERR_OR_NULL(cookie)) { + nvgpu_err(g, "mempool %u reserve failed", mempool); + return ERR_PTR(-EINVAL); + } + return cookie; +} + +u32 vgpu_css_get_buffer_size(struct gk20a *g) +{ + struct tegra_hv_ivm_cookie *cookie; + u32 size; + + nvgpu_log_fn(g, " "); + + if (css_cookie) { + size = (u32)vgpu_ivm_get_size(css_cookie); + nvgpu_log_info(g, "buffer size = 0x%08x", size); + return size; + } + + cookie = vgpu_css_reserve_mempool(g); + if (IS_ERR(cookie)) + return 0; + + size = vgpu_ivm_get_size(cookie); + + vgpu_ivm_mempool_unreserve(cookie); + nvgpu_log_info(g, "buffer size = 0x%08x", size); + return size; +} + +static int vgpu_css_init_snapshot_buffer(struct gr_gk20a *gr) +{ + struct gk20a *g = gr->g; + struct gk20a_cs_snapshot *data = gr->cs_data; + void *buf = NULL; + int err; + u64 size; + + nvgpu_log_fn(g, " "); + + if (data->hw_snapshot) + return 0; + + css_cookie = vgpu_css_reserve_mempool(g); + if (IS_ERR(css_cookie)) + return PTR_ERR(css_cookie); + + size = vgpu_ivm_get_size(css_cookie); + /* Make sure buffer size is large enough */ + if (size < CSS_MIN_HW_SNAPSHOT_SIZE) { + nvgpu_info(g, "mempool size 0x%llx too small", size); + err = -ENOMEM; + goto fail; + } + + buf = vgpu_ivm_mempool_map(css_cookie); + if (!buf) { + nvgpu_info(g, "vgpu_ivm_mempool_map failed"); + err = -EINVAL; + goto fail; + } + + data->hw_snapshot = buf; + data->hw_end = data->hw_snapshot + + size / sizeof(struct gk20a_cs_snapshot_fifo_entry); + data->hw_get = data->hw_snapshot; + memset(data->hw_snapshot, 0xff, size); + return 0; +fail: + vgpu_ivm_mempool_unreserve(css_cookie); + css_cookie = NULL; + return err; +} + +void vgpu_css_release_snapshot_buffer(struct gr_gk20a *gr) +{ + struct gk20a_cs_snapshot *data = gr->cs_data; + struct gk20a *g = gr->g; + + if (!data->hw_snapshot) + return; + + vgpu_ivm_mempool_unmap(css_cookie, data->hw_snapshot); + data->hw_snapshot = NULL; + + vgpu_ivm_mempool_unreserve(css_cookie); + css_cookie = NULL; + + nvgpu_log_info(g, "cyclestats(vgpu): buffer for snapshots released\n"); +} + +int vgpu_css_flush_snapshots(struct channel_gk20a *ch, + u32 *pending, bool *hw_overflow) +{ + struct gk20a *g = ch->g; + struct tegra_vgpu_cmd_msg msg = {}; + struct tegra_vgpu_channel_cyclestats_snapshot_params *p; + struct gr_gk20a *gr = &g->gr; + struct gk20a_cs_snapshot *data = gr->cs_data; + int err; + + nvgpu_log_fn(g, " "); + + msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; + msg.handle = vgpu_get_handle(g); + p = &msg.params.cyclestats_snapshot; + p->handle = ch->virt_ctx; + p->subcmd = TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_FLUSH; + p->buf_info = (uintptr_t)data->hw_get - (uintptr_t)data->hw_snapshot; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + + err = (err || msg.ret) ? -1 : 0; + + *pending = p->buf_info; + *hw_overflow = p->hw_overflow; + + return err; +} + +static int vgpu_css_attach(struct channel_gk20a *ch, + struct gk20a_cs_snapshot_client *cs_client) +{ + struct gk20a *g = ch->g; + struct tegra_vgpu_cmd_msg msg = {}; + struct tegra_vgpu_channel_cyclestats_snapshot_params *p = + &msg.params.cyclestats_snapshot; + int err; + + nvgpu_log_fn(g, " "); + + msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; + msg.handle = vgpu_get_handle(g); + p->handle = ch->virt_ctx; + p->subcmd = TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_ATTACH; + p->perfmon_count = cs_client->perfmon_count; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (err) + nvgpu_err(g, "failed"); + else + cs_client->perfmon_start = p->perfmon_start; + + return err; +} + +int vgpu_css_detach(struct channel_gk20a *ch, + struct gk20a_cs_snapshot_client *cs_client) +{ + struct gk20a *g = ch->g; + struct tegra_vgpu_cmd_msg msg = {}; + struct tegra_vgpu_channel_cyclestats_snapshot_params *p = + &msg.params.cyclestats_snapshot; + int err; + + nvgpu_log_fn(g, " "); + + msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT; + msg.handle = vgpu_get_handle(g); + p->handle = ch->virt_ctx; + p->subcmd = TEGRA_VGPU_CYCLE_STATS_SNAPSHOT_CMD_DETACH; + p->perfmon_start = cs_client->perfmon_start; + p->perfmon_count = cs_client->perfmon_count; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (err) + nvgpu_err(g, "failed"); + + return err; +} + +int vgpu_css_enable_snapshot_buffer(struct channel_gk20a *ch, + struct gk20a_cs_snapshot_client *cs_client) +{ + int ret; + + ret = vgpu_css_attach(ch, cs_client); + if (ret) + return ret; + + ret = vgpu_css_init_snapshot_buffer(&ch->g->gr); + return ret; +} + +#endif /* CONFIG_GK20A_CYCLE_STATS */ -- cgit v1.2.2