diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/vgpu/vgpu.c')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/vgpu/vgpu.c | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu.c b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu.c deleted file mode 100644 index 7915a599..00000000 --- a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu.c +++ /dev/null | |||
@@ -1,344 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014-2018, 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 | |||
17 | #include <nvgpu/enabled.h> | ||
18 | #include <nvgpu/bus.h> | ||
19 | #include <nvgpu/vgpu/vgpu_ivc.h> | ||
20 | |||
21 | #include "gk20a/gk20a.h" | ||
22 | #include "vgpu.h" | ||
23 | #include "fecs_trace_vgpu.h" | ||
24 | |||
25 | int vgpu_comm_init(struct gk20a *g) | ||
26 | { | ||
27 | size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES }; | ||
28 | |||
29 | return vgpu_ivc_init(g, 3, queue_sizes, TEGRA_VGPU_QUEUE_CMD, | ||
30 | ARRAY_SIZE(queue_sizes)); | ||
31 | } | ||
32 | |||
33 | void vgpu_comm_deinit(void) | ||
34 | { | ||
35 | size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES }; | ||
36 | |||
37 | vgpu_ivc_deinit(TEGRA_VGPU_QUEUE_CMD, ARRAY_SIZE(queue_sizes)); | ||
38 | } | ||
39 | |||
40 | int vgpu_comm_sendrecv(struct tegra_vgpu_cmd_msg *msg, size_t size_in, | ||
41 | size_t size_out) | ||
42 | { | ||
43 | void *handle; | ||
44 | size_t size = size_in; | ||
45 | void *data = msg; | ||
46 | int err; | ||
47 | |||
48 | err = vgpu_ivc_sendrecv(vgpu_ivc_get_server_vmid(), | ||
49 | TEGRA_VGPU_QUEUE_CMD, &handle, &data, &size); | ||
50 | if (!err) { | ||
51 | WARN_ON(size < size_out); | ||
52 | memcpy(msg, data, size_out); | ||
53 | vgpu_ivc_release(handle); | ||
54 | } | ||
55 | |||
56 | return err; | ||
57 | } | ||
58 | |||
59 | u64 vgpu_connect(void) | ||
60 | { | ||
61 | struct tegra_vgpu_cmd_msg msg; | ||
62 | struct tegra_vgpu_connect_params *p = &msg.params.connect; | ||
63 | int err; | ||
64 | |||
65 | msg.cmd = TEGRA_VGPU_CMD_CONNECT; | ||
66 | p->module = TEGRA_VGPU_MODULE_GPU; | ||
67 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
68 | |||
69 | return (err || msg.ret) ? 0 : p->handle; | ||
70 | } | ||
71 | |||
72 | int vgpu_get_attribute(u64 handle, u32 attrib, u32 *value) | ||
73 | { | ||
74 | struct tegra_vgpu_cmd_msg msg; | ||
75 | struct tegra_vgpu_attrib_params *p = &msg.params.attrib; | ||
76 | int err; | ||
77 | |||
78 | msg.cmd = TEGRA_VGPU_CMD_GET_ATTRIBUTE; | ||
79 | msg.handle = handle; | ||
80 | p->attrib = attrib; | ||
81 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
82 | |||
83 | if (err || msg.ret) | ||
84 | return -1; | ||
85 | |||
86 | *value = p->value; | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void vgpu_handle_channel_event(struct gk20a *g, | ||
91 | struct tegra_vgpu_channel_event_info *info) | ||
92 | { | ||
93 | struct tsg_gk20a *tsg; | ||
94 | |||
95 | if (!info->is_tsg) { | ||
96 | nvgpu_err(g, "channel event posted"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | if (info->id >= g->fifo.num_channels || | ||
101 | info->event_id >= TEGRA_VGPU_CHANNEL_EVENT_ID_MAX) { | ||
102 | nvgpu_err(g, "invalid channel event"); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | tsg = &g->fifo.tsg[info->id]; | ||
107 | |||
108 | gk20a_tsg_event_id_post_event(tsg, info->event_id); | ||
109 | } | ||
110 | |||
111 | int vgpu_intr_thread(void *dev_id) | ||
112 | { | ||
113 | struct gk20a *g = dev_id; | ||
114 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); | ||
115 | |||
116 | while (true) { | ||
117 | struct tegra_vgpu_intr_msg *msg; | ||
118 | u32 sender; | ||
119 | void *handle; | ||
120 | size_t size; | ||
121 | int err; | ||
122 | |||
123 | err = vgpu_ivc_recv(TEGRA_VGPU_QUEUE_INTR, &handle, | ||
124 | (void **)&msg, &size, &sender); | ||
125 | if (err == -ETIME) | ||
126 | continue; | ||
127 | if (WARN_ON(err)) | ||
128 | continue; | ||
129 | |||
130 | if (msg->event == TEGRA_VGPU_EVENT_ABORT) { | ||
131 | vgpu_ivc_release(handle); | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | switch (msg->event) { | ||
136 | case TEGRA_VGPU_EVENT_INTR: | ||
137 | if (msg->unit == TEGRA_VGPU_INTR_GR) | ||
138 | vgpu_gr_isr(g, &msg->info.gr_intr); | ||
139 | else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_GR) | ||
140 | vgpu_gr_nonstall_isr(g, | ||
141 | &msg->info.gr_nonstall_intr); | ||
142 | else if (msg->unit == TEGRA_VGPU_INTR_FIFO) | ||
143 | vgpu_fifo_isr(g, &msg->info.fifo_intr); | ||
144 | else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_FIFO) | ||
145 | vgpu_fifo_nonstall_isr(g, | ||
146 | &msg->info.fifo_nonstall_intr); | ||
147 | else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_CE2) | ||
148 | vgpu_ce2_nonstall_isr(g, | ||
149 | &msg->info.ce2_nonstall_intr); | ||
150 | break; | ||
151 | #ifdef CONFIG_GK20A_CTXSW_TRACE | ||
152 | case TEGRA_VGPU_EVENT_FECS_TRACE: | ||
153 | vgpu_fecs_trace_data_update(g); | ||
154 | break; | ||
155 | #endif | ||
156 | case TEGRA_VGPU_EVENT_CHANNEL: | ||
157 | vgpu_handle_channel_event(g, &msg->info.channel_event); | ||
158 | break; | ||
159 | case TEGRA_VGPU_EVENT_SM_ESR: | ||
160 | vgpu_gr_handle_sm_esr_event(g, &msg->info.sm_esr); | ||
161 | break; | ||
162 | default: | ||
163 | nvgpu_err(g, "unknown event %u", msg->event); | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | vgpu_ivc_release(handle); | ||
168 | } | ||
169 | |||
170 | while (!nvgpu_thread_should_stop(&priv->intr_handler)) | ||
171 | nvgpu_msleep(10); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | void vgpu_remove_support_common(struct gk20a *g) | ||
176 | { | ||
177 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); | ||
178 | struct tegra_vgpu_intr_msg msg; | ||
179 | int err; | ||
180 | |||
181 | if (g->dbg_regops_tmp_buf) | ||
182 | nvgpu_kfree(g, g->dbg_regops_tmp_buf); | ||
183 | |||
184 | if (g->pmu.remove_support) | ||
185 | g->pmu.remove_support(&g->pmu); | ||
186 | |||
187 | if (g->gr.remove_support) | ||
188 | g->gr.remove_support(&g->gr); | ||
189 | |||
190 | if (g->fifo.remove_support) | ||
191 | g->fifo.remove_support(&g->fifo); | ||
192 | |||
193 | if (g->mm.remove_support) | ||
194 | g->mm.remove_support(&g->mm); | ||
195 | |||
196 | msg.event = TEGRA_VGPU_EVENT_ABORT; | ||
197 | err = vgpu_ivc_send(vgpu_ivc_get_peer_self(), TEGRA_VGPU_QUEUE_INTR, | ||
198 | &msg, sizeof(msg)); | ||
199 | WARN_ON(err); | ||
200 | nvgpu_thread_stop(&priv->intr_handler); | ||
201 | } | ||
202 | |||
203 | void vgpu_detect_chip(struct gk20a *g) | ||
204 | { | ||
205 | struct nvgpu_gpu_params *p = &g->params; | ||
206 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); | ||
207 | |||
208 | p->gpu_arch = priv->constants.arch; | ||
209 | p->gpu_impl = priv->constants.impl; | ||
210 | p->gpu_rev = priv->constants.rev; | ||
211 | |||
212 | gk20a_dbg_info("arch: %x, impl: %x, rev: %x\n", | ||
213 | p->gpu_arch, | ||
214 | p->gpu_impl, | ||
215 | p->gpu_rev); | ||
216 | } | ||
217 | |||
218 | int vgpu_init_gpu_characteristics(struct gk20a *g) | ||
219 | { | ||
220 | int err; | ||
221 | |||
222 | gk20a_dbg_fn(""); | ||
223 | |||
224 | err = gk20a_init_gpu_characteristics(g); | ||
225 | if (err) | ||
226 | return err; | ||
227 | |||
228 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_BUFFER_BATCH, false); | ||
229 | |||
230 | /* features vgpu does not support */ | ||
231 | __nvgpu_set_enabled(g, NVGPU_SUPPORT_RESCHEDULE_RUNLIST, false); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | int vgpu_read_ptimer(struct gk20a *g, u64 *value) | ||
237 | { | ||
238 | struct tegra_vgpu_cmd_msg msg = {0}; | ||
239 | struct tegra_vgpu_read_ptimer_params *p = &msg.params.read_ptimer; | ||
240 | int err; | ||
241 | |||
242 | gk20a_dbg_fn(""); | ||
243 | |||
244 | msg.cmd = TEGRA_VGPU_CMD_READ_PTIMER; | ||
245 | msg.handle = vgpu_get_handle(g); | ||
246 | |||
247 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
248 | err = err ? err : msg.ret; | ||
249 | if (!err) | ||
250 | *value = p->time; | ||
251 | else | ||
252 | nvgpu_err(g, "vgpu read ptimer failed, err=%d", err); | ||
253 | |||
254 | return err; | ||
255 | } | ||
256 | |||
257 | int vgpu_get_timestamps_zipper(struct gk20a *g, | ||
258 | u32 source_id, u32 count, | ||
259 | struct nvgpu_cpu_time_correlation_sample *samples) | ||
260 | { | ||
261 | struct tegra_vgpu_cmd_msg msg = {0}; | ||
262 | struct tegra_vgpu_get_timestamps_zipper_params *p = | ||
263 | &msg.params.get_timestamps_zipper; | ||
264 | int err; | ||
265 | u32 i; | ||
266 | |||
267 | gk20a_dbg_fn(""); | ||
268 | |||
269 | if (count > TEGRA_VGPU_GET_TIMESTAMPS_ZIPPER_MAX_COUNT) { | ||
270 | nvgpu_err(g, "count %u overflow", count); | ||
271 | return -EINVAL; | ||
272 | } | ||
273 | |||
274 | msg.cmd = TEGRA_VGPU_CMD_GET_TIMESTAMPS_ZIPPER; | ||
275 | msg.handle = vgpu_get_handle(g); | ||
276 | p->source_id = TEGRA_VGPU_GET_TIMESTAMPS_ZIPPER_SRC_ID_TSC; | ||
277 | p->count = count; | ||
278 | |||
279 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
280 | err = err ? err : msg.ret; | ||
281 | if (err) { | ||
282 | nvgpu_err(g, "vgpu get timestamps zipper failed, err=%d", err); | ||
283 | return err; | ||
284 | } | ||
285 | |||
286 | for (i = 0; i < count; i++) { | ||
287 | samples[i].cpu_timestamp = p->samples[i].cpu_timestamp; | ||
288 | samples[i].gpu_timestamp = p->samples[i].gpu_timestamp; | ||
289 | } | ||
290 | |||
291 | return err; | ||
292 | } | ||
293 | |||
294 | int vgpu_init_hal(struct gk20a *g) | ||
295 | { | ||
296 | u32 ver = g->params.gpu_arch + g->params.gpu_impl; | ||
297 | int err; | ||
298 | |||
299 | switch (ver) { | ||
300 | case NVGPU_GPUID_GP10B: | ||
301 | gk20a_dbg_info("gp10b detected"); | ||
302 | err = vgpu_gp10b_init_hal(g); | ||
303 | break; | ||
304 | case NVGPU_GPUID_GV11B: | ||
305 | err = vgpu_gv11b_init_hal(g); | ||
306 | break; | ||
307 | default: | ||
308 | nvgpu_err(g, "no support for %x", ver); | ||
309 | err = -ENODEV; | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | return err; | ||
314 | } | ||
315 | |||
316 | int vgpu_get_constants(struct gk20a *g) | ||
317 | { | ||
318 | struct tegra_vgpu_cmd_msg msg = {}; | ||
319 | struct tegra_vgpu_constants_params *p = &msg.params.constants; | ||
320 | struct vgpu_priv_data *priv = vgpu_get_priv_data(g); | ||
321 | int err; | ||
322 | |||
323 | gk20a_dbg_fn(""); | ||
324 | |||
325 | msg.cmd = TEGRA_VGPU_CMD_GET_CONSTANTS; | ||
326 | msg.handle = vgpu_get_handle(g); | ||
327 | err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); | ||
328 | err = err ? err : msg.ret; | ||
329 | |||
330 | if (unlikely(err)) { | ||
331 | nvgpu_err(g, "%s failed, err=%d", __func__, err); | ||
332 | return err; | ||
333 | } | ||
334 | |||
335 | if (unlikely(p->gpc_count > TEGRA_VGPU_MAX_GPC_COUNT || | ||
336 | p->max_tpc_per_gpc_count > TEGRA_VGPU_MAX_TPC_COUNT_PER_GPC)) { | ||
337 | nvgpu_err(g, "gpc_count %d max_tpc_per_gpc %d overflow", | ||
338 | (int)p->gpc_count, (int)p->max_tpc_per_gpc_count); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | |||
342 | priv->constants = *p; | ||
343 | return 0; | ||
344 | } | ||