aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/posix/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/os/posix/io.c')
-rw-r--r--include/os/posix/io.c371
1 files changed, 0 insertions, 371 deletions
diff --git a/include/os/posix/io.c b/include/os/posix/io.c
deleted file mode 100644
index 8369e73..0000000
--- a/include/os/posix/io.c
+++ /dev/null
@@ -1,371 +0,0 @@
1/*
2 * Copyright (c) 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/io.h>
24#include <nvgpu/io_usermode.h>
25#include <nvgpu/bug.h>
26
27#include <nvgpu/posix/io.h>
28
29#include "os_posix.h"
30
31
32/*
33 * This function sets the IO callbacks to the passed set of callbacks. It
34 * returns the value of the old IO callback struct pointer. This function
35 * cannot fail.
36 *
37 * This is expected to be called from modules to set up their IO interaction.
38 */
39struct nvgpu_posix_io_callbacks *nvgpu_posix_register_io(
40 struct gk20a *g,
41 struct nvgpu_posix_io_callbacks *io_callbacks)
42{
43 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
44 struct nvgpu_posix_io_callbacks *old_io = p->callbacks;
45
46 p->callbacks = io_callbacks;
47
48 return old_io;
49}
50
51void nvgpu_writel(struct gk20a *g, u32 r, u32 v)
52{
53 struct nvgpu_posix_io_callbacks *callbacks =
54 nvgpu_os_posix_from_gk20a(g)->callbacks;
55
56 struct nvgpu_reg_access access = {
57 .addr = r,
58 .value = v
59 };
60
61 if (callbacks == NULL || callbacks->writel == NULL) {
62 BUG();
63 }
64
65 callbacks->writel(g, &access);
66}
67
68void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v)
69{
70 BUG();
71}
72
73u32 nvgpu_readl(struct gk20a *g, u32 r)
74{
75 struct nvgpu_posix_io_callbacks *callbacks =
76 nvgpu_os_posix_from_gk20a(g)->callbacks;
77
78 struct nvgpu_reg_access access = {
79 .addr = r,
80 .value = 0L
81 };
82
83 if (callbacks == NULL || callbacks->readl == NULL) {
84 BUG();
85 }
86
87 callbacks->readl(g, &access);
88
89 return access.value;
90}
91
92void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v)
93{
94 BUG();
95}
96
97u32 __nvgpu_readl(struct gk20a *g, u32 r)
98{
99 struct nvgpu_posix_io_callbacks *callbacks =
100 nvgpu_os_posix_from_gk20a(g)->callbacks;
101
102 struct nvgpu_reg_access access = {
103 .addr = r,
104 .value = 0L
105 };
106
107 if (callbacks == NULL || callbacks->__readl == NULL) {
108 BUG();
109 }
110
111 callbacks->__readl(g, &access);
112
113 return access.value;
114}
115
116void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v)
117{
118 struct nvgpu_posix_io_callbacks *callbacks =
119 nvgpu_os_posix_from_gk20a(g)->callbacks;
120
121 struct nvgpu_reg_access access = {
122 .addr = b,
123 .value = v
124 };
125
126 if (callbacks == NULL || callbacks->bar1_writel == NULL) {
127 BUG();
128 }
129
130 callbacks->bar1_writel(g, &access);
131}
132
133u32 nvgpu_bar1_readl(struct gk20a *g, u32 b)
134{
135 struct nvgpu_posix_io_callbacks *callbacks =
136 nvgpu_os_posix_from_gk20a(g)->callbacks;
137
138 struct nvgpu_reg_access access = {
139 .addr = b,
140 .value = 0L
141 };
142
143 if (callbacks == NULL || callbacks->bar1_readl == NULL) {
144 BUG();
145 }
146
147 callbacks->bar1_readl(g, &access);
148
149 return access.value;
150}
151
152void nvgpu_usermode_writel(struct gk20a *g, u32 r, u32 v)
153{
154 struct nvgpu_posix_io_callbacks *callbacks =
155 nvgpu_os_posix_from_gk20a(g)->callbacks;
156
157 struct nvgpu_reg_access access = {
158 .addr = r,
159 .value = v
160 };
161
162 if (callbacks == NULL || callbacks->usermode_writel == NULL) {
163 BUG();
164 }
165
166 callbacks->usermode_writel(g, &access);
167}
168
169bool nvgpu_io_exists(struct gk20a *g)
170{
171 return false;
172}
173
174bool nvgpu_io_valid_reg(struct gk20a *g, u32 r)
175{
176 return false;
177}
178
179void nvgpu_posix_io_init_reg_space(struct gk20a *g)
180{
181 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
182
183 p->recording = false;
184 p->error_code = 0;
185 nvgpu_init_list_node(&p->reg_space_head);
186 nvgpu_init_list_node(&p->recorder_head);
187}
188
189int nvgpu_posix_io_get_error_code(struct gk20a *g)
190{
191 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
192
193 return p->error_code;
194}
195
196void nvgpu_posix_io_reset_error_code(struct gk20a *g)
197{
198 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
199
200 p->error_code = 0;
201}
202
203/*
204 * Add a new register space to the list of spaces, defined by a base
205 * address and a size.
206 */
207int nvgpu_posix_io_add_reg_space(struct gk20a *g, u32 base, u32 size)
208{
209 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
210 struct nvgpu_posix_io_reg_space *new_reg_space =
211 nvgpu_kzalloc(g, sizeof(struct nvgpu_posix_io_reg_space));
212
213 if (new_reg_space == NULL) {
214 return -ENOMEM;
215 }
216
217 new_reg_space->base = base;
218 new_reg_space->size = size;
219
220 new_reg_space->data = nvgpu_vzalloc(g, size);
221 if (new_reg_space->data == NULL) {
222 return -ENOMEM;
223 }
224
225 nvgpu_list_add_tail(&new_reg_space->link, &p->reg_space_head);
226 return 0;
227}
228
229void nvgpu_posix_io_delete_reg_space(struct gk20a *g, u32 base)
230{
231 struct nvgpu_posix_io_reg_space *reg_space =
232 nvgpu_posix_io_get_reg_space(g, base);
233 if (reg_space == NULL) {
234 /* Invalid space, or already de-allocated */
235 return;
236 }
237 nvgpu_list_del(&reg_space->link);
238 nvgpu_vfree(g, reg_space->data);
239 nvgpu_kfree(g, reg_space);
240}
241
242/*
243 * Lookup a register space from a given address. If no register space is found
244 * this is a bug similar to a translation fault.
245 */
246struct nvgpu_posix_io_reg_space *nvgpu_posix_io_get_reg_space(struct gk20a *g,
247 u32 addr)
248{
249 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
250 struct nvgpu_posix_io_reg_space *reg_space;
251
252 nvgpu_list_for_each_entry(reg_space, &p->reg_space_head,
253 nvgpu_posix_io_reg_space, link) {
254 u32 offset = addr - reg_space->base;
255
256 if ((addr >= reg_space->base) && (offset <= reg_space->size)) {
257 return reg_space;
258 }
259 }
260 p->error_code = -EFAULT;
261 nvgpu_err(g, "ABORT for address 0x%x", addr);
262 return NULL;
263}
264
265void nvgpu_posix_io_writel_reg_space(struct gk20a *g, u32 addr, u32 data)
266{
267 struct nvgpu_posix_io_reg_space *space =
268 nvgpu_posix_io_get_reg_space(g, addr);
269
270 if (space != NULL) {
271 u32 offset = (addr - space->base) / ((u32) sizeof(u32));
272
273 *(space->data + offset) = data;
274 }
275}
276
277u32 nvgpu_posix_io_readl_reg_space(struct gk20a *g, u32 addr)
278{
279 struct nvgpu_posix_io_reg_space *space =
280 nvgpu_posix_io_get_reg_space(g, addr);
281
282 if (space != NULL) {
283 u32 offset = (addr - space->base) / ((u32) sizeof(u32));
284
285 return *(space->data + offset);
286 } else {
287 return 0;
288 }
289}
290
291/*
292 * Start recording register writes. If this function is called again,
293 * it will free all previously recorded events.
294 */
295void nvgpu_posix_io_start_recorder(struct gk20a *g)
296{
297 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
298 struct nvgpu_posix_io_reg_access *ptr;
299
300 /* If list already has events, delete them all */
301 if (p->recording == true) {
302 while (!nvgpu_list_empty(&p->recorder_head)) {
303 ptr = nvgpu_list_first_entry(&p->recorder_head,
304 nvgpu_posix_io_reg_access, link);
305 nvgpu_list_del(&ptr->link);
306 nvgpu_kfree(g, ptr);
307 }
308 }
309 p->recording = true;
310}
311
312void nvgpu_posix_io_record_access(struct gk20a *g,
313 struct nvgpu_reg_access *access)
314{
315 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
316
317 if (p->recording == true) {
318 struct nvgpu_posix_io_reg_access *new_event = nvgpu_kzalloc(g,
319 sizeof(struct nvgpu_posix_io_reg_access));
320 (void) memcpy(&(new_event->access), access,
321 sizeof(struct nvgpu_reg_access));
322 nvgpu_list_add_tail(&new_event->link, &p->recorder_head);
323 }
324}
325
326/*
327 * Take an array of accesses and compare to the recorded sequence. Returns true
328 * if the array matches the recorded sequence.
329 * If strict mode is false, this function allows extra accesses to be present
330 * in the recording.
331 */
332bool nvgpu_posix_io_check_sequence(struct gk20a *g,
333 struct nvgpu_reg_access *sequence, u32 size, bool strict)
334{
335 struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
336 struct nvgpu_posix_io_reg_access *ptr;
337 u32 i = 0;
338
339 if (p->recording == false) {
340 return false;
341 }
342
343 nvgpu_list_for_each_entry(ptr, &p->recorder_head,
344 nvgpu_posix_io_reg_access, link) {
345 if ((sequence[i].addr == ptr->access.addr) &&
346 (sequence[i].value == ptr->access.value)) {
347 i++;
348 } else {
349 if (strict == true) {
350 return false;
351 }
352 }
353 }
354
355 if (i != size) {
356 /* Either missing or too many accesses */
357 return false;
358 }
359
360 if (&ptr->link == &p->recorder_head) {
361 /* Identical match */
362 return true;
363 }
364
365 /* Not an identical match */
366 if (strict) {
367 return false;
368 } else {
369 return true;
370 }
371}