summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/css_vgpu.c
diff options
context:
space:
mode:
authorPeter Daifuku <pdaifuku@nvidia.com>2016-08-31 20:04:56 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-09-08 19:04:09 -0400
commit9aa7de15c2a644e9c7e9c157e49087e66d4ac3d0 (patch)
treee5080886f09aa75c6a3cc83e5b27f8f7553678a4 /drivers/gpu/nvgpu/vgpu/css_vgpu.c
parent70cad5fbb593602a49f91e57c04d1da0334b3a49 (diff)
gpu: nvgpu: vgpu: cyclestat snapshot support
Add support for cyclestats snapshots in the virtual case Bug 1700143 JIRA EVLR-278 Change-Id: I376a8804d57324f43eb16452d857a3b7bb0ecc90 Signed-off-by: Peter Daifuku <pdaifuku@nvidia.com> Reviewed-on: http://git-master/r/1211547 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/css_vgpu.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/css_vgpu.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/css_vgpu.c b/drivers/gpu/nvgpu/vgpu/css_vgpu.c
new file mode 100644
index 00000000..486d3e88
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/css_vgpu.c
@@ -0,0 +1,221 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#if defined(CONFIG_GK20A_CYCLE_STATS)
17
18#include <linux/kernel.h>
19#include <linux/nvhost.h>
20#include <linux/tegra-ivc.h>
21#include <linux/tegra_vgpu.h>
22
23#include "gk20a/gk20a.h"
24#include "gk20a/channel_gk20a.h"
25#include "gk20a/platform_gk20a.h"
26#include "gk20a/css_gr_gk20a.h"
27#include "vgpu.h"
28
29struct vgpu_hw_snapshot_buffer {
30 struct tegra_hv_ivm_cookie *cookie;
31 void *buf;
32 struct gk20a_cs_snapshot_fifo_entry *end;
33 struct gk20a_cs_snapshot_fifo_entry *src_get;
34 struct gk20a_cs_snapshot_fifo_entry *src_put;
35};
36
37struct tegra_hv_ivm_cookie *css_cookie;
38
39int vgpu_css_init_snapshot_buffer(struct gr_gk20a *gr)
40{
41 struct gk20a *g = gr->g;
42 struct device *dev = g->dev;
43 struct gk20a_cs_snapshot *data = gr->cs_data;
44 struct device_node *np = dev->of_node;
45 struct of_phandle_args args;
46 struct device_node *hv_np;
47 void *buf = NULL;
48 u32 mempool;
49 int err;
50
51 gk20a_dbg_fn("");
52
53 if (data->hw_snapshot)
54 return 0;
55
56 err = of_parse_phandle_with_fixed_args(np,
57 "mempool-css", 1, 0, &args);
58 if (err) {
59 dev_info(dev_from_gk20a(g), "dt missing mempool-css\n");
60 goto fail;
61 }
62
63 hv_np = args.np;
64 mempool = args.args[0];
65 css_cookie = tegra_hv_mempool_reserve(hv_np, mempool);
66 if (IS_ERR(css_cookie)) {
67 dev_info(dev_from_gk20a(g),
68 "mempool %u reserve failed\n", mempool);
69 err = -EINVAL;
70 goto fail;
71 }
72
73 /* Make sure buffer size is large enough */
74 if (css_cookie->size < CSS_MIN_HW_SNAPSHOT_SIZE) {
75 dev_info(dev_from_gk20a(g), "mempool size %lld too small\n",
76 css_cookie->size);
77 err = -ENOMEM;
78 goto fail;
79 }
80
81#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
82 buf = ioremap_cached(css_cookie->ipa, css_cookie->size);
83#else
84 buf = ioremap_cache(css_cookie->ipa, css_cookie->size);
85#endif
86 if (!buf) {
87 dev_info(dev_from_gk20a(g), "ioremap_cache failed\n");
88 err = -EINVAL;
89 goto fail;
90 }
91
92 data->hw_snapshot = buf;
93 data->hw_end = data->hw_snapshot +
94 css_cookie->size / sizeof(struct gk20a_cs_snapshot_fifo_entry);
95 data->hw_get = data->hw_snapshot;
96 memset(data->hw_snapshot, 0xff, css_cookie->size);
97 return 0;
98fail:
99 if (!IS_ERR_OR_NULL(css_cookie))
100 tegra_hv_mempool_unreserve(css_cookie);
101 return err;
102}
103
104static void vgpu_css_release_snapshot_buffer(struct gr_gk20a *gr)
105{
106 struct gk20a_cs_snapshot *data = gr->cs_data;
107
108 if (!data->hw_snapshot)
109 return;
110
111 iounmap(data->hw_snapshot);
112 data->hw_snapshot = NULL;
113
114 tegra_hv_mempool_unreserve(css_cookie);
115
116 gk20a_dbg_info("cyclestats(vgpu): buffer for snapshots released\n");
117}
118
119static int vgpu_css_flush_snapshots(struct channel_gk20a *ch,
120 u32 *pending, bool *hw_overflow)
121{
122 struct gk20a *g = ch->g;
123 struct tegra_vgpu_cmd_msg msg = {};
124 struct tegra_vgpu_channel_cyclestats_snapshot_params *p;
125 struct gr_gk20a *gr = &g->gr;
126 struct gk20a_cs_snapshot *data = gr->cs_data;
127 int err;
128
129 gk20a_dbg_fn("");
130
131 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT;
132 msg.handle = vgpu_get_handle(g);
133 p = &msg.params.cyclestats_snapshot;
134 p->handle = ch->virt_ctx;
135 p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_FLUSH;
136 p->buf_info = (uintptr_t)data->hw_get - (uintptr_t)data->hw_snapshot;
137
138 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
139
140 err = (err || msg.ret) ? -1 : 0;
141
142 *pending = p->buf_info;
143 *hw_overflow = p->hw_overflow;
144
145 return err;
146}
147
148static int vgpu_css_attach(struct channel_gk20a *ch,
149 struct gk20a_cs_snapshot_client *cs_client)
150{
151 struct gk20a *g = ch->g;
152 struct tegra_vgpu_cmd_msg msg = {};
153 struct tegra_vgpu_channel_cyclestats_snapshot_params *p =
154 &msg.params.cyclestats_snapshot;
155 int err;
156
157 gk20a_dbg_fn("");
158
159 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT;
160 msg.handle = vgpu_get_handle(g);
161 p->handle = ch->virt_ctx;
162 p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_ATTACH;
163 p->perfmon_count = cs_client->perfmon_count;
164
165 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
166 err = err ? err : msg.ret;
167 if (err)
168 gk20a_err(dev_from_gk20a(g), "%s failed", __func__);
169 else
170 cs_client->perfmon_start = p->perfmon_start;
171
172 return err;
173}
174
175static int vgpu_css_detach(struct channel_gk20a *ch,
176 struct gk20a_cs_snapshot_client *cs_client)
177{
178 struct gk20a *g = ch->g;
179 struct tegra_vgpu_cmd_msg msg = {};
180 struct tegra_vgpu_channel_cyclestats_snapshot_params *p =
181 &msg.params.cyclestats_snapshot;
182 int err;
183
184 gk20a_dbg_fn("");
185
186 msg.cmd = TEGRA_VGPU_CMD_CHANNEL_CYCLESTATS_SNAPSHOT;
187 msg.handle = vgpu_get_handle(g);
188 p->handle = ch->virt_ctx;
189 p->subcmd = NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT_CMD_DETACH;
190 p->perfmon_start = cs_client->perfmon_start;
191 p->perfmon_count = cs_client->perfmon_count;
192
193 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
194 err = err ? err : msg.ret;
195 if (err)
196 gk20a_err(dev_from_gk20a(g), "%s failed", __func__);
197
198 return err;
199}
200
201static int vgpu_css_enable_snapshot_buffer(struct channel_gk20a *ch,
202 struct gk20a_cs_snapshot_client *cs_client)
203{
204 int ret;
205
206 ret = vgpu_css_attach(ch, cs_client);
207 if (ret)
208 return ret;
209
210 ret = vgpu_css_init_snapshot_buffer(&ch->g->gr);
211 return ret;
212}
213
214void vgpu_init_css_ops(struct gpu_ops *gops)
215{
216 gops->css.enable_snapshot = vgpu_css_enable_snapshot_buffer;
217 gops->css.disable_snapshot = vgpu_css_release_snapshot_buffer;
218 gops->css.check_data_available = vgpu_css_flush_snapshots;
219 gops->css.detach_snapshot = vgpu_css_detach;
220}
221#endif /* CONFIG_GK20A_CYCLE_STATS */