summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/sim.c
diff options
context:
space:
mode:
authorAntony Clince Alex <aalex@nvidia.com>2018-04-25 11:56:21 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-05-09 21:25:45 -0400
commit50d1b0c72bfa5bf662c04db85e39c04ca3abfd67 (patch)
tree85d12588affcfcd23a3794257f965542aadea6b1 /drivers/gpu/nvgpu/common/sim.c
parentb144935644f76328aa9ec2592655b4553ed28222 (diff)
gpu: nvgpu: os-agnostic segregation of sim/sim_pci
segregated os-agnostic function from linux/sim.c and linux/sim_pci.c to sim.c and sim_pci.c, while retaining os-specific functions. renamed all gk20a_* api's to nvgpu_*. renamed hw_sim_gk20a.h to nvgpu/hw_sim.h moved hw_sim_pci.h to nvgpu/hw_sim_pci.h JIRA VQRM-2368 Change-Id: I040a6b12b19111a0b99280245808ea2b0f344cdd Signed-off-by: Antony Clince Alex <aalex@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1702425 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/sim.c')
-rw-r--r--drivers/gpu/nvgpu/common/sim.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/sim.c b/drivers/gpu/nvgpu/common/sim.c
new file mode 100644
index 00000000..0f88ec4d
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/sim.c
@@ -0,0 +1,311 @@
1/*
2 * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/log.h>
24#include <nvgpu/bitops.h>
25#include <nvgpu/nvgpu_mem.h>
26#include <nvgpu/dma.h>
27#include <nvgpu/io.h>
28#include <nvgpu/hw_sim.h>
29#include "gk20a/gk20a.h"
30#include "linux/sim.h"
31
32
33int nvgpu_alloc_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem)
34{
35 int err;
36
37 err = nvgpu_dma_alloc(g, PAGE_SIZE, mem);
38
39 if (err)
40 return err;
41 /*
42 * create a valid cpu_va mapping
43 */
44 nvgpu_mem_begin(g, mem);
45
46 return 0;
47}
48
49void nvgpu_free_sim_buffer(struct gk20a *g, struct nvgpu_mem *mem)
50{
51 if (nvgpu_mem_is_valid(mem)) {
52 /*
53 * invalidate the cpu_va mapping
54 */
55 nvgpu_mem_end(g, mem);
56 nvgpu_dma_free(g, mem);
57 }
58
59 memset(mem, 0, sizeof(*mem));
60}
61
62void nvgpu_free_sim_support(struct gk20a *g)
63{
64 nvgpu_free_sim_buffer(g, &g->sim->send_bfr);
65 nvgpu_free_sim_buffer(g, &g->sim->recv_bfr);
66 nvgpu_free_sim_buffer(g, &g->sim->msg_bfr);
67}
68
69void nvgpu_remove_sim_support(struct gk20a *g)
70{
71 if (g->sim)
72 nvgpu_free_sim_support(g);
73}
74
75static inline u32 sim_msg_header_size(void)
76{
77 return 24;/*TBD: fix the header to gt this from NV_VGPU_MSG_HEADER*/
78}
79
80static inline u32 *sim_msg_bfr(struct gk20a *g, u32 byte_offset)
81{
82 u8 *cpu_va;
83
84 cpu_va = (u8 *)g->sim->msg_bfr.cpu_va;
85
86 return (u32 *)(cpu_va + byte_offset);
87}
88
89static inline u32 *sim_msg_hdr(struct gk20a *g, u32 byte_offset)
90{
91 return sim_msg_bfr(g, byte_offset); /*starts at 0*/
92}
93
94static inline u32 *sim_msg_param(struct gk20a *g, u32 byte_offset)
95{
96 /*starts after msg header/cmn*/
97 return sim_msg_bfr(g, byte_offset + sim_msg_header_size());
98}
99
100static inline void sim_write_hdr(struct gk20a *g, u32 func, u32 size)
101{
102 /*memset(g->sim->msg_bfr.kvaddr,0,min(PAGE_SIZE,size));*/
103 *sim_msg_hdr(g, sim_msg_signature_r()) = sim_msg_signature_valid_v();
104 *sim_msg_hdr(g, sim_msg_result_r()) = sim_msg_result_rpc_pending_v();
105 *sim_msg_hdr(g, sim_msg_spare_r()) = sim_msg_spare__init_v();
106 *sim_msg_hdr(g, sim_msg_function_r()) = func;
107 *sim_msg_hdr(g, sim_msg_length_r()) = size + sim_msg_header_size();
108}
109
110static inline u32 sim_escape_read_hdr_size(void)
111{
112 return 12; /*TBD: fix NV_VGPU_SIM_ESCAPE_READ_HEADER*/
113}
114
115static u32 *sim_send_ring_bfr(struct gk20a *g, u32 byte_offset)
116{
117 u8 *cpu_va;
118
119 cpu_va = (u8 *)g->sim->send_bfr.cpu_va;
120
121 return (u32 *)(cpu_va + byte_offset);
122}
123
124static int rpc_send_message(struct gk20a *g)
125{
126 /* calculations done in units of u32s */
127 u32 send_base = sim_send_put_pointer_v(g->sim->send_ring_put) * 2;
128 u32 dma_offset = send_base + sim_dma_r()/sizeof(u32);
129 u32 dma_hi_offset = send_base + sim_dma_hi_r()/sizeof(u32);
130
131 *sim_send_ring_bfr(g, dma_offset*sizeof(u32)) =
132 sim_dma_target_phys_pci_coherent_f() |
133 sim_dma_status_valid_f() |
134 sim_dma_size_4kb_f() |
135 sim_dma_addr_lo_f(nvgpu_mem_get_addr(g, &g->sim->msg_bfr)
136 >> PAGE_SHIFT);
137
138 *sim_send_ring_bfr(g, dma_hi_offset*sizeof(u32)) =
139 u64_hi32(nvgpu_mem_get_addr(g, &g->sim->msg_bfr));
140
141 *sim_msg_hdr(g, sim_msg_sequence_r()) = g->sim->sequence_base++;
142
143 g->sim->send_ring_put = (g->sim->send_ring_put + 2 * sizeof(u32))
144 % PAGE_SIZE;
145
146 /* Update the put pointer. This will trap into the host. */
147 sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put);
148
149 return 0;
150}
151
152static inline u32 *sim_recv_ring_bfr(struct gk20a *g, u32 byte_offset)
153{
154 u8 *cpu_va;
155
156 cpu_va = (u8 *)g->sim->recv_bfr.cpu_va;
157
158 return (u32 *)(cpu_va + byte_offset);
159}
160
161static int rpc_recv_poll(struct gk20a *g)
162{
163 u64 recv_phys_addr;
164
165 /* XXX This read is not required (?) */
166 /*pVGpu->recv_ring_get = VGPU_REG_RD32(pGpu, NV_VGPU_RECV_GET);*/
167
168 /* Poll the recv ring get pointer in an infinite loop*/
169 do {
170 g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r());
171 } while (g->sim->recv_ring_put == g->sim->recv_ring_get);
172
173 /* process all replies */
174 while (g->sim->recv_ring_put != g->sim->recv_ring_get) {
175 /* these are in u32 offsets*/
176 u32 dma_lo_offset =
177 sim_recv_put_pointer_v(g->sim->recv_ring_get)*2 + 0;
178 u32 dma_hi_offset = dma_lo_offset + 1;
179 u32 recv_phys_addr_lo = sim_dma_addr_lo_v(
180 *sim_recv_ring_bfr(g, dma_lo_offset*4));
181 u32 recv_phys_addr_hi = sim_dma_hi_addr_v(
182 *sim_recv_ring_bfr(g, dma_hi_offset*4));
183
184 recv_phys_addr = (u64)recv_phys_addr_hi << 32 |
185 (u64)recv_phys_addr_lo << PAGE_SHIFT;
186
187 if (recv_phys_addr !=
188 nvgpu_mem_get_addr(g, &g->sim->msg_bfr)) {
189 nvgpu_err(g, "%s Error in RPC reply",
190 __func__);
191 return -1;
192 }
193
194 /* Update GET pointer */
195 g->sim->recv_ring_get = (g->sim->recv_ring_get + 2*sizeof(u32))
196 % PAGE_SIZE;
197
198 sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get);
199
200 g->sim->recv_ring_put = sim_readl(g->sim, sim_recv_put_r());
201 }
202
203 return 0;
204}
205
206static int issue_rpc_and_wait(struct gk20a *g)
207{
208 int err;
209
210 err = rpc_send_message(g);
211 if (err) {
212 nvgpu_err(g, "%s failed rpc_send_message",
213 __func__);
214 return err;
215 }
216
217 err = rpc_recv_poll(g);
218 if (err) {
219 nvgpu_err(g, "%s failed rpc_recv_poll",
220 __func__);
221 return err;
222 }
223
224 /* Now check if RPC really succeeded */
225 if (*sim_msg_hdr(g, sim_msg_result_r()) != sim_msg_result_success_v()) {
226 nvgpu_err(g, "%s received failed status!",
227 __func__);
228 return -(*sim_msg_hdr(g, sim_msg_result_r()));
229 }
230 return 0;
231}
232
233static int nvgpu_sim_esc_readl(struct gk20a *g,
234 char *path, u32 index, u32 *data)
235{
236 int err;
237 size_t pathlen = strlen(path);
238 u32 data_offset;
239
240 sim_write_hdr(g, sim_msg_function_sim_escape_read_v(),
241 sim_escape_read_hdr_size());
242 *sim_msg_param(g, 0) = index;
243 *sim_msg_param(g, 4) = sizeof(u32);
244 data_offset = roundup(0xc + pathlen + 1, sizeof(u32));
245 *sim_msg_param(g, 8) = data_offset;
246 strcpy((char *)sim_msg_param(g, 0xc), path);
247
248 err = issue_rpc_and_wait(g);
249
250 if (!err)
251 memcpy(data, sim_msg_param(g, data_offset), sizeof(u32));
252 return err;
253}
254
255int nvgpu_init_sim_support(struct gk20a *g)
256{
257 int err = -ENOMEM;
258 u64 phys;
259
260 if (!g->sim)
261 return 0;
262
263 /* allocate sim event/msg buffers */
264 err = nvgpu_alloc_sim_buffer(g, &g->sim->send_bfr);
265 err = err || nvgpu_alloc_sim_buffer(g, &g->sim->recv_bfr);
266 err = err || nvgpu_alloc_sim_buffer(g, &g->sim->msg_bfr);
267
268 if (err)
269 goto fail;
270 /*mark send ring invalid*/
271 sim_writel(g->sim, sim_send_ring_r(), sim_send_ring_status_invalid_f());
272
273 /*read get pointer and make equal to put*/
274 g->sim->send_ring_put = sim_readl(g->sim, sim_send_get_r());
275 sim_writel(g->sim, sim_send_put_r(), g->sim->send_ring_put);
276
277 /*write send ring address and make it valid*/
278 phys = nvgpu_mem_get_addr(g, &g->sim->send_bfr);
279 sim_writel(g->sim, sim_send_ring_hi_r(),
280 sim_send_ring_hi_addr_f(u64_hi32(phys)));
281 sim_writel(g->sim, sim_send_ring_r(),
282 sim_send_ring_status_valid_f() |
283 sim_send_ring_target_phys_pci_coherent_f() |
284 sim_send_ring_size_4kb_f() |
285 sim_send_ring_addr_lo_f(phys >> PAGE_SHIFT));
286
287 /*repeat for recv ring (but swap put,get as roles are opposite) */
288 sim_writel(g->sim, sim_recv_ring_r(), sim_recv_ring_status_invalid_f());
289
290 /*read put pointer and make equal to get*/
291 g->sim->recv_ring_get = sim_readl(g->sim, sim_recv_put_r());
292 sim_writel(g->sim, sim_recv_get_r(), g->sim->recv_ring_get);
293
294 /*write send ring address and make it valid*/
295 phys = nvgpu_mem_get_addr(g, &g->sim->recv_bfr);
296 sim_writel(g->sim, sim_recv_ring_hi_r(),
297 sim_recv_ring_hi_addr_f(u64_hi32(phys)));
298 sim_writel(g->sim, sim_recv_ring_r(),
299 sim_recv_ring_status_valid_f() |
300 sim_recv_ring_target_phys_pci_coherent_f() |
301 sim_recv_ring_size_4kb_f() |
302 sim_recv_ring_addr_lo_f(phys >> PAGE_SHIFT));
303
304 g->sim->remove_support = nvgpu_remove_sim_support;
305 g->sim->esc_readl = nvgpu_sim_esc_readl;
306 return 0;
307
308 fail:
309 nvgpu_free_sim_support(g);
310 return err;
311}